STMicroelectronics / STM32CubeF4

STM32Cube MCU Full Package for the STM32F4 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))
Other
824 stars 408 forks source link

Problem in HAL_I2C_Mem_Read, no NAK generated in rare cases #139

Closed ks000 closed 1 year ago

ks000 commented 1 year ago

Describe the set-up

Describe the bug

In some cases HAL_I2C_Mem_Read will finish reading given number of bytes from I2C slave, but will not NAK the last byte. This may cause the slave to pull SDA low if its next byte's MSb is 0, thus freezing the I2C bus.

How to reproduce the bug

  1. My code is reading the data from slave via I2C bus using HAL_I2C_Mem_Read function.

  2. List the modules that you suspect to be the cause of the problem:

    • stm32f4xx_hal_i2c.c
  3. Describe the use case that generates the problem The problem appears when receiving >3 data bytes and HAL_I2C_Mem_Read function can be pre-empted. This could be also caused by an interrupt (I did not check this).

  4. How we can reproduce the problem: Run HAL_I2C_Mem_Read from a task which can be pre-empted by FreeRTOS (or some interrupt) in order to read >3 data bytes via I2C.

Additional context

It seems that I localized the problem to lines 2812-2823 in file stm32f4xx_hal_i2c.c (looking at the latest commit 3d6be4b)

Screenshots

I used logic analyzer to drill down to the reason of the no-NAK behavior and used 4 extra GPIO outputs to understand what the code is doing. On screenshots, there is I2C bus SCL and SDA signals, as well as 4 GPIO lines:

On screenshot with normal data reception the 6 data bytes are received as expected: first three bytes with RXNE loop (DBG0 high), last three bytes in lines 2744-2792 (DBG3 high), NAK in the end.

On screenshot with the problematic behavior, the last bytes are handled in code lines 2711-2741 (DBG2 high), no NAK in the end.

ALABSTM commented 1 year ago

Duplicate of stm32f4xx_hal_driver#17.

ASELSTM commented 1 year ago

Hi @ks000,

Thank you for your contribution. Would it be possible to share the project you have used to reproduce the issue in order to allow a better analysis of the problem.

With regards,

ks000 commented 1 year ago

Hi @ASELSTM,

Sorry, I can't share the whole project, but I can share a snippet of code from where HAL_I2C_Mem_Read is called. The software in my project works under the control of FreeRTOS and reads data from LSM303AGR STM accelerometer.

My code calls function lsm303agr_acceleration_raw_get() from lsm303agr_reg.c driver by STM which in turn calls data read callback (snippet below) in order to read 6 bytes from the accelerometer:

int32_t platform_read(void *handle, uint8_t Reg, uint8_t *Bufp, uint16_t len) {
    uint32_t i2c_add = (uint32_t) handle;
    if (i2c_add == LSM303AGR_I2C_ADD_XL) {
        /* enable auto incremented in multiple read/write commands */
        Reg |= 0x80;
    }
    HAL_I2C_Mem_Read(&hi2c2, (uint8_t) i2c_add, Reg, I2C_MEMADD_SIZE_8BIT, Bufp, len, 1000);
    return 0;
}

I think you do not need LSM303AGR, any I2C memory will do, but >4 bytes should be read with a single call. Just make sure that the thread which calls HAL_I2C_Mem_Read() gets pre-empted frequently.

I guess if you use such setup and set a breakpoint to line stm32f4xx_hal_i2c.c:2815, then you should eventually get it stopped, and from there you can observe the incorrect behavior: going to lines 2711-2741 and not disabling I2C ACK while running out of bytes to receive.

Let me know if I can help somehow else.

Best regards.

vei1av commented 1 year ago

Hi. What is the status of this ticket? Is it planned to be fixed soon? We are facing a similar issue on a stm32f412vg when reading data from an external EEPROM. See also https://github.com/STMicroelectronics/stm32f4xx_hal_driver/issues/17#issuecomment-1380198130.

ASELSTM commented 1 year ago

Hi @ks000,

As this issue is a duplicate of stm32f4xx_hal_driver#17 please allow me thus to close this one and keep the other.

With regards,