'STM32 HAL I2C Slave Interrupts Stop Working
I'm working with an STM32 (STM32F030K6TX) with the HAL Library. The STM32 functions as a slave device, all events are triggered by interrupts by events from the master MCU (Jetson Nano), interrupting the main loop running on the STM32. Upon resetting the device, the I2C works for a period of time, fulfilling several I2C requests before it stops working. When this happens the interrupts stop firing on the STM32 and all I2C reads/writes from the master MCU time out. The main loop is still active.
I noticed the HAL_I2C_GetError(&hi2c1) = HAL_I2C_ERROR_AF after these events. I tried to see if I could disable and re-enable the I2C to fix the interrupts, but it does not work. The code restores the state of the I2C to listening and clears the errors, but the interrupts still do not fire.
Does anyone know what might be the cause of these errors, and/or logic that can restore the I2C to a good state if this occurs?
MX_DMA_Init();
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC_Init();
MX_I2C1_Init();
MX_TIM3_Init();
MX_DMA_Init();
MX_TIM14_Init();
/* USER CODE BEGIN 2 */
if(HAL_I2C_EnableListen_IT(&hi2c1) != HAL_OK)
{
/* Transfer error in reception process */
Error_Handler();
}
transferState = 0;
while (1)
{
// 2) Respond to I2C Requests
if (transferState == 1) {
transferState = 2;
if (transferDirection == I2C_DIRECTION_TRANSMIT) {
// Receive a message from the Jetson, it's telling us to do something!
HAL_StatusTypeDef receiveState = HAL_I2C_Slave_Seq_Receive_DMA(&hi2c1, (uint8_t *)jetsonRequestRX, RXBUFFERSIZE, I2C_FIRST_AND_LAST_FRAME);
if(receiveState != HAL_OK)
{
Error_Handler();
}
} else {
// State is listen. This request fails... why?
if(HAL_I2C_Slave_Seq_Transmit_DMA(&hi2c1, (uint8_t *)jetsonTransmitPos, TXBUFFERSIZE, I2C_FIRST_AND_LAST_FRAME) != HAL_OK)
{
Error_Handler();
}
reset_calibration();
}
}
// This code attempts to detect the error condition and fix the I2C interrupts, but does not work
else if (transferState == 0) {
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) {
HAL_I2C_DeInit(&hi2c1);
HAL_I2C_Init(&hi2c1);
if(HAL_I2C_EnableListen_IT(&hi2c1) != HAL_OK)
{
/* Transfer error in reception process */
Error_Handler();
}
}
}
// *** ... Main loop ...
}
/* USER CODE BEGIN 4 */
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *i2cHandle) {
transferState = 0;
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *i2cHandle) {
jetsonRequest[0] = jetsonRequestRX[0];
jetsonRequest[1] = jetsonRequestRX[1];
transferState = 0;
}
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
/* restart listening for master requests */
if(HAL_I2C_EnableListen_IT(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
UNUSED(AddrMatchCode);
if(transferState == 0) {
transferState = 1;
transferDirection = TransferDirection;
}
}
Solution 1:[1]
the slave and listen hal is not very robust nor simple to use i had use it very rarely and with hard time always
i remenber the hal handle do have some internal state or alike that went wrong in rare or unexpected error or if you rd/Wr less data than initaly expected or you don't do "right" (wjat they expect you) on the callback. In this case it wan't restart operating correctly until state it's not hacked.
Try hanlding all hal error callback to see if their'ss any error thrown before it get screwd.
I don't have the f/W working in slave mode right now with me to help more :/
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Michel Sanches |
