FreeRTOS Arduino: Changing the Priority of a Task

In this series of FreeRTOS with Arduino tutorials, today we will learn how to change task priority during program execution or after the scheduler has been started. Last tutorial, we have seen how to create tasks with FreeRTOS API and Arduino. We have seen we can also define task priority while creating a task with vCreateTask() function. But during program execution, we may also want to change the priority using FreeRTOS API.

vTaskPrioritySet() API Function

vTaskPrioritySet() is used to set task priority after the scheduler has been started.

Before using this API, make sure that INCLUDE_vTaskPrioritySet is set to 1 in FreeRTOSConfig.h header file.

How to delete Task with FreeRTOS API using Arduino

This is a prototype of task priority changing function:

void vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority );

The first argument is a handle to the task which priority we want to change. While creating a task with xTaskCreate() API function, priority is also defined. Alternatively, a task can change its own priority by passing NULL in place of a valid task handle.

The second argument defines the task’s priority level. The maximum priority a task can attain is set with (configMAX_PRIORITIES – 1. Here configMAX_PRIORITIES is constant that can be set using FreeRTOSConfig.h header file.

Acquiring Task Priority

uxTaskPriorityGet() API function can be used to get the level task priority.

Before using this API, make sure that INCLUDE_uxTaskPriorityGet is set to 1 in FreeRTOSConfig.h header file.

This is a prototype of a task priority get function. Similar to vTaskPrioritySet(), we pass handler as a input to this function to which priority we want to know.

UBaseType_t uxTaskPriorityGet( TaskHandle_t pxTask );

Tasks Priority Changing Example Arduino

In this example, we use two tasks in order to demonstrate the use of vTaskPrioritySet() API function. We create two task one with higher priority and one with low priority. We change their priorities using their reference handlers.

First, these lines adds libraries of FreeRTOS and tasks. We also define prototypes for two tasks such as Task1 and Task2.

#include <Arduino_FreeRTOS.h>
#include <task.h>
void Task1( void *pvParameters );
void Task2( void *pvParameters );

We should also define reference handlers to these two tasks. Because we use these TaskHandle_t type variables to change task priority.

TaskHandle_t TaskHandle_1; // handler for Task1
TaskHandle_t TaskHandle_2; // handler for Task2

This code creates two tasks with different priorities. Task1 has the highest and Task2 has the lowest priority. Hence, Task1 will be the first one in the running state selected by the FreeRTOS scheduler.

Serial.begin(9600); // Enable serial communication library.
xTaskCreate(Task1, "LED1", 100, NULL, 2, &TaskHandle_1); // Create Task1 with priority=2
xTaskCreate(Task2, "LED2", 100, NULL, 1, &TaskHandle_2); // Create Task1 with priority=1
vTaskStartScheduler(); // start FreeRTOS scheduler 

This routine defines Task1. Firstly, we get the priority of the task using uxTaskPriorityGet() and store it in uxPriority variable of type UBaseType_t. After that inside the while(1) loop, it prints a string “Task1 is running and about to raise Task2 Priority”. In the end, we call vTaskPrioritySet() to raise the priority of Task2 by one higher than Task1.

Therefore, Task2 priority will become higher than the Task1. In response, Task1 enters the Ready state and Task2 enters the running state.

//definition of Task1
void Task1(void* pvParameters)
{
     UBaseType_t uxPriority = uxTaskPriorityGet( NULL );
    while(1)
    {
    Serial.println("Task1 is running and about to raise Task2 Priority");
    vTaskPrioritySet( TaskHandle_2, ( uxPriority + 1 ) );
   
    }
}

This routine defines Task2. Firstly, we get the priority of the task2 using uxTaskPriorityGet() and store it in uxPriority variable of type UBaseType_t. After that inside the while(1) loop, it prints a string “Task2 is running and about to lower Task2 Priority”. In the end, we call vTaskPrioritySet() to lower the priority of Task2 by one.

Therefore, Task1 priority will become higher than the Task2 again. In response, Task2 enters the Ready state, and Task2 enters the running state.

void Task2(void* pvParameters)
{
 UBaseType_t   uxPriority = uxTaskPriorityGet( NULL );
     while(1)
    {
    Serial.println("Task2 is running and about to lower Task2 Priority");
    vTaskPrioritySet( TaskHandle_2, ( uxPriority - 2 ) );
    
    }
  
}

Complete Arduino Code

#include <Arduino_FreeRTOS.h>
#include <task.h>
void Task1( void *pvParameters );
void Task2( void *pvParameters );

TaskHandle_t TaskHandle_1; // handler for Task1
TaskHandle_t TaskHandle_2; // handler for Task2


void setup() 
{
  Serial.begin(9600); // Enable serial communication library.

   xTaskCreate(Task1, "LED1", 100, NULL, 3, &TaskHandle_1);
   xTaskCreate(Task2, "LED2", 100, NULL, 2, &TaskHandle_2);
   vTaskStartScheduler();
}

void loop() 
{
  // put your main code here, to run repeatedly:

}

//definition of Task1
void Task1(void* pvParameters)
{
     UBaseType_t uxPriority = uxTaskPriorityGet( NULL );
    while(1)
    {
    Serial.println("Task1 is running and about to raise Task2 Priority");
    vTaskPrioritySet( TaskHandle_2, ( uxPriority + 1 ) );
   
    }
}
void Task2(void* pvParameters)
{
 UBaseType_t   uxPriority = uxTaskPriorityGet( NULL );
     while(1)
    {
    Serial.println("Task2 is running and about to lower Task2 Priority");
    vTaskPrioritySet( TaskHandle_2, ( uxPriority - 2 ) );
    
    }
  
}

Arduino Serial Monitor Output

Now copy this code to Arduino IDE and upload code to Arduino. After that open, Arduino Serial monitor, you will see output like this on Arduino Serial monitor:

how to change task priority using FreeRTOS and Arduino Serial Monitor

How Priority Changing Code works?

  • At the start, Task1 being the highest priority run first and enters the running state. After that, it prints out strings before raising the priority of Task2 to above its own priority. Because now Task2 runs and Task1 waits in the ready state.
  • Task2 enters the Running state as soon as it has the highest relative priority. Only one task can be in the Running state at any one time, so when Task 2 is in the Running state, Task1 is in the Ready state.
  • Task2 prints out “Task2 is running and about to lower Task2 Priority” before setting its own priority back down to below that of Task1.
  • Task2 setting its priority back down means Task 1 is once again the highest priority task, so Task1 re-enters the Running state, forcing Task 2 back into the Ready state.

Where to go Next?

2 thoughts on “FreeRTOS Arduino: Changing the Priority of a Task”

  1. Goode snippet always helps to programmer to understand basics and easy to build program. Beginner always loves it!

    Thanks!

    Reply

Leave a Comment