gd32l23cct6芯片在硬件i2c读写过程中会偶尔出现write函数在TI标志位超时跳出,read函数在RBNE标志位超时跳出,TIMEOUT时间测试200ms+,在这两个标志位超时异常跳出导致i2c通信时序缺少stop位,bsy标志位一直位1,i2c再也无法继续通信,一定要通过复位i2c外设才能解决。硬件i2c驱动代码去下
int gd32_i2c_write(unsigned char bus, unsigned short addr, unsigned char *data, unsigned int data_len)
{
drv_i2c_mgr_t *i2c_mgr = NULL;
unsigned int timeout = DRV_I2C_TIME_OUT;
unsigned int idx;
if (bus >= DRV_I2C_BUS_MAX)
{
return -1;
}
i2c_mgr = &s_st_i2c_mgr[bus];
if (0 == i2c_mgr->is_init)
{
return -1;
}
/* wait until I2C bus is idle */
timeout = DRV_I2C_TIME_OUT;
i2c_master_addressing(i2c_mgr->periph, addr<<1, I2C_MASTER_TRANSMIT);
i2c_address_config(i2c_mgr->periph, DRV_I2C_OWN_ADDRESS7, I2C_ADDFORMAT_7BITS);
/* len not include addr byte */
i2c_transfer_byte_number_config(i2c_mgr->periph, data_len);
while(i2c_flag_get(i2c_mgr->periph, I2C_FLAG_I2CBSY))
{
if ((timeout--) == 0)
{
return -1;
}
}
/* send a start condition to I2C bus */
timeout = DRV_I2C_TIME_OUT;
i2c_start_on_bus(i2c_mgr->periph);
/* wait until the transmit data buffer is empty */
I2C_STAT(i2c_mgr->periph) |= I2C_STAT_TBE;
while(!i2c_flag_get(i2c_mgr->periph, I2C_FLAG_TBE))
{
if ((timeout--) == 0)
{
return -1;
}
}
for(idx = 0; idx < data_len; idx++)
{
/* data transmission */
timeout = DRV_I2C_TIME_OUT;
i2c_data_transmit(i2c_mgr->periph, data[idx]);
while(!i2c_flag_get(i2c_mgr->periph, I2C_FLAG_TI))
{
if ((timeout--) == 0)
{
LOG_DIRECT_ERR("ti\r\n");
return -1;
}
}
}
timeout = DRV_I2C_TIME_OUT;
while(!i2c_flag_get(i2c_mgr->periph, I2C_FLAG_TC))
{
if ((timeout--) == 0)
{
return -1;
}
}
/* send a stop condition to I2C bus */
i2c_stop_on_bus(i2c_mgr->periph);
/* wait until stop condition generate */
while(!i2c_flag_get(i2c_mgr->periph, I2C_FLAG_STPDET))
{
if ((timeout--) == 0)
{
return -1;
}
}
/* clear the STPDET bit */
i2c_flag_clear(i2c_mgr->periph, I2C_FLAG_STPDET);
return 0;
}
int gd32_i2c_read(unsigned char bus, unsigned short addr, unsigned char *data, unsigned int data_len)
{
drv_i2c_mgr_t *i2c_mgr = NULL;
unsigned int timeout = DRV_I2C_TIME_OUT;
unsigned int idx;
if (bus >= DRV_I2C_BUS_MAX)
{
return -1;
}
i2c_mgr = &s_st_i2c_mgr[bus];
if (0 == i2c_mgr->is_init)
{
/* I2C init fail ,value invalid */
return -1;
}
/* wait until I2C bus is idle */
i2c_master_addressing(i2c_mgr->periph, addr<<1, I2C_MASTER_RECEIVE);
i2c_address_config(i2c_mgr->periph, addr<<1, I2C_ADDFORMAT_7BITS);
i2c_transfer_byte_number_config(i2c_mgr->periph, data_len);
timeout = DRV_I2C_TIME_OUT;
while(i2c_flag_get(i2c_mgr->periph, I2C_FLAG_I2CBSY))
{
if ((timeout--) == 0)
{
return -1;
}
}
/* send a start condition to I2C bus */
i2c_start_on_bus(i2c_mgr->periph);
for(idx = 0; idx < data_len; idx++)
{
/* wait until the RBNE bit is set */
timeout = DRV_I2C_TIME_OUT;
while(!i2c_flag_get(i2c_mgr->periph, I2C_FLAG_RBNE))
{
if ((timeout--) == 0)
{
LOG_DIRECT_ERR("rbne\r\n");
return -1;
}
}
/* read a data from I2C_DATA */
data[idx] = i2c_data_receive(i2c_mgr->periph);
}
while(!i2c_flag_get(i2c_mgr->periph, I2C_FLAG_TC))
{
timeout = DRV_I2C_TIME_OUT;
if ((timeout--) == 0)
{
return -1;
}
}
/* send a stop condition to I2C bus */
i2c_stop_on_bus(i2c_mgr->periph);
/* wait until stop condition generate */
while(!i2c_flag_get(i2c_mgr->periph, I2C_FLAG_STPDET))
{
timeout = DRV_I2C_TIME_OUT;
if ((timeout--) == 0)
{
return -1;
}
}
/* clear the STPDET bit */
i2c_flag_clear(i2c_mgr->periph, I2C_FLAG_STPDET);
return 0;
}
|