cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_I2C hangs when it enters I2C_WaitOnFlagUntilTimeout() function.

ty.locke
Associate II

I'm using verion 1.1.5 of the I-CUBE-LRWAN software and reading a few I2C sensors using the HAL_I2C functions.

No issues when sensors are functioning properly; however, I have run into periodic sensor failure issues while testing, either permanent or temporary, where one of the I2C lines may be held low or enter the wrong state.

In these cases, once the HAL TX enters the I2C_WaitOnFlagUntilTimeout() function, timeout is never reached and the entire application hangs until the board is reset.

Has anyone encountered a similar issue or have an advice on this problem?

In the real world there are bound to be issues here and there with defects and bad communication once in a while, ideally this should not freeze the entire application if the STM32 fails to communicate with a slave device properly during a single read.

Code snippet below:

In a failed scenario, I2C_FLAG_BUSY remains set and it appears HAL_GetTick() never exceeds Tickstart to generate the HAL_TIMEOUT return.

static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)

{

 while(__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)

 {

  if(Timeout != HAL_MAX_DELAY)

  {

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

   {

    hi2c->State= HAL_I2C_STATE_READY;

    hi2c->Mode = HAL_I2C_MODE_NONE;

    /* Process Unlocked */

    __HAL_UNLOCK(hi2c);

    return HAL_TIMEOUT;

   }

  }

 }

 return HAL_OK;

}

12 REPLIES 12
ty.locke
Associate II

Update on this question.

Found two definitions for HAL_InitTick() in the example code and swapped the __weak keyword from the definition I believe to be the correct one below:

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)

{

 HAL_SYSTICK_Config(SystemCoreClock/1000U);

 /*Configure the SysTick IRQ priority */

 HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0U);

  /* Return function status */

 return HAL_OK;

}

HAL_GetTick() now appears to working as expected initially when the application begins to run through main(); however, once the MCU goes into stop mode, HAL_GetTick() no longer keeps the correct time, so I'm still running into the same issue with I2C.

If anyone has any ideas as to what could be causing this or how to resolve I'd appreciate the help.

CCama.2
Associate

Did anyone ever find an answer to this question? I seem to be having the same issue...

ty.locke
Associate II

I wasn't able to get the HAL_GetTick() function to work properly. I replaced with the below functions using the RTC to calculate ticks instead of the system clock. I2C drivers are working as expected now; if there's any issue on the bus or with the communication the HAL I2C function will timeout as expected and the application will continue to run.

uint32_t GetCurrentTicks( void )

{

 uint32_t now = HW_RTC_GetTimerValue( );

 return now;

}

uint32_t GetElapsedTicks( uint32_t past )

{

 uint32_t nowInTicks = HW_RTC_GetTimerValue( );

 uint32_t pastInTicks = past;

 // intentional wrap around. Works Ok if tick duration below 1ms

 return nowInTicks-pastInTicks;

}

JHerr.4
Associate II

Hello ty.locke,

I have same problem. I implemented the functions you shared and now Tick is working but I2C is not working yet... Did you implemented something more?

Thanks in advance,

Jorge

No, I didn't implement anything else. I only replaced the default HAL_GetTick() with the RTC based functions I added above, but this needs to be done for each of the relevant I2C functions that are used (HAL_I2C_Mem_Read/Write, HAL_I2C_Master_Transmit/Receive, as well as the other I2C functions called within each of these routines).

I didn't have any issues with I2C working previously under *normal* conditions using the default example code, so if your I2C bus isn't working properly there may be another issue somewhere else in your project.

My issue with I2C was specifically when an I2C slave failed or one of the I2C signals was driven to an unexpected state, the MCU would then get stuck in an infinite loop and freeze since HAL_GetTick() was not working and therefore unable to reach the timeout threshold.

MWils.4
Associate II

We had a similar hang in I2C when we build a new project using an STM32L4A6. We had working code on a previous STM32L433. When we compared the HAL code we found there was one line difference in Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c in the function

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,

uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

Near the end of this function in both HAL's there is a line of code to clear the STOP flag:

  /* Clear STOP Flag */

  __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);

In the STM32L433 driver this line is followed by a clear of the NAK flag, but it was absent in the L4A6 driver:

  /* Clear NAK flag */

  __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);

Adding this line to the L4A6 driver has cured our I2C hangs with this processor.

Those MCUs are both L4 and have the same drivers. At least in current driver versions I cannot see clearing of a NAK in HAL_I2C_Mem_Write() at all.

@Imen DAHMEN​, somewhat inconsistent, but still a bug report.

Hello @Piranha​ ,

Thanks for pointing out this issue.

I am checking it and I will come back to you with update.

Thanks

Imen

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

The error detected link to NACK, is generally manage in function I2C_IsAcknowledgeFailed.

This function is called by different way, depend of flag to verify.

Checking this function I2C_IsAcknowledgeFailed, the NACK flag is detected, and associated error is set in the handle. And NACK flag is clear too.

I hope that is clear and I've answered your question!

Imen

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