2020-07-15 12:55 PM
I2C Error trapping
I am using the STM32WB in master mode, polling a single LSM303AGR accelerometer. Using the HAL transmit routine as follows:
if(hi2c1.State == HAL_I2C_STATE_READY)
{
/* Now send the device address and register to be read with 1 sec delay max*/
while(HAL_I2C_Master_Transmit(&hi2c1, DEVICE_ADDR, i2cbuffer, 1, 1000) != HAL_OK)
{
/* Error_Handler() function is called when Timeout error occurs.
When Acknowledge failure occurs (Slave doesn't acknowledge its address)
Master restarts communication */
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
errorcount = 20;
Error_Handler();
}
}
/* Now get the return byte of the register in i2cbuffer[0, 1] with 1 sec delay max*/
while(HAL_I2C_Master_Receive(&hi2c1, DEVICE_ADDR, i2cbuffer, 2, 1000) != HAL_OK)
{
/* Error_Handler() function is called when Timeout error occurs.
When Acknowledge failure occurs (Slave doesn't acknowledge it's address)
Master restarts communication */
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
errorcount = 21;
Error_Handler();
}
}
tmp = i2cbuffer[1];
tmp = (tmp<<8) & 0x0000ff00;
tmp = (tmp | i2cbuffer[0]) & 0x0000ffff;
rtnval = (int16_t)tmp;
}
The last two variables in the debug window are obtained as follows at the start of the Error_Handler() routine:
uint32_t itflags = READ_REG(hi2c1.Instance->ISR);
uint32_t itsources = READ_REG(hi2c1.Instance->CR1);
Not interrupt, just polling. Every so often, it jumps to the Error_Handler() routine which just toggles an LED in a while(1) loop indefinitely. I am trying to determine the cause of this error.
Attached is a picture of the debugger screen showing the i2c instance and all relevant variables. From this picture, can anyone help me determine the cause of the error? It's taking 2 days of runtime to catch this so any help would be appreciated.
Thanks
2020-07-15 01:50 PM
Your hi2c1.ErrorCode value is 32 which matches up with a timeout error.
#define HAL_I2C_ERROR_TIMEOUT (0x00000020U) /*!< Timeout error */
So that is the reason. It's probably getting set in I2C_WaitOnFlagUntilTimeout which is called in two different places in HAL_I2C_Master_Transmit.
Potential cause is that the I2C bus is busy due to a misbehaving device. Use a logic analyzer to find out more info.