Question on vTaskResume & vTaskDelayUntil

groufosse wrote on Friday, July 05, 2013:


On this FreeRTOS web page:

It says this:
"…Therefore a task using vTaskDelayUntil() to execute periodically will have to re-calculate its required wake time if the periodic execution is halted for any reason (for example, the task is temporarily placed into the Suspended state) causing the task to miss one or more periodic executions. This can be detected by checking the variable passed by reference as the pxPreviousWakeTime parameter against the current tick count. "

I am having the issue where I place the task into suspended, then upon resume it executes the “missed” time. In trying to understand the last line of the paragraph above, where would this check occur, and can someone provide an example of how it would be done? In other words, how to re-calculate the required wake time?

Thank you

davedoors wrote on Friday, July 05, 2013:

There are some internal (not API) functions that allow code to calculate absolute times even when the tick count has overflowed. If you search for vTaskSetTimeOutState and xTaskCheckForTimeOut in queue.c you will see how they are used. The functions are pubic but apparently not intended for application writers to use because they are not part of the documented API.

A simpler solution might be to simply reinit the last wake time parameter by calling xTaskGetTickCount() again, but that can only be done if you can communicate to the task that it has just come out of the Suspended state.

You can of course manually check the value of (last wake time + delay period) before calling vTaskDelayUntil() to check it is in the future, not in the past, but you will need to take care of timer overflows too.

groufosse wrote on Friday, July 05, 2013:

Hi davedoors,

Thanks for your reply.
I can’t help but wonder why such good, useful methods (vTaskSuspend and vTaskResume) cause such issues with the execution timer they carry, and why an equally accessible solution hasn’t been written in the API to solve this? I guess another way to put it is; what good is those methods without a relatively easy way to solve this issue which I think is one that anyone who uses it needs to address?

BTW - I have tried reinitializing the parameter to xTaskGetTickCount() just before calling vTaskResume, but that didn’t seem to do much of anything.

Thanks again.

rtel wrote on Friday, July 05, 2013:

It is actually vary uncommon for applications to place tasks into the Suspended state, and its difficult to say what is the best thing to do when it does happen.

The task itself only has a concept of executing a sequential piece of code, it has no knowledge of being swapped on and off the CPU, or of being placed into the Suspended state unless it actually places itself into the Suspended state.  In your case it cannot both be calling vTaskDelayUntil() and vTaskSuspend() at the same time, so it can only go into the Suspended state if another task puts it there, and when it leaves the Suspended state it just carries on from where it was none the wiser.

The semantics of the vTaskDelayUntil() function state that if the requested unblock time is in the past then the task should not block at all - it would not make any sense for it to block because if its unblock time was in the past when would it unblock?

In your case the two things are happening at the same time, the task goes into the Suspended state without knowing it, then asks to be woken up sometime in the past, so doesn’t block.  Logically everything is happening as expected.

The question then becomes, should the task have some way of knowing it is asking to block in the past?  Well really it can do that if it needs to as per the reply above - it knows the last time it unblocked and it knows how long from that time it want to next unblock, so it can calculate the next unblock time.  It also knows what the time is now by calling xTaskGetTickCount().  It also knows if the tick count has overflowed because xTaskGetTickCount() will return a value lower than the last unblock time.

I understand you may want some more elegant way of knowing if the requested block time was in the past, maybe to have an API function that did the calculation for you - if you can specify how that should be done then add something to the feature request tracker - but the kernel cannot automatically adjust any times that are held by the task because it cannot make any assumptions as to how the task is using the API functions.  If vTaskDelayUntil() is being used to perform an operation a certain number of times, and a couple of operations have been missed because the task was suspended, then it may well be  desirable for the vTaskDelayUntil() function to continuously return immediately until its time has caught up with system time, at which point it will once again enter the Blocked state for real.

Not sure if any of that makes sense, but hopefully you get the gist.


groufosse wrote on Friday, July 05, 2013:


Thanks for the thorough reply.
Sure, I do get the gist, but I guess I’m still uncertain of the right approach to solve the problem with the given tool set. If I have a task that needs to execute every 30 seconds, is it better to create, then delete, rather than suspend, and resume?

I was using the create-delete approach, but decided to try this way as I thought this was a more “resourceful” and perhaps safer approach, but it’s got a whole new set of issues.


edwards3 wrote on Friday, July 05, 2013:

I would never advocate creating and deleting, but if you need it to run every 30 seconds and you are using vTaskDelayUntil() to execute it every 30 seconds, why do you need to suspend it at all?

