/** * @file i2c.c * @author chipsea * @brief * @version 0.1 * @date 2020-11-30 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd. * @note */ /******************************************************************************* * @file i2c.c * @brief Contains all functions support for i2c driver * @version 0.0 * @date 25. Oct. 2017 * @author qing.han * * *******************************************************************************/ /******************************************************************************* *@ Module : pre-compiler *@ Description : NULL *******************************************************************************/ #define _I2C_CMD_ /******************************************************************************* *@ Module : Includes *@ Description : None *******************************************************************************/ #include "rom_sym_def.h" #include "types.h" #include "gpio.h" #include "i2c.h" #include "clock.h" #include "log.h" #include "error.h" #include "OSAL.h" #include "pwrmgr.h" #define I2C_OP_TIMEOUT 100 //100ms for an Byte operation extern uint32_t pclk; /************************************************************************************** * @fn hal_master_send_read_cmd * * @brief This function process for master send read command;It's vaild when the chip act as master * * input parameters * * @param uint8_t len: read length * * output parameters * * @param None. * * @return None. **************************************************************************************/ static void hal_master_send_read_cmd(void* pi2c, uint8_t len){ uint8_t i; AP_I2C_TypeDef * pi2cdev = (AP_I2C_TypeDef *)pi2c; for(i=0;iIC_DATA_CMD = data; //data } /************************************************************************************** * @fn hal_i2c_send * * @brief This function process for send a serial(programe length) data by i2c interface * * input parameters * * @param unsigned char* str: send data(string) * uint32_t len: send length * * output parameters * * @param None. * * @return None. **************************************************************************************/ int hal_i2c_send(void* pi2c, uint8_t* str,uint8_t len) { uint8_t i; AP_I2C_TypeDef * pi2cdev = (AP_I2C_TypeDef *)pi2c; if(pi2cdev != AP_I2C0 && pi2cdev != AP_I2C1){ return ERR_INVALID_PARAM; } for(i=0;iIC_INTR_STAT; //st = pi2cdev->IC_RAW_INTR_STAT; while(1){ cnt++; if(pi2cdev->IC_RAW_INTR_STAT&0x200)//check tx empty break; I2C_CHECK_TOUT(to, I2C_OP_TIMEOUT, "hal_i2c_wait_tx_completed TO\n"); } //LOG("I2c Tx empty:%x, %x\n", st0,st); return SUCCESS; } void* hal_i2c_init(i2c_dev_t dev, I2C_CLOCK_e i2c_clock_rate) { int pclk = clk_get_pclk(); AP_I2C_TypeDef * pi2cdev = NULL; if(dev == I2C_0){ pi2cdev = AP_I2C0; hal_clk_gate_enable(MOD_I2C0); } else if(dev == I2C_1){ pi2cdev = AP_I2C1; hal_clk_gate_enable(MOD_I2C1); } else{ return NULL; } pi2cdev->IC_ENABLE=0; pi2cdev->IC_CON=0x61; if(i2c_clock_rate==I2C_CLOCK_100K){ pi2cdev->IC_CON= ((pi2cdev->IC_CON) & 0xfffffff9)|(0x01 << 1); if(pclk==16000000){ pi2cdev->IC_SS_SCL_HCNT=70; //16 pi2cdev->IC_SS_SCL_LCNT=76; //32) }else if(pclk==32000000){ pi2cdev->IC_SS_SCL_HCNT=148; //16 pi2cdev->IC_SS_SCL_LCNT=154; //32) }else if(pclk==48000000){ pi2cdev->IC_SS_SCL_HCNT=230; //16 pi2cdev->IC_SS_SCL_LCNT=236; //32) }else if(pclk==64000000){ pi2cdev->IC_SS_SCL_HCNT=307; //16 pi2cdev->IC_SS_SCL_LCNT=320; //32) }else if(pclk==96000000){ pi2cdev->IC_SS_SCL_HCNT=460; //16 pi2cdev->IC_SS_SCL_LCNT=470; //32) } }else if(i2c_clock_rate==I2C_CLOCK_400K){ pi2cdev->IC_CON= ((pi2cdev->IC_CON) & 0xfffffff9)|(0x02 << 1); if(pclk==16000000){ pi2cdev->IC_FS_SCL_HCNT=10; //16 pi2cdev->IC_FS_SCL_LCNT=17; //32) }else if(pclk==32000000){ pi2cdev->IC_FS_SCL_HCNT=30; //16 pi2cdev->IC_FS_SCL_LCNT=35; //32) }else if(pclk==48000000){ pi2cdev->IC_FS_SCL_HCNT=48; //16 pi2cdev->IC_FS_SCL_LCNT=54; //32) }else if(pclk==64000000){ pi2cdev->IC_FS_SCL_HCNT=67; //16 pi2cdev->IC_FS_SCL_LCNT=75; //32) }else if(pclk==96000000){ pi2cdev->IC_FS_SCL_HCNT=105; //16 pi2cdev->IC_FS_SCL_LCNT=113; //32) } } pi2cdev->IC_TAR = I2C_MASTER_ADDR_DEF; pi2cdev->IC_INTR_MASK=0; pi2cdev->IC_RX_TL=0x0; pi2cdev->IC_TX_TL=0x1; pi2cdev->IC_ENABLE=1; return (void*)pi2cdev; } int hal_i2c_deinit(void* pi2c){ AP_I2C_TypeDef * pi2cdev = (AP_I2C_TypeDef *)pi2c; if(pi2cdev == AP_I2C0){ pi2cdev->IC_ENABLE=0; hal_clk_gate_disable(MOD_I2C0); } else if(pi2cdev == AP_I2C1){ pi2cdev->IC_ENABLE=0; hal_clk_gate_enable(MOD_I2C1); } else{ return ERR_INVALID_PARAM; } return SUCCESS; } /************************************************************************************** * @fn hal_i2c_pin_init * * @brief This function process for i2c pin initial(2 lines);You can use two i2c,i2c0 and i2c1,should programe by USE_AP_I2CX * * input parameters * * @param GpioPin_t pin_sda: define sda_pin * GpioPin_t pin_clk: define clk_pin * * output parameters * * @param None. * * @return None. **************************************************************************************/ int hal_i2c_pin_init(i2c_dev_t dev, GpioPin_t pin_sda, GpioPin_t pin_clk){ if(dev == I2C_0){ HalGpioFmuxConfig(pin_clk, FMUX_IIC0_SCL); HalGpioFmuxConfig(pin_sda, FMUX_IIC0_SDA); } else if(dev == I2C_1){ HalGpioFmuxConfig(pin_clk, FMUX_IIC1_SCL); HalGpioFmuxConfig(pin_sda, FMUX_IIC1_SDA); } else{ return ERR_INVALID_PARAM; } HalGpioPupdConfig(pin_sda,GPIO_PULL_UP_S); HalGpioPupdConfig(pin_clk,GPIO_PULL_UP_S); if(dev == I2C_0){ hal_clk_gate_enable(MOD_I2C0); } else if(dev == I2C_1){ hal_clk_gate_enable(MOD_I2C1); } return SUCCESS; } int hal_i2c_tx_start(void* pi2c) { AP_I2C_TypeDef * pi2cdev = (AP_I2C_TypeDef *)pi2c; if(pi2cdev != AP_I2C0 && pi2cdev != AP_I2C1){ return ERR_INVALID_PARAM; } pi2cdev->IC_ENABLE=1; return SUCCESS; } /************************************************************************************** * @fn hal_i2c_addr_update * * @brief This function process for tar update * * input parameters * * @param uint8_t addr: address * * output parameters * * @param None. * * @return None. **************************************************************************************/ int hal_i2c_addr_update(void* pi2c, uint8_t addr){ AP_I2C_TypeDef * pi2cdev = (AP_I2C_TypeDef *)pi2c; if(pi2cdev != AP_I2C0 && pi2cdev != AP_I2C1){ return ERR_INVALID_PARAM; } pi2cdev->IC_ENABLE=0; pi2cdev->IC_TAR = addr; pi2cdev->IC_ENABLE=0; return SUCCESS; } int _hal_i2c_read_s(void* pi2c, uint8_t slave_addr, uint8_t reg, uint8_t* data, uint8_t size) { I2C_INIT_TOUT(to); AP_I2C_TypeDef * pi2cdev = (AP_I2C_TypeDef *)pi2c; if(pi2cdev != AP_I2C0 && pi2cdev != AP_I2C1){ return ERR_INVALID_PARAM; } hal_i2c_addr_update(pi2c, slave_addr); HAL_ENTER_CRITICAL_SECTION(); hal_i2c_tx_start(pi2c); _hal_i2c_send_byte(pi2c, reg); hal_master_send_read_cmd(pi2c, size); HAL_EXIT_CRITICAL_SECTION(); while(1){ if(I2C_RX_FIFO_NOT_EMPTY(pi2cdev)){ *data = (pi2cdev->IC_DATA_CMD&0xff); data++; size --; if(size == 0) break; } I2C_CHECK_TOUT(to, I2C_OP_TIMEOUT*size, "I2C RD TO\n"); } return SUCCESS; } int hal_i2c_read( void* pi2c, uint8_t slave_addr, uint8_t reg, uint8_t* data, uint8_t size) { uint8_t cnt; int ret = SUCCESS; AP_I2C_TypeDef * pi2cdev = (AP_I2C_TypeDef *)pi2c; if(pi2cdev != AP_I2C0 && pi2cdev != AP_I2C1){ return ERR_INVALID_PARAM; } while(size){ cnt = (size >7) ? 7 : size; size -= cnt; ret = _hal_i2c_read_s(pi2c, slave_addr, reg, data , cnt); if(ret != SUCCESS) break; data += cnt; } return ret; }