LED Flashes

There are three Tasks ,each of which flash an LED at a different rate. The first LED flashes every 200ms, the second every 400ms, the third every 600ms. All three tasks have the same priority. Time slice is 1 ms.

In FreeRTOS if all tasks have same priority then all tasks will be executed in round robin fashion.

I don’t understand how to decide which task will be executed and when will be executed, blocked, ready at generic target.

Does anyone know how you would achieve that in FreeRTOS?

Do you mean you don’t understand how you decide which task will execute when? Or you don’t understand how FreeRTOS decides? If the latter, then this may help: FreeRTOS single-core AMP and SMP RTOS task scheduling - FreeRTOS If the former then I suggest reading the book: Free RTOS Book and Reference Manual

1 Like

I don’t understand how FreeRTOS decides LED Tasks?

How it determine which LED task is ready to run?

How it decides when it needs to run or blocked or ready to run?

How would you flash three LED at different rates ?

Did the book help? Link in my previous post.

After reading a lot I don’t understand which of the three tasks will run first and for how long. How will it suspend or how will it be ready to run.

All three Tasks cannot run simultaneously. any of them must be run while the other is waiting to be run.

So before coding how do you decide which task should run when and for how long?

Even though the FreeRTOS book and online docs are very good and comprehensive there are even more in the web like e.g. http://www.learnitmakeit.com/freertos-tick/ explaining what you still want to know.

When programming in RTOS, the order of execution should not be assumed (i.e. do not rely on timing). If it is important that tasks execute in a particular order, then a suitable synchronisation should be added to the code. Of course if you are interested in the internals of RTOS and scheduling there are many books and references.

This sounds suspiciously like a school assignment.

I don’t understand what you mean by this.

Assuming there’s no requirement for the tasks to communicate with each other, the tasks could each do

loop
   delay for the interval for this task (e.g. 200 ms) - the flash period, say 10 ms
   turn the LED on
   delay for 10 ms so we can see the flash
   turn the LED off
end loop

You don’t need to care about round-robin vs preemptive scheduling, in fact you don’t need to care abut anything much. Just let the tasks get on with it.

The tasks will be run according to:

  1. interrupt / priority (pre-emptive scheduling)
  2. round robin scheduling

Consider the following code


struct LedTaskParams {
    int pin;
    int flashPeriod;
};

void Task_FlashLed(void * pvParameters)
{
    configASSERT((LedTaskParams*)pvParameters != nullptr);
    
    const LedTaskParams data = *((LedTaskParams*)pvParameters);
    const int led_pin = data.pin;
    const TickType_t xOuterFrequency = pdMS_TO_TICKS(data.flashPeriod);
    const TickType_t xInnerFrequency = pdMS_TO_TICKS(10);

    TickType_t lastRun = xTaskGetTickCount();  // 1
    TickType_t flashMarker;

    while(true)
    {
/*
        flashMarker = xTaskGetTickCount();  // 2
        digitalToggle(led_pin);
        vTaskDelayUntil(&flashMarker, xInnerFrequency );
*/ // 3

        digitalToggle(led_pin);
        vTaskDelay(xInnerFrequency);
        digitalToggle(led_pin);

        vTaskDelayUntil(&lastRun, xOuterFrequency);
    }
}

LedTaskParams redParams(1, 200);
LedTaskParams greenParams(2, 300);
LedTaskParams blueParams(3, 100);

xTaskCreate(Task_FlashLed, "red-led", 1024, (void *)&redParams, TASK_PRIO_NORMAL, NULL);
xTaskCreate(Task_FlashLed, "green-led", 1024, (void *)&greenParams, TASK_PRIO_NORMAL, NULL);
xTaskCreate(Task_FlashLed, "blue-led", 1024, (void *)&blueParams, TASK_PRIO_HIGH, NULL);

The Blue LED is prioritised TASK_PRIO_HIGH, whilst the other two tasks are prioritised TASK_PRIO_NORMAL. This means that the Blue LED’s task will be scheduled for execution ahead of Green and Red tasks.

The RTOS scheduler will look for highest priority tasks in the ready state, and will therefore pick up the blue task. The blue task will toggle the led pin and then it will yield control by calling xTaskDelayUntil() The scheduler will then look for the task of highest priority in the ready state. This time, it will be red or green, and since they are of equal priority, the actual task selected will be based on a round robin system i.e. each task will be given equal run time in turn, until a higher priority task is in the ready state.

Hopefully that helps -even though it is a very high level description

Edited after @richard-damon’s response:

  1. corrected mismatched variable names (from lastRun to lastFlash)
  2. initialized flashMarker prior to toggling the LED upon entry into the loop
  3. replaced call to vTaskDelayUntil with call to vTaskDelay
1 Like

There is a caveat to creating tasks with different priorities, you have to be certain that tasks with a higher priority run faster than those with a lower priority, and you have to be certain that the higher priority tasks will be in some non-blocking waiting state more than they are in the running state. Otherwise, your lower priority tasks will not get to run.

An addendum to this would be that on a dual core processor (such as the ESP32) FreeRTOS has a port to support pinning tasks to a specific core, and one could run higher priority tasks on one core and lower priority tasks on another, however having the tasks run across multiple cores would mean that prioritisation could well become a non-issue.