richard_damon wrote on Friday, July 05, 2013:

I would definately use a task in a delay loop over a create-delete approach. Create-Delete does a lot more extra work, including making heap allocation after init time, which is often considered a bad practice (are you prepared to handle the possible memory allocation failure, or are you going to PROVE that it can never occur, not an easy task in general).

The question is, Why are you suspending the task, if it is to run once every 30 seconds, let it use vTaskDelayUntil (or vTaskDelay) to restart itself on schedule. If you need to wait for something, wait on a semaphore/queue that will be poked when that thing happens.

groufosse wrote on Friday, July 05, 2013:

Actually, that’s a good point.   8~]
The concern is that the function that’s actually being launched from the task may still be executing, so I don’t want it to execute again if it is. But that said, I can use a semaphore to verify if the “function” is still executing ans skip over the code in the task.


groufosse wrote on Friday, July 05, 2013:

OK, here’s another question based on these replies (thanks again for taking the time to answer)

Problem is, if I need to create the task upon program start, I don’t want it to run until it’s needed, meaning I need to suspend it right away. It can only run when a specific state is reached, then I want the task to start running every 30 seconds. Which means I need to use vTaskResume, bringing about the timer tick issue again. So, do I need to use vTaskDelay, or vTaskDelayUntil ? Or, …?

rtel wrote on Friday, July 05, 2013:

Well, you could just not create the task until the time that it first needs to run, so you change your code to create the task once then let it control its own timing.  The task would never have to enter the Suspended state at all if it didn’t exist until it needed to execute the first time. 

However, the ‘issue’ as defined in this thread is only an issue if the task is suspended between calls to vTaskDelayUntil().  I will try and demonstrate below:

void vATask( void *pvParameters )
portTickType xLastRunTime;
const portTickType x30SecondsInTicks = 30000 / portTICK_RATE_MS;
    // A Initialise the last run time variable.
    xLastRunTime = xTaskGetTickCount();
    // B Enter a loop to run every 30 seconds.
    for( ;; )
        // C Wait until it is time to run again.
        vTaskDelayUntil( &xLastRunTime, x30SecondsInTicks );
        // D Perform processing here.
        // E Loop back to 'C' to wait for the next execution time.

Scenario, no suspension, normal execution:

1) The task start to run and takes a snapshot of the time at A.

2) The task blocks at C relative to the time taken at A.  The unblock time will be 30 seconds in the future.

3) At D xLastRunTime will equal its initial value + x30SecondsInTicks, everything is ok.

4) At E the processing for this cycle is complete and the task loops back to C, to wait another 30 seconds.

5) The task wakes at the correct time and at D performs its processing.

That scenario can loop as many times as you like with correct behaviour, now lets change the scenario at some point…

6) Between D and E the task is suspended for 40 seconds.

7) At E the task loops back to C, but this time xLastRunTime was 40 seconds ago (plus whatever the time it takes to process the loop), so it asks to wake up 40 seconds ago plus 30 seconds, which is 10 seconds in the past.

8) vTaskDelayUntil() adds 30 seconds worth of ticks to xLastRunTime and returns immediately.  Now xLastRunTime is 10 seconds in the past.

9) D and E execute without the task being suspended.

10) vTaskDelayUntil() is called again asking to wake up 30 seconds after a time that is already 10 seconds in the past, so the task enters the Blocked state for 20 seconds only.  Now the time has caught up with itself and the task has executed its processing the expected number of times.

Now assume the task is created in the Suspended state (which is possible if the task is created and then suspended before the scheduler is started, or simply by calling TaskSuspend( NULL ) as the first line of the task so it runs then immediately suspends itself - which is ok provided it is guaranteed to happen before anything tries to resume it).  It does not matter how long it stays in the suspended state because it has not yet initialised xLastRunTime.  When it leaves the Suspended state the first thing it will do is as per the comment line A above - which is to initialise xLastRunTime.  Then the scenario as described above executes in exactly the same way using a time relative to the time it left the Suspended state rather than the time the task started running.


groufosse wrote on Friday, July 05, 2013:

This detailed explanation now makes sense. There was never any problem understanding normal execution; just exactly what was happening on suspended state was the issue. One thing you pointed out and that wasn’t immediately obvious to me was to suspend the task right after creation, which holds “xLastRunTime” in the initialized state (value) until it’s resumed. This is perfect and would make the execution of my tasks exactly the way I need them to be.

Thank you!