cancel
Showing results for 
Search instead for 
Did you mean: 

Using STM32WB55: FreeRTOS osThreadFlagsWait can return osErrorTimeout early

Graham1
Associate II

I have come across an issue which I believe is a bug in the implementation of the osThreadFlagsWait function.

Scenario

A thread is waiting on a flag (e.g. 0x2u) for a timeout above 0, before this timeout should occur, there are multiple other flags set on the thread (e.g. 0x1u) using osThreadFlagsSet, this results in the osThreadFlagsWait function returning with a value of osErrorTimeout sooner than the set timeout.

Cause

The xTaskNotifyWait function which is called by osThreadFlagsWait returns each time the 0x1u flag is set, resulting in this section of code being run:

Graham1_1-1738260906062.png

Note that t0 is set to the return value of xTaskGetTickCount() at the start of the wait loop, so is the start time, tout is a timeout value passed to xTaskNotifyWait, which is originally the set timeout, but is adjusted each time the xTaskNotifyWait function returns.

The issue with the code above is that the value of td is the total time that the thread has been waiting, this is subtracting from tout each time a flag is set that is not waited on e.g.

for a set timeout of 100, if the flag that is not waited on happens every 10 ticks, the value of td and tout will be as follows for each time xTaskNotifyWait returns:

  1. td = 10 therefore tout = (100 - 10) = 90
  2. td = 20 therefore tout = (90 - 20) = 70
  3. td = 30 therefore tout = (70 - 30) = 40
  4. td = 40 therefore tout = (40 - 40) = 0 // timeout is detected on the next call to xTaskNotifyWait

This gives a timeout of 40 ticks in this case instead of the desired 100.

Suggested Fix

To fix this issue, I would suggest removing the cumulative subtraction from tout, instead replacing it with a subtraction of td from the set timeout e.g.

Graham1_2-1738261376861.png

 

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @Graham1 

According to an internal feedback FreeRTOS version has been updated to v10.6.2 in STM32WB release v1.24.0. Does it solve the problem reported in this post?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

View solution in original post

10 REPLIES 10
TDK
Super User

The code on GitHub already has this change.

stm32-mw-freertos/Source/CMSIS_RTOS_V2/cmsis_os2.c at e41c220a37adbb55b59dca704def6e73d6258b95 · STMicroelectronics/stm32-mw-freertos

 

What exact chip and library are you using? Are you using the latest version?

 

If you have an IOC file that generates the faulty code please attach it.

If you feel a post has answered your question, please click "Accept as Solution".

I am using an STM32WB55, using the FREERTOS middleware from STM32CubeIDEs Pinout & configuration tool with repository version STM32Cube_FW_WB_V1.21.0 which I believe is the latest.

 

https://github.com/STMicroelectronics/STM32CubeWB/blob/dcc538339a30165ced95745969706b7423e3d96d/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c#L862

STTwo-32
ST Employee

Hello @Graham1 @TDK 

Thank you so much for bringing this on the ST Community. I've escalated for review on the Future (under internal ticket number (204574).

Best Regards.

STTwo-32

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

fvv
Associate II

Hi everyone,
my apologies for reviving this, but yesterday I discovered another annoying problem with this code.
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 until a signal arrives and thus be suspended.
However, in a similar scenario, tout -= td becomes the result; what's done essentially amounts to timeout -= td.
Therefore, timeout != osWaitForever, and xTaskNotifyWait 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;
  }
}

 

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)

@fvv I would recommend the following solution: 

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

This should address the issue I observed, and the issue you describe as well. 

Hello @Graham1 

According to an internal feedback FreeRTOS version has been updated to v10.6.2 in STM32WB release v1.24.0. Does it solve the problem reported in this post?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

@mƎALLEm I have just downloaded the update, and it solves the problem that I was having, however it does not look like it addresses the issue @fvv describes.

As the first issue has been solved this thread needs to be closed.

@fvv  needs to post the new question in a new thread.

Thank you for the confirmation.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.