AnsweredAssumed Answered

Found 2 bugs in HAL_I2C_Master_Transmit_DMA().

Question asked by phothiphan.warut.001 on Apr 10, 2016
Latest reply on May 5, 2016 by FTITI.Walid
Run the "I2C_TwoBoards_ComDMA" example in Master mode. And do not connect it to a slave board (to simulate NACK). And you will find that you get stuck in the infinity loop inside the  I2Cx_DMA_TX_IRQHandler().

When the HAL_I2C_Master_Transmit_DMA() is called and no ACK is received, the function I2C_IsAcknowledgeFailed() will be called two times. First time with fucntion I2C_WaitOnTXISFlagUntilTimeout(). Second time with I2C_WaitOnSTOPFlagUntilTimeout() inside the I2Cx_DMA_TX_IRQHandler.

The first bug, the NACK flag was cleared since the first call of I2C_IsAcknowledgeFailed(). So the second time that the I2C_IsAcknowledgeFailed() is called inside the IRQHandler, it will return HAL_OK, so it will never can get out of the infinity loop. As the second bug is SysTick geting blocked by the IRQHandler, so the Timeout will also not work.

static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout)
  uint32_t tickstart = 0x00;
  tickstart = HAL_GetTick();
  while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
    /* Check if a NACK is detected */
    if(I2C_IsAcknowledgeFailed(hi2c, Timeout) != HAL_OK)
      return HAL_ERROR;
    /* Check for the Timeout */
    if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
      hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
      hi2c->State= HAL_I2C_STATE_READY;
      /* Process Unlocked */
      return HAL_TIMEOUT;
  return HAL_OK;

I have tried to change the SysTick_IRQHandler to the highest priority (0) and the DMA priority to (1). It still get stuck in the infinity loop.

I have tried with STM32F3, F7 and L4 Discovery borad and I got the same result.

This problem also cause the FreeRTOS to get blocked in my another project.

Can somebody try this and tell me whether you get the same problem? I've spend the whole day on this issue. Hope I can find out soon.