cancel
Showing results for 
Search instead for 
Did you mean: 

Found 2 bugs in HAL_I2C_Master_Transmit_DMA().

gtopba
Associate II
Posted on April 10, 2016 at 20:42

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 */

      __HAL_UNLOCK(hi2c);

      

      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.

Thanks

 

#i2c
4 REPLIES 4
Posted on April 10, 2016 at 22:48

SysTick would need to preempt

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
gtopba
Associate II
Posted on April 14, 2016 at 03:40

I generated the code from CubeMX by setting the SysTick NVIC priorty higher than the DMA. Everything work fine. But I still cannot modify the DMA priority in the I2C example. This is the fucntion that I use, but has no affect on the DMA Priority

  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 1, 0);

  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

S0CR register still contain a high priority setting.

Thanks for you reply.
gtopba
Associate II
Posted on April 15, 2016 at 21:00

I have found the origin of my problem in the using of HAL_I2C Library in the FreeRTOS. As I said before, I tried to change the SysTick IRQ priority but was not successful. That is because the osKernelStart() fucntion sets the SysTick priority to the lowest, which is the recommended priority by FreeRTOS. However, some of HAL functions utilizes the SysTick interrupt for their Timeout functionality. And these WaitUtillTimout kind of functions, sometime, are called from a higher priority interrupt service routine. This cases the Timeout functionality to not work. Resulting the system to be blocked forever as the SysTick ISR cannot be activated.

What should I do in this case? Should I change the SysTick to the highest priority? or should I modify the HAL Library?

Regards
Walid FTITI_O
Senior II
Posted on May 05, 2016 at 12:29

Hi phothiphan.warut.001,

you need to use other HAL time base than Systick and keep Systick as only FreeRtos Timer base ( to prevent dead lock issue) you ought to select a timer as HAL time base source. Refer to ''HAL_TimeBase'' example in

http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1897/PF259243

at this path:

STM32Cube_FW_F4_V1.11.0\Projects\STM32469I_EVAL\Examples\HAL\HAL_TimeBase

You can do that using

http://www2.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-configurators-and-code-generators/stm32cubemx.html

tool, in SYS table -> Timerbase Source . To check this in details , you should take a look at the

http://www2.st.com/content/ccc/resource/technical/document/user_manual/10/c5/1a/43/3a/70/43/7d/DM00104712.pdf/files/DM00104712.pdf/jcr:content/translations/en.DM00104712.pdf

(4.11.6 Setting HAL timebase source).

-Hannibal-