acehigh1971 wrote on Tuesday, August 07, 2007:
Hello all,
After completing the development, I decided to do some debug on vTaskDelayUntil behaviour, to support my previous statements (and to correct some of them).
I wrote a simple task that resembles the following:
…
static portTASK_FUNCTION( vTESTTASKTask, pvParameters)
{
(void) pvParameters;
xLastWakeTime = xTaskGetTickCount();
for(;
{
uint32_t ciclo;
B = 4567;
for (ciclo=0;ciclo<=1800;ciclo++)
{
A = B * ciclo;
}
vTaskDelayUntil(&xLastWakeTime,10/portTICK_RATE_MS);
}
}
…
Everything works fine. I preload the tick count in xLastWakeTime, and, at the end of the operations, I call the vTaskDelayUntil to precisely run again after 10ms.
Note: Without optimisation, the computation cycle lasts some 2ms.
Suppose you have the tick time at 9400, and the xLastWakeTime is put at 9405. The task is now "blocked" waiting for the timer to expire.
The problem arises when another task does a vTaskSuspend on this task. The task goes to "suspend state".
Then the tick timer goes up (eg. to 10000), and I do a call to vTaskResume. the wake time is still set at 9405, but the tick is 10000.
The task now does not block on the timer, and the task runs freely, without blocking on the vTaskDelayUntil call (In every vTaskDelayUntil call, the xLastWakeTime is increased of 10/portTICK_RATE_MS counts per call).
Depending on how fast is the task (how many tick it gets to execute), after a lot of free loops of the task, finally the lastwaketime reaches and overpasses the os ticktime, finally allowing the task to block on the vTaskDelayUntil call.
This causes, obviously, to use all the available processing time, respecting the task priorities, to recover the lost time.
If, after a suspend/resume I would not like this behaviour but a 10 ms constant execution, I see only the following solution:
Reset the xLastWakeTime value to the actual TickTime value, before the vTaskResume call.
Not quite elegant, because the xLastWakeTime must be in this case a global variable.
My question now is this: Is this behaviour intended? Am I doing something wrong? Should this be noted down in the API documentation?
I have seen that is quite usual to
stop the execution of a task by suspending it if needed by another "controller" task, and by resuming it when required again to operate.
The vTaskDelayUntil always falls into this pitfall.
I would really prefer to have the lastwaketime updated automatically in the call to vTaskDelayUntil, so not having the xLastWakeTime variable defined as global.
Is this wrong?
P.S. I haven’t done any consideration on tick timer overflow, I prefer to leave this to the OS writer.