cancel
Showing results for 
Search instead for 
Did you mean: 

Is there a bug in stm32f4xx_hal_i2c.c related to memory read/write?

ZBond
Associate

I believe there is a problem in stm32f4xx_hal_i2c.c. We using an STM32F412RE to communicate with an I2C accelerometer using the HAL_I2C_Mem_Read_IT() and HAL_I2C_Mem_Write_IT() functions.

Sometimes, when the system is very busy, we find that the HAL drivers get stuck endlessly handling interrupts caused by the BTF flag being set. This happens after the write of the target memory address. After it is written, we get a TXE interrupt. Here's an excerpt of HAL_I2C_EV_IRQHandler():

/* I2C in mode Transmitter -----------------------------------------------*/
    else if (I2C_CHECK_FLAG(sr2itflags, I2C_FLAG_TRA) != RESET)
    {
      /* Do not check buffer and BTF flag if a Xfer DMA is on going */
      if (READ_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN) != I2C_CR2_DMAEN)
      {
        /* TXE set and BTF reset -----------------------------------------------*/
        if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_TXE) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_BUF) != RESET) && (I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) == RESET))
        {
          I2C_MasterTransmit_TXE(hi2c);
        }
        /* BTF set -------------------------------------------------------------*/
        else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET))
        {
          I2C_MasterTransmit_BTF(hi2c);
        }
        else
        {
          /* Do nothing */
        }
      }
    }

Since TXE is set and BTF is not set, we will enter I2C_MasterTransmit_TXE() and generate a restart, which makes sense because the next step is to read data from the external device. This restart is needed to clear TXE.

The problem is at according to the STM32F412 reference manual, the BTF flag is set "...In transmission when a new byte should be sent and DR has not been written yet (TxE=1)."

So if it takes software a little too long to handle the TXE interrupt, then the BTF flag will be set. In that case, we'll never call I2C_MasterTransmit_TXE() and never send the restart that is needed to clear TXE (and BTF). Instead, I2C_MasterTransmit_BTF() will be called, but will exit without doing anything at all because we're not in the HAL_I2C_STATE_BUSY_TX state.

As a result, the hardware will stretch the clock, and lock up while processing BTF interrupts forever because it never does anything to clear the interrupt.

Thanks,

-Zac

4 REPLIES 4
Imen.D
ST Employee

Hello @ZBond​ ,

Which STM32CubeF4 is used ?

Can you please confirm that you are using the latest STM32CubeF4 v1.24.1, which contains HAL I2C enhancement.

Best Regards,

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
ZBond
Associate

Imen,

According to the project manager, we are using the STM32Cube FW_F4 V1.24.1 firmware package.

Thanks,

Zac

This place. Opened an issue on behalf of the OP:

https://github.com/STMicroelectronics/STM32CubeF4/issues/7

Regards,

-- pa

@ZBond​ Zac can you provide more info to help reproduce , please?

https://github.com/STMicroelectronics/STM32CubeF4/issues/7

Have you seen the latest update , 1.24.2?

-- pa