STMicroelectronics / STM32CubeH7

STM32Cube MCU Full Package for the STM32H7 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
https://www.st.com/en/embedded-software/stm32cubeh7.html
Other
518 stars 308 forks source link

Bug : I2C TX IT flag isn't disable at the end of HAL_I2C_Mem_Read_IT() #270

Closed EdouardMALOT closed 1 year ago

EdouardMALOT commented 1 year ago

During HAL_I2C_Mem_Read_IT() the I2C TX interrupt is set but not disable at the end of transfert, which may cause the following bug:

If we're using a preemptive RTOS (FreeRTOS, ThreadX...) and if RTOS schedule at that time : image

  1. I2C transfert is started. (Note : hi2c isn't unlocked yet).

  2. At the end of transfert, I2C TX interrupt trig and we have the following calls : a. HAL_I2V_EV_IRQHandler() b. I2C_Mem_IST_IR() c. _HAL_LOCK(hi2c)

Because I2C is locked, _HAL_LOCK() return HAL_BUSY, without clearing any flags

image

image

The results is a dead lock in I2C interrupt : HAL_I2V_EV_IRQHandler() => I2C_Mem_IST_IR() => _HAL_LOCK() => HAL_I2V_EV_IRQHandler() => I2C_Mem_IST_IR()...

HBOSTM commented 1 year ago

Hello @EdouardMALOT ,

Thank you for the report, could you please try to make these modifications in stm32h7xx_hal_i2c.c: here


I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);

here

    I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);

here

      I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);

Add Disable/ Enable interrupts here

    /* Disable Interrupt related to address step */
    I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);

    /* Enable ERR, TC, STOP, NACK and RXI interrupts */
    I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);

Add Disable interrupts here

    /* Disable Interrupt related to address step */
    I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);

Add Disable/ Enable interrupts here

    /* Disable Interrupt related to address step */
    I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);

    /* Enable only Error and NACK interrupt for data transfer */
    I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);

here

  if ((tmpstate == HAL_I2C_STATE_BUSY_TX) || (tmpstate == HAL_I2C_STATE_BUSY_TX_LISTEN) ||
      (tmpstate == HAL_I2C_STATE_LISTEN))

Please get back to me if you have more details.

best Regards,

EdouardMALOT commented 1 year ago

Thanks for your quick reply. Yes, it solve the issue.

I've updated the PR with your suggestion.

HBOSTM commented 1 year ago

ST Internal Reference: 147666