2021-07-28 07:55 AM
STM32L432
I'm using interrupt mode HAL driver and the i2c slave responses successfully for many transactions but then will randomly hang. Here is the code I'm using, its fairly simple.
volatile uint8_t i2cbuf[2] = {0, 0};
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x10909CEC;
hi2c1.Init.OwnAddress1 = 84;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
i2cbuf[0]++;
i2cbuf[1]++;
if (hi2c->Instance == I2C1)
{
if (HAL_I2C_Slave_Seq_Transmit_IT(hi2c, (uint8_t *)i2cbuf, 2, I2C_LAST_FRAME) != HAL_OK)
{
}
}
}
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
HAL_I2C_EnableListen_IT(hi2c);
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
uint32_t err = HAL_I2C_GetError(hi2c);
if (err != HAL_I2C_ERROR_NONE)
{
printf("error=%x\n", err);
i2c_reinit();
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_I2C1_Init();
HAL_I2C_EnableListen_IT(&hi2c1);
while(1){
}
}
Any suggestions? The i2c slave's only required operation is to transmit 2 bytes
Also the i2c bus is low after the slave hangs
2021-08-03 02:23 AM
Hi @YPear.1 ,
if SCL is held low, it may indicate clock stretching.
Slaves are using clock stretching to gain time to respond masters.
Use debugger and check I2C register flags and the hi2c structure to see what's going on.
J
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2021-08-03 08:46 AM
Clock stretching is enabled, but the slave does not have to stretch forever. As you can tell, the code is pretty simple but eventually hangs after a few hundred transactions.
2021-08-03 08:47 AM
In polling mode, the slave does not hang this just affects IT mode.
2021-08-03 09:18 AM
Hi @YPear.1 ,
yes, there should be a timeout set on stretching.
But when you enable debug interface and peek at the state when the hang appears, you should see what's the handle state and what's the state of the I2C IP registers. It should be pretty straightforward from there. I know from experience the HAL based IT operation can be very reliable when all corners are covered.
J
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2021-08-03 09:23 AM
You are saying if I set a clock stretch timeout this will fix the problem?
2021-08-03 09:28 AM
There doesn't seem to be a way through the HAL to limit how long clock stretching can occur.