cancel
Showing results for 
Search instead for 
Did you mean: 

I2C getting stuck in HAL_I2C_STATE_BUSY_TX state

THML
Associate II

Hello,

I'm currently working with a STM32F411RC chip in a custom board and using I2C to communicate with some peripherals (namely memory and ADCs). I decided to use I2C with DMA, but it wasn't working, so I switched to I2C with interruptions.

My setup is done exactly as in the cube examples. The important part of the code follows:

void I2C_Start(void)
{     
        // Start I2C hardware.
        main_i2c.scl = MCU_InitGPIO(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_Type_AF_OD, GPIO_Speed_Max, GPIO_PuPd_NoPull);
        main_i2c.sda = MCU_InitGPIO(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_Type_AF_OD, GPIO_Speed_Max, GPIO_PuPd_NoPull);
        MCU_SetGPIOAlternativeFuction(main_i2c.sda, GPIO_Alt_I2C_1);
        MCU_SetGPIOAlternativeFuction(main_i2c.scl, GPIO_Alt_I2C_1);
        
        main_i2c.i2c.Instance             = I2C1;
  
        main_i2c.i2c.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;
        main_i2c.i2c.Init.ClockSpeed      = 400000;
        main_i2c.i2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
        main_i2c.i2c.Init.DutyCycle       = I2C_DUTYCYCLE_16_9;
        main_i2c.i2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
        main_i2c.i2c.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLE;
        main_i2c.i2c.Init.OwnAddress1     = I2C_MASTER_DEVICE_ADDRESS;
        main_i2c.i2c.Init.OwnAddress2     = 0xFE;
 
        if(HAL_I2C_Init(&main_i2c.i2c) != HAL_OK)
        {
                ERROR_Add(ERR_I2C_UNABLE_TO_INITIALIZE);
        }
        
        // Set interruption functions
        irq_functions_buffer[I2C1_ER_IRQn] = I2C_ERIRQ;
        irq_structures_buffer[I2C1_ER_IRQn] = &main_i2c.i2c;
        irq_functions_buffer[I2C1_EV_IRQn] = I2C_EVIRQ;
        irq_structures_buffer[I2C1_EV_IRQn] = &main_i2c.i2c;
}
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
        /* Enable I2C1 clock */
        __HAL_RCC_I2C1_CLK_ENABLE();
 
        /*##-5- Configure the NVIC for I2C #########################################*/   
        /* NVIC for I2C1 */  
        NVIC_SetPriority(I2C1_ER_IRQn, 1);
        NVIC_EnableIRQ(I2C1_ER_IRQn);
        NVIC_SetPriority(I2C1_EV_IRQn, 2);
        NVIC_EnableIRQ(I2C1_EV_IRQn);
}

There is a pull-up of 10kOhms in both SDA and SCL lines. The I2C_ERIRQ and I2C_EVIRQ functions are equal to, respectively, HAL_I2C_ER_IRQHandler and HAL_I2C_EV_IRQHandler.

The I2C initially works fine and the MCU is perfectly capable of communicating with the peripherals. The issue is that, eventually, the I2C gets stuck in the HAL_I2C_STATE_BUSY_TX state. Since i'm using IAR, I can observe the state of the I2C register and the internal object, as follows:

0693W00000QNQQFQA5.bmpand

0693W00000QNQQKQA5.bmpThe interesting thing is that the registers indicate that a transmission operation is ongoing, but in the internal object XferCount is zero, indicating that everything was transferred. It's like the closing steps never happened (and I checked the interruption with a breakpoint and it is never called).

Just one more bit of information: if I use the blocking I2C functions (with polling), everything works fine.

1 REPLY 1
Amel NASRI
ST Employee

Hi @THML​ ,

Is I2C_Start() the only location where SCL & SDA lines are configured?

Please make sure that GPIO configuration is done before I2C clock enabling.

-Amel

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.