1 Like

It helps a lot more than before.

I assume single core cpu

Blue is high priority task
Green is next high priority task
Red is lower priority task

All three task ready to run at starting but Blue Led Task is a high priority task. CPU execute it first

When does blue led task preempt. I mean at what time?

If you just want three LEDs flashing at different frequencies, you don’t ven need to worry about creating these threads with different priorities. The scheduler is extremely good at doing its job, and when we change the priority of a task we are effectively hijacking the scheduler and therefore we have to consider every decision that the scheduler will make.

The higher a task’s priority means the more attention it is given by the scheduler. When exactly the task is given processing time is entirely in the hands of the operating system; we can tell the system that we really want it to happen at a given interval, but that will depend upon whether or not the task is given run time due to other tasks having higher priority.

Rule of thumb with tasks: don’t mess with priority unless you have to.

The higher the tasks priority is, the shorter the processing time should be.

Think about ISRs, they are so important (generally the highest priority achievable on the device) that they just interrupt anything that is already running, however the routine itself must run as quickly as possible in order for the rest of the system to be able to carry on with what it was doing.

When you have a task running with elevated priority, you must make sure that the task is dormant (in a non-blocking manner) long enough for other lower priority tasks to run.

1 Like

I have read the following page thoroughly and I understand the details of each state. but when i compare my example with the given state in the page i get stuck

For my LED example here I don’t understand in which state the task goes.

What exactly are you trying to do?

This program (in message 11) has a couple of problems that are going to give it major issues.

First, it uses vTaskDelayUntils without initializing the memory cell. This causes all sorts of problems, and can just short circuit the delays because the system thinks it is very far behind, and just makes the task run through.

The second problem is having two vTaskDelayUntils in a single loop doesn’t do what you want. Remember, vTaskDelayUntil works by incrementing the time in the memory cell by the delay and then delays until that timestamp, so the shorter delay will immediately get into the ‘fallen behind’ mode. I think the inner frequency delay really wants to be a plain vTaskDelay to always delay for 10ms, and the outer loop want the vTaskDelayUntil to keep the period stable even if the system gets busy (and fix the difference between lastFlash and lastRun)

I’m not entirely certain what initializing the memory cell means here @richard-damon?

The latFlash member is misnamed (doh!)

TickType_t lastFlash = xTaskGetTickCount();

should read

TickType_t lastRun = xTaskGetTickCount();

Then there is the omission of setting up the flashMarker (is this what you meant by without initializing the memory cell?)

while(true)
   {
       digitalToggle(led_pin);
       vTaskDelayUntil(&flashMarker, xInnerFrequency );
       digitalToggle(led_pin);

       // other stuff omitted
   }

should also have been

while(true)
   {
       flashMarker = xTaskGetTickCount();
       digitalToggle(led_pin);
       vTaskDelayUntil(&flashMarker, xInnerFrequency );
       digitalToggle(led_pin);

       // other stuff omitted
   }

@richard-damon, is vTaskDelay non-blocking? -I guess I could/should go read the documentation; I had it in my mind that vTaskDelay is a blocking call, but thinking about it, that makes little sense.

I thinkk that

  • vTaskDelayUntil
    “sleeps” the thread at least until the specified period has elapsed and its return value (bool ?) indicates whether or not the specified period had elapsed prior to the thread being “woken up”

  • vTaskDelay
    “sleeps” the thread for the specified number of ticks

So, now thinking it through (out loud and in a public forum :woozy_face:) you are absolutely correct, there is no need for vTaskDelayUntil for the flash period, and if I’d paid attention to what the code is saying, I would have realised that vTaskDelay would suffice.

@skyr I highly recommend working through the Modern Embedded Systems Programming Course by Miro Sameck, each video is roughly 20-30 minutes long and I think a really good resource for learning about embedded systems programming from the ground up.

I cannot recall off the top of my head which lesson it is in, but he covers the concept of scheduling extremely well -it might be the lesson in which he introduces real time operating systems.

I personally think this course (or one like it) is essential viewing.

Setting it to a value. That is part of the protocol for using vTaskDelayUntil, the variable needs to be set to the initial value of the tick counter (or at least assume that to be 0, which mostly works for now).
If the variable starts at a random value (actually likely the stack fill value if that is enabled) the vTaskDelayUntil will start off thinking it is WAY behind and making it a non-blocking 0 delay until it cycles enough times to catch up.

There is no requirement that high priority tasks “run faster” than low priority tasks. You could easily have a high-priority task that runs once a minute, while a lower-priority task is running every 100 ms. Now, if the high-priority task takes too long to run, that will interfere with the lower-priority task finishing on time. Priority often is more related to response time, than its periodic rate (jitter tolerance would be the factor for simple things like flashers).

It might well be, but would that invalidate the question somehow?

Isn’t the whole point of a forum for people to discuss ideas and topics? Where else do you think the OP should go to find out the information s/he is after?

Would it hurt to try and find out a little more about the problem the OP is trying to resolve, and possibly help them to overcome it? So what if they are a shool/college/university student?