Skip to main content
ty.locke
Associate II
May 18, 2020
Question

HAL_I2C hangs when it enters I2C_WaitOnFlagUntilTimeout() function.

  • May 18, 2020
  • 8 replies
  • 12499 views

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;

}

This topic has been closed for replies.

8 replies

ty.locke
ty.lockeAuthor
Associate II
May 27, 2020

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
Visitor II
July 22, 2020

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

ty.locke
ty.lockeAuthor
Associate II
July 23, 2020

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
December 2, 2020

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

ty.locke
ty.lockeAuthor
Associate II
December 2, 2020

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
January 14, 2022

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.

Piranha
Principal III
January 14, 2022

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.

Technical Moderator
January 18, 2022

Hello @Piranha​ ,

Thanks for pointing out this issue.

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

Thanks

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Gumer RoMa
Visitor II
January 19, 2022

I got the same issue with HAL_GetTick() function. I notice it gets stuck when I call a HAL_I2C function FROM an interruption (in my case, from an UART interruption). It works fine when called from the main loop.

Hope this helps to find a work around in your code.

MBertocchi
Associate II
May 10, 2022

I also had this problem and I firmly believed that it was a software bug, but after hours of testing I realized that the problem was on the priority I gave to the interrupt. the SysTick has a priority 0 interrupt while the uart has to be set to priority 1, and then you will see that everything works.

MBertocchi
Associate II
May 10, 2022

I also had this problem and I firmly believed that it was a software bug, but after hours of testing I realized that the problem was on the priority I gave to the interrupt. the SysTick has a priority 0 interrupt while the uart has to be set to priority 1, and then you will see that everything works.