cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WB55: FreeRTOS osThreadFlagsWait can change behavior of osWaitForever

fvv
Associate II

Hello, a while ago I ran into a problem with my system consuming to much power.
After searching this forum, I came across this post:

 

https://community.st.com/t5/stm32-mcus-wireless/using-stm32wb55-freertos-osthreadflagswait-can-return/td-p/767777


It describes how osThreadFlagsWait adjusts the timeout and explains that this can cause problems.
In the thread i described my problem with this function (see below), but I was asked to post that question in a new thread.
No problem, of course, so I did :)

I discovered another annoying problem with osThreadFlagsWait.
I was measuring the current consumption to check if it was sufficiently low in case the system goes into stop2.
To my surprise, I discovered that it wasn't (draining 6mA instead of 30uA).
After a long search, I discovered that the high-consuming task state wasn't "suspended", but "blocked"!
A little later, I realized this would happen when I called osThreadFlagsWait.
I assumed the timout value could be osWaitForever, so the task would sleep (and thus be suspended) until a signal arrives.
However, in a similar scenario, tout -= td becomes the result; what's done essentially amounts to timeout -= td.
Therefore, timeout != osWaitForever, and xTaskNotifyWait (wrapped in osThreadFlagsWait) will notice this and set a very long timeout.
This causes the behavior to be different (the task is blocked, not suspended).

I've currently tested this as a solution:

if (timeout != osWaitForever) {
  if (td > tout) {
    tout = 0;
  }
  else {
    tout -= td;
  }
}

 @Graham1 suggested the following solution (in the other thread), which resolves both issues:

 

if (timeout != osWaitForever)
{
  if (td >= timeout)
  {
    tout = 0;
  }
  else
  {
    tout = (timeout - td);
  }
}

 

Is this a correct sollution?


I am also using stm32wb55 and STM32CubeIDE (Version: 1.19.0 Build: 25607_20250703_0907 (UTC)) as tool to configure the hw and generate code.
It generated the FreeRTOS code (FreeRTOS Kernel V10.3.1.h states: FreeRTOS Kernel V10.3.1)

1 REPLY 1
Khaled_DHIF
ST Employee

Hello @fvv ,

Thanks for the detailed write-up, this is very interesting.

One thing that is still not fully clear to me is how the osThreadFlagsWait timeout recomputation alone would explain the higher Stop2 current. Once the MCU is truly in Stop2, the application core is halted, SysTick is stopped, and no FreeRTOS thread code is executing during that period. Because of that, the direct link between timeout recomputation and Stop2 current is not obvious.

Could you share a bit more context so we can isolate the root cause?

1. Is tickless idle enabled in your FreeRTOS config (configUSE_TICKLESS_IDLE / vPortSuppressTicksAndSleep)?
2. How exactly do you enter Stop2 in your project:
via idle hook, direct HAL_PWREx_EnterSTOP2Mode(), etc.?
3. Are there any periodic wake sources still active (timer server, RTC, IPCC/radio activity, debug, SysTick still running)?

My understanding is that with proper tickless + Stop2 integration, even a very long finite block time often allows long sleep intervals. So the difference between a true osWaitForever and a very large finite timeout should usually not by itself cause a jump from tens of uA to mA range.

About the proposed code fix, the version you have proposed looks correct and safer for both edge cases as it avoids underflow and preserves true osWaitForever behavior.

Kind regards,

DHIF Khaled

Please mark my answer as best by clicking on the “Accept as solution" button if it fully answered your question. This will help other users find this solution faster.​