Analysing tasks management and priorities

xavierpacheco wrote on Sunday, March 11, 2018:

A task has been created that reads a value of the ADC of a temperature sensor of a battery every 100 ms, calculate the value of it from the reading and update the value of a variable with it. My first iteration of the routine is as follows:

`#define DELAY_TICKS 100 // tick period 1 ms => 100 ms delay
volatile float battery_temperature;

void temperature_task(void* parameters) {

TickType_t current_tick_count, expired_tick_count;

while (1) {
// Read ADC
unsigned short adc_value = read_temperature_adc();

// Compute temperature
float temperature = compute_temperature(adc_value);

// Update variable
battery_temperature = temperature;

// Get current system tick count and compute expired count
current_tick_count = xTaskGetTickCount();
expired_tick_count = current_tick_count + DELAY_TICKS;
// Wait until the number of ticks has happen (100 ms)
while (xTaskGetTickCount() < expired_tick_count) {} } }`

Once incorporated into the system, other tasks have begun to have problems because they are receiving less processing time, and even one of them has stopped working completely.

The task has been created with “normal” priority and the tick of the system is 1 ms (time of change between concurrent tasks). And the function to read the ADC works waiting for the reading, but it only takes a few nanoseconds and is not considered to impact the system, like the routine that computes the temperature.

So these are my questions:

What happens with tasks that have been receiving less processing time, but still running? Specifically about their priority and the way they use their time.

What happened to the task that has stopped running completely?

What is the problem that I have caused with my routine and how can I solve it?

P.D.: I’m using FreeRTOS Cortex M3

heinbali01 wrote on Sunday, March 11, 2018:

In this loop:

    while (xTaskGetTickCount() < expired_tick_count) {

your task consumes all CPU time, depending on it priority.

Please have a look at vTaskDelayUntil()
and vTaskDelay()

xavierpacheco wrote on Sunday, March 11, 2018:

But, if that loop consumes all CPU time, how can other tasks still execute?

heinbali01 wrote on Sunday, March 11, 2018:

That is a very good question! I thought about it while I composed my answer here above.

The loop doesn’t block in any way, so that task is non-stop runnable.

As long as a task with priority P is runnable, only tasks of priority P and higher will run.

These three defines determine the behaviour of the FreeRTOS scheduler:


I think you find good documentation here. Although it might not be up-to-date with the latest newest 10.x release. The principles of FreeRTOS scheduling have never changed. … as far as I know.

I can answer your question, but then I’d have to see your code, most importantly FreeRTOSConfig.h, and also the priorities of the other tasks, and see if and how they block.

About timing: note that TickType_t is a 32-bit number. It will overflow, and also this calculation will, some day, overflow:

    expired_tick_count = current_tick_count + DELAY_TICKS; 

When it overflows, your timing will be incorrect.

Here you find safe method, along with an example.


xavierpacheco wrote on Sunday, March 11, 2018:

Thank you. I just want to understand something in this example: I know that the while loop doesn’t block, so it takes as much time as it is possible. But, how can other tasks get less processing time and still executing? I mean, in this example, a task with higher priority will pre-empts my ADC task without taking into account that ADC task doesn’t block. But, if the other tasks have the same priorities, I think they might execute really fast and then get pre-empted by my ADC task again, right?

heinbali01 wrote on Sunday, March 11, 2018:

I know that the while loop doesn’t block, so it takes as
much time as it is possible.
But, how can other tasks get less processing time and
still executing?

It looks like the other tasks have an equal priority and thus there is time-slicing.

But before guessing more, I’d like to see your FreeRTOSConfig.h, and also the priorities of all tasks, and see if they block.

richard_damon wrote on Sunday, March 11, 2018:

Assuming you have the proper options enable in FreeRTOSConfig.H, task of the same priority will time share in a round robbin fashion, switching which ready task will run on each Tick interrupt. If the other task do something to block, then they will give up the processor, and this task will eventually get run, and continue until the next Tick.

xavierpacheco wrote on Sunday, March 11, 2018:

The problem is about guessing, because the approach doesn’t give more information. That’s all it says. That’s a problem that I found in an article and I was interested in analysing it. So, we can guess what it sounds more reasonable. As you say, we can assume that other tasks have same priorities. But, as the problem says, there is a task that stopped executing, so it has to be the iddle task. So, as the ADC task doesn’t block, the only way that other tasks are able to execute, is either if they have higher priorities and they block or if they have the same priorities and don’t block, so there is time-slicing and that’s why they receive less time than the ADC task.

Is it my approch good?
Now, the way to solve this is replacing the while loop with a TaskDelay or TaskDelayUntil function.

richard_damon wrote on Tuesday, March 13, 2018:

Because it can’t actually take ALL the time, higher priority tasks can still get time when then become ready, and equal priority too if you have configUSE_TIME_SLICING enabled.