#include "include.h" #define TRACE_EN 0 #if TRACE_EN #define TRACE(...) printf(__VA_ARGS__) #define TRACE_K(...) printk(__VA_ARGS__) #else #define TRACE(...) #define TRACE_K(...) #endif #if I2C_SW_EN //AT(.text.bsp.i2c) //static void bsp_i2c_delay(void) //{ // u8 delay = 60; // while (delay--) { // asm("nop"); // } //} #define bsp_i2c_delay() delay_us(5) //ACK: The transmitter releases the SDA line (HIGH->LOW) during the acknowledge clock pulse AT(.text.bsp.i2c) void bsp_i2c_tx_ack(void) { I2C_SDA_OUT(); I2C_SDA_L(); bsp_i2c_delay(); I2C_SCL_H(); bsp_i2c_delay(); I2C_SCL_L(); } AT(.text.bsp.i2c) bool bsp_i2c_rx_ack(void) { bool ret = false; I2C_SDA_IN(); bsp_i2c_delay(); I2C_SCL_H(); bsp_i2c_delay(); if (!I2C_SDA_IS_H()) { ret = true; } I2C_SCL_L(); return ret; } //NACK: The transmitter holds the SDA line (keep HIGH) during the acknowledge clock pulse AT(.text.bsp.i2c) void bsp_i2c_tx_nack(void) { I2C_SDA_OUT(); I2C_SDA_H(); bsp_i2c_delay(); I2C_SCL_H(); bsp_i2c_delay(); I2C_SCL_L(); } //START: A HIGH to LOW transition on the SDA line while SCL is HIGH is one such unique case. AT(.text.bsp.i2c) void bsp_i2c_start(void) { I2C_SDA_SCL_OUT(); I2C_SDA_SCL_H(); bsp_i2c_delay(); I2C_SDA_L(); bsp_i2c_delay(); I2C_SCL_L(); } //STOP: A LOW to HIGH transition on the SDA line while SCL is HIGH AT(.text.bsp.i2c) void bsp_i2c_stop(void) { I2C_SDA_OUT(); I2C_SDA_L(); bsp_i2c_delay(); I2C_SCL_H(); bsp_i2c_delay(); I2C_SDA_H(); } //tx 1byte AT(.text.bsp.i2c) void bsp_i2c_tx_byte(uint8_t dat) { u8 i; I2C_SDA_OUT(); for (i=0; i<8; i++) { if (dat & BIT(7)) { I2C_SDA_H(); } else { I2C_SDA_L(); } bsp_i2c_delay(); I2C_SCL_H(); bsp_i2c_delay(); I2C_SCL_L(); dat <<= 1; } } //rx 1byte AT(.text.bsp.i2c) uint8_t bsp_i2c_rx_byte(void) { u8 i, dat = 0; I2C_SDA_IN(); for (i=0; i<8; i++) { bsp_i2c_delay(); I2C_SCL_H(); bsp_i2c_delay(); dat <<= 1; if (I2C_SDA_IS_H()) { dat |= BIT(0); } I2C_SCL_L(); } return dat; } #endif //I2C_SW_EN #if I2C_HW_EN #if CHIP_PACKAGE_QFN40 static i2c_t __IIC0 = { .sfr = (i2c_sfr_t *)&IIC0CON0, .map = (i2c_map_t *)&FUNCMCON2, }; i2c_t *HW_IIC = &__IIC0; #else #if (CHIP_PACKAGE_SELECT == CHIP_5682C) static i2c_t __IIC0 = { .sfr = (i2c_sfr_t *)&IIC0CON0, .map = (i2c_map_t *)&FUNCMCON2, }; i2c_t *HW_IIC = &__IIC0; #else static i2c_t __IIC1 = { .sfr = (i2c_sfr_t *)&IIC1CON0, .map = (i2c_map_t *)&FUNCMCON2, }; i2c_t *HW_IIC = &__IIC1; #endif #endif void bsp_i2c0_lock(void) { os_i2c0_lock(100); } void bsp_i2c0_unlock(void) { os_i2c0_unlock(); } AT(.com_text.str) char str_tmp[] = ">>>bsp_i2c_isr\n"; AT(.com_text.isr.i2c) void bsp_i2c_isr(void) { if (HW_IIC->sfr->IICxCON0 & BIT(31)) { HW_IIC->sfr->IICxCON0 |= BIT(29); // clear pending HW_IIC->sfr->IICxCON0 &= ~BIT(1); // disable irq HW_IIC->sfr->IICxDMACNT = 0; // Disable DMA // printf(str_tmp); } } static u32 bsp_hw_i2c_config(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u32 dat) { TRACE("%s: cfg=%X dev=%X reg=%X\n", __FUNCTION__, i2c_cfg, dev_addr, reg_addr); HW_IIC->sfr->IICxCMDA = (u8)dev_addr | ((u32)(dev_addr >> 8)) << 24 | (u32)((u8)reg_addr) << 8 | (u32)((u8)(reg_addr >> 8)) << 16; HW_IIC->sfr->IICxCON1 = i2c_cfg; HW_IIC->sfr->IICxDATA = dat; HW_IIC->sfr->IICxCON0 |= BIT(28); // kick u32 ticks = tick_get(); while ((!(HW_IIC->sfr->IICxCON0 & BIT(31)))) { if (tick_check_expire(ticks, 20)) { TRACE("IIC ERROR[%x %x %x %x]\n", i2c_cfg, dev_addr, reg_addr, dat); return false; } } HW_IIC->sfr->IICxCON0 |= BIT(29); if (i2c_cfg & RDATA) { return HW_IIC->sfr->IICxDATA; } else { return true; } } void bsp_hw_i2c_tx_byte(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u32 data) { bsp_i2c0_lock(); bsp_hw_i2c_config(i2c_cfg, dev_addr, reg_addr, data); bsp_i2c0_unlock(); } void bsp_hw_i2c_tx_buf(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u8 *buf, u16 len) { int i; u32 cfg; if (buf == NULL || len == 0) { return; } bsp_i2c0_lock(); for (i = 0; i < len; i++) { cfg = WDATA; if (i == 0) { //收第1byte cfg |= i2c_cfg; } if (i == (len - 1)) { //收最后1byte cfg |= STOP_FLAG; } bsp_hw_i2c_config(cfg | DATA_CNT_1B, dev_addr, reg_addr, buf[i]); } bsp_i2c0_unlock(); } void bsp_hw_i2c_rx_buf(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u8 *buf, u16 len) { int i; u32 cfg; if (buf == NULL || len == 0) { return; } bsp_i2c0_lock(); for (i = 0; i < len; i++) { cfg = RDATA; if (i == 0) { //收第1byte cfg |= i2c_cfg; } if (i == (len - 1)) { //收最后1byte cfg |= STOP_FLAG | NACK; } buf[i] = bsp_hw_i2c_config(cfg | DATA_CNT_1B, dev_addr, reg_addr, 0); } bsp_i2c0_unlock(); } void i2c_init(void) { #if CHIP_PACKAGE_QFN40 CLKCON1 |= BIT(7); // x26m_clkdiv8 CLKGAT2 |= BIT(0); // en iic0 clk RSTCON0 |= BIT(3); // Release IIC0 #else #if (CHIP_PACKAGE_SELECT == CHIP_5682C) CLKCON1 |= BIT(7); // x26m_clkdiv8 CLKGAT2 |= BIT(0); // en iic0 clk RSTCON0 |= BIT(3); // Release IIC0 #else CLKCON1 |= BIT(8); // x26m_clkdiv8 CLKGAT2 |= BIT(1); // en iic1 clk RSTCON0 |= BIT(7); // Release IIC1 #endif #endif #if CHIP_PACKAGE_QFN40 GPIOEDIR |= BIT(4) | BIT(5); // SCL SDA GPIOEPU |= BIT(4) | BIT(5); GPIOEDE |= BIT(4) | BIT(5); GPIOEFEN |= BIT(4) | BIT(5); #else GPIOBDIR |= BIT(2) | BIT(1); // SCL SDA GPIOBPU |= BIT(2) | BIT(1); GPIOBDE |= BIT(2) | BIT(1); GPIOBFEN |= BIT(2) | BIT(1); #endif #if CHIP_PACKAGE_QFN40 HW_IIC->map->FUNCMCONx = (0xf << 8); HW_IIC->map->FUNCMCONx = (4 << 8); #else #if (CHIP_PACKAGE_SELECT == CHIP_5682C) HW_IIC->map->FUNCMCONx = (0xf << 8); HW_IIC->map->FUNCMCONx = (2 << 8); #else HW_IIC->map->FUNCMCONx = (0xf << 12); HW_IIC->map->FUNCMCONx = (2 << 12); #endif #endif HW_IIC->sfr->IICxCON0 = 1 << 0 | // IIC EN 0 << 1 | // IIC INT 0 << 2 | // IIC HOLD CNT [3:2] 20 << 4 | // IIC POSDIV [9:4] 1 << 10; // IIC WSCL_OPT delay_5ms(8); } #endif #if SECURITY_PAY_EN static i2c_t __IIC1 = { .sfr = (i2c_sfr_t *) &IIC1CON0, .map = (i2c_map_t *) &FUNCMCON2, }; i2c_t *HS_IIC = &__IIC1; void ctp_int_isr(void); AT(.text.bsp.i2c) void bsp_hs_i2c_tx_buf(u16 dev_addr, u8 *buf, u16 len) { u32 ticks; HS_IIC->sfr->IICxCMDA = (buf[0]<<8) | dev_addr; HS_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(10) | BIT(5) | BIT(4) | BIT(3); HS_IIC->sfr->IICxDMAADR = DMA_ADR(&buf[1]); HS_IIC->sfr->IICxDMACNT = ((len - 2) << 16) | BIT(1) |BIT(0); HS_IIC->sfr->IICxCON0 |= BIT(28); //KICK // printf("IICxCMDA: 0x%x, IICxDMAADR: 0x%x, IICxDMACNT: 0x%x, IICxCON0: 0x%x, IICxCON1: 0x%x\n", // HS_IIC->sfr->IICxCMDA, HS_IIC->sfr->IICxDMAADR, HS_IIC->sfr->IICxDMACNT, HS_IIC->sfr->IICxCON0, HS_IIC->sfr->IICxCON1); ticks = tick_get(); while (!(HS_IIC->sfr->IICxCON0 & BIT(31))) { if (tick_check_expire(ticks, 1000)) { printf("i2c_write time out ERROR\n"); return; } } HS_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending } AT(.text.bsp.i2c) void bsp_hs_i2c_rx_buf(u16 dev_addr, u8 *buf, u16 len) { u32 ticks; HS_IIC->sfr->IICxCMDA = dev_addr<<24; HS_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(9) | BIT(8) | BIT(7); HS_IIC->sfr->IICxDMAADR = DMA_ADR(buf); HS_IIC->sfr->IICxDMACNT = ((len - 1) << 16) | BIT(0); HS_IIC->sfr->IICxCON0 |= BIT(28); //KICK ticks = tick_get(); while (!(HS_IIC->sfr->IICxCON0 & BIT(31))) { if (tick_check_expire(ticks, 2000)) { printf("alipay_i2c_read time out ERROR\n"); return; } } HS_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending } AT(.text.bsp.i2c) void bsp_hs_i2c_rx_byte(u16 dev_addr, u8 *buf) { u32 ticks; HS_IIC->sfr->IICxCMDA = dev_addr<<24; HS_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(9) | BIT(8) | BIT(7); HS_IIC->sfr->IICxDMAADR = DMA_ADR(buf); HS_IIC->sfr->IICxDMACNT = BIT(0); HS_IIC->sfr->IICxCON0 |= BIT(28); //KICK ticks = tick_get(); while (!(HS_IIC->sfr->IICxCON0 & BIT(31))) { if (tick_check_expire(ticks, 50)) { printf("alipay_i2c_read time out ERROR\n"); return; } } HS_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending } #endif // SECURITY_PAY_EN AT(.text.bsp.i2c) void bsp_i2c_init(void) { #if I2C_SW_EN I2C_SDA_SCL_OUT(); I2C_SDA_H(); delay_5ms(2); #endif #if I2C_HW_EN i2c_init(); sys_irq_init(IRQ_I2C_VECTOR, 0, bsp_i2c_isr); #endif }