cancel
Showing results for 
Search instead for 
Did you mean: 

[Bug] I2C I2C_WaitOnRXNEFlagUntilTimeout

vincenthamp9
Associate III
Posted on August 20, 2017 at 20:18

The L4 1.8.1 drivers contains a tedious race condition inside the 'I2C_WaitOnRXNEFlagUntilTimeout' function. There is a chance that RXNE reads 0 (RESET), which causes the while {} to execute. Potentially RXNE and STOPF could get set now right (e.g. if there are IRQs running in between) before the STOPF bit gets checked. If we're about to poll the last byte of a transmission, the function might return a HAL_ERROR, altough we received a perfectly legal sequence of RXNE being set right before STOPF.

Also, I believe this question here is related, although about the F7 driver:

https://community.st.com/message/5948-stm32-fwf7v131-i2c-hali2cmasterreceive-bug

 

I suggest working on the internal communication between whoever is responsible for keeping the drivers up-to-date...

Also, the insert-code function won't work, although I've got all the god damn JS stuff enabled, so here is a plain text copy of 'I2C_WaitOnRXNEFlagUntilTimeout' ->

static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)

{

  while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)

  {

    /* Check if a NACK is detected */

    if(I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)

    {

      return HAL_ERROR;

    }

 

    /* Check if a STOPF is detected */

    if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)

    {

      /* Clear STOP Flag */

      __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);

 

      /* Clear Configuration Register 2 */

      I2C_RESET_CR2(hi2c);

 

      hi2c->ErrorCode = HAL_I2C_ERROR_NONE;

      hi2c->State= HAL_I2C_STATE_READY;

      hi2c->Mode = HAL_I2C_MODE_NONE;

 

      /* Process Unlocked */

      __HAL_UNLOCK(hi2c);

 

      return HAL_ERROR;

    }

 

    /* Check for the Timeout */

    if((Timeout == 0U)||((HAL_GetTick() - Tickstart) > Timeout))

    {

      hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;

      hi2c->State= HAL_I2C_STATE_READY;

 

      /* Process Unlocked */

      __HAL_UNLOCK(hi2c);

 

      return HAL_TIMEOUT;

    }

  }

  return HAL_OK;

}
0 REPLIES 0