Prevent from sleep when a task is in a blocked state with finite timeout

kkoovalsky wrote on Tuesday, December 11, 2018:

Hello all.

I’m running FreeRTOS V9.0.0 on STM32L432KC.

I have a problem in preventing the device from going to sleep. At startup I have some tasks which I need to run without sleep. They use vTaskDelay and also some of the tasks use functions like xQueueReceive with timeouts which are finite (no portMAX_DELAY). The problem is that when one of the tasks gets blocked on such functions the device goes to sleep and I do not want it to. In general I want to implement some kind of mechanism which allows to prevent from sleeping if there are tasks which wait for something with a finite timeout. I can’t find any API which allows me to distinguish tasks which wait for something with finite timeout (e.g. those which have called vTaskDelay(pdMS_TO_TICKS(200)), xQueueReceive(q, pdMS_TO_TICKS(200)), xSemaphoreTake(mux, pdMS_TO_TICKS(200))… ) from those which are blocked indefinitely (xQueueReceive(q, portMAX_DELAY), xSemaphoreTake(mux, portMAX_DELAY)… ) .
The second problem is that I want to determine that in the configPRE_SLEEP_PROCESSING() callback (it’s a macro - I know - but in general it’s defined as a callback in my app). When I try to call uxTaskGetSystemState in the callback I get a hardfault. I don’t know then whether I can call FreeRTOS specific functions in this callback and I can’t find any information about that in the documentation.
I’m thinking about two solutions:

  1. Implement some kind of internal FreeRTOS mechanism, but then I need to edit FreeRTOS code, what’s quite intrusive and I don’t want to do it
  2. Instead of using vTaskDelay implement a mechanism based on a hardware timer which wakes up the task after the specifed time and the timer is able to wake up the device from sleep. The problem here is that I would need to connect somehow the timer with the FreeRTOS code for the task which call functions like xQueueReceive or xSemaphoreTake with a finite timeout.
  3. Manually add some flags which can be set/reset from task code and checked in the configPRE_SLEEP_PROCESSING callback. This is for me an ugly solution (but the simplest one) because every programmer in the team needs to remember about that when implementing a task, it can be error-prone and time-wasting when debugging.
    My question is if there is some kind of out of the box mechanism in FreeRTOS which allows to implement 2. solution or is there a way to determine in the configPRE_SLEEP_PROCESSING callback whether any task is in the “delayed” state, what means that it is waiting for something with a finite timeout?

rtel wrote on Tuesday, December 11, 2018:

I’m a little confused. Are you asking for a method of optionally selecting if the MCU should go into a sleep mode depending on the state of the application tasks? If so, your third option does not look like a bad choice to me as it is simple. Perhaps implement a ‘sleep manager’ with which tasks can register. You can keep a nesting count of whether to go to sleep - if a task does not want the system to enter a sleep state it calls a function to increment the nesting count, when it is happy for the system to go into a low power state it can call a function to decrement the nesting count. Then the pre-sleep-processing macro need just check the nesting count - if it is zero it can enter a low power state otherwise it aborts going into a low power state.

kkoovalsky wrote on Wednesday, December 12, 2018:

Yeah, I know that’s the simplest solution and works well but it’s intrusive. I need to remember all the time that my application can interfere with sleep so each task I create and run has to register in the sleep manager. It adds a lot of boilerplate.
Thanks, @Richard Barry, I will implement this in such a way as you suggested.
I hoped that there is some kind of way which allows to determine whether there is any task which waits for something with a finite timeout.

richarddamon wrote on Wednesday, December 12, 2018:

I thought that the current tickless implementation did something like that as there is a check for how long until the next task will awake, so you don’t go into tickless if that is too soon. There is an upper limit to that, as I believe the tick rollover is considered such an event, but with a 32 bit tick that will be far enough in the future to generally not happen. IF you know the upper bound for your finite timeouts, just set that threshold above that value.