FreeRTOS Getting Started Tutorial (Task Priority, Tick)


Preface

This article will teach you about task priority in FreeRTOS and understand what task priority is.

1. What is task priority?

In FreeRTOS, task priority is used to determine the execution order and scheduling order of tasks. The higher the task priority, the more frequently the task is scheduled for execution. FreeRTOS supports the use of integer values ​​to represent task priorities. The higher the integer value, the higher the priority.

Task priorities in FreeRTOS usually range from 0 to configMAX_PRIORITIES-1, where configMAX_PRIORITIES is a configuration constant indicating the maximum number of task priorities supported in the system.

You can view the task priority configuration macro in FreeRTOSconfig.h:
Insert image description here

2. How does FreeRTOS identify the executable tasks with the highest priority?

1.通用方法:

Implemented using C functions, it is the same code for all architectures. There is no limit on the value of configMAX_PRIORITIES. However
, the value of configMAX_PRIORITIES should be as small as possible, because the larger the value, the more memory and time are wasted.
Use this method when configUSE_PORT_OPTIMISED_TASK_SELECTION is defined as 0 or undefined.

2.架构相关的优化的方法:

Architecture-related assembly instructions can quickly find the highest bit of 1 from a 32-bit number. Using these instructions, you can quickly
find the highest priority tasks that can be run.
When using this method, the value of configMAX_PRIORITIES cannot exceed 32.
Use this method when configUSE_PORT_OPTIMISED_TASK_SELECTION is defined as 1

3. Clock Tick in FreeRTOS

The clock tick (Tick) in FreeRTOS is a basic time unit used to manage task scheduling and time-related functions. The concept of clock ticks is very important in real-time operating systems because it provides the basic unit of measurement of time, allowing tasks and timers to execute at predetermined intervals.

以下是有关FreeRTOS中时钟节拍的重要信息:

1. Unit of clock beat: Clock beat is an abstract unit of time, usually expressed as an integer value. It can be mapped to real time, but the accuracy and length of the clock ticks are configurable. In most cases, the clock tick is measured in milliseconds, but it can be configured for shorter or longer intervals, depending on the needs of the application.

2. Clock tick counter: FreeRTOS maintains a clock tick counter to track the number of clock ticks that have passed. This counter is usually a 32-bit value and can support a wide range of time tracking.

3. Task scheduling: Task scheduling and switching usually occur at multiples of clock beats. When the clock tick counter reaches the task's time interval (often called the task's delay or period), the task may be placed in a ready state for execution at the next task switch point.

4. Timer: The clock beat is also used for the timer function. By setting the timer period to a multiple of the clock beat, you can trigger scheduled tasks and events.

5. Configuration and customization: FreeRTOS allows users to configure the frequency and accuracy of clock ticks to suit the needs of specific applications. This can be done by modifying parameters in the FreeRTOS configuration file. For example, you can configure the clock beat to 1 millisecond, 10 milliseconds, or even shorter intervals to meet real-time requirements.

6. The clock beat plays a key role in FreeRTOS. It is not only used for task scheduling, but also for implementing scheduled waiting, timeout operations and time-related functions.

The Tick value in FreeRTOS is usually configured as 1ms:

Insert image description here

4. What is a time slice?

Time slice is a concept in the operating system scheduling algorithm, which is used to allocate processor time to multiple runnable tasks. It means that the operating system divides the execution time of the processor into small segments of fixed length, and each task obtains the execution time of the processor within a time slice.

5. How to switch tasks with the same priority

FreeRTOS adopts the time slice rotation scheduling strategy by default, assigning a fixed time slice to each task. The size of this time slice is 1ms. The size of the time slice can be modified by modifying the configTICK_RATE_HZ macro.

时间片大小(毫秒) = 1秒 / configTICK_RATE_HZ

Insert image description here

After Task1 finishes executing a time slice, a tick interrupt will occur, and then it will enter the tick interrupt processing function. In the tick interrupt, select the next interrupt to be executed. When the tick interrupt is executed, Task2 will be switched to execution.

6. Task priority experiment

// 任务句柄
TaskHandle_t Task1Handle;
TaskHandle_t Task2Handle;

// 任务函数
void Task1(void* pvParameters) {
    
    
  while (1) {
    
    
    vTaskDelay(1000);
    printf("Task1 is running\n");
  }
}

void Task2(void* pvParameters) {
    
    
  while (1) {
    
    
    vTaskDelay(1000);
    printf("Task2 is running\n");
  }
}

int main(void) {
    
    
  // 创建两个任务
  xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, &Task1Handle);
  xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, &Task2Handle);

  // 启动调度器
  vTaskStartScheduler();

  while (1) {
    
    
    // 主循环为空,所有的任务由 FreeRTOS 调度
  }
}

Because Task 2 has a higher priority than Task 1, Task2 is running will be printed first, and then Task1 is running, and so on.

7. Modify task priority

uxTaskPriorityGet() and vTaskPrioritySet() are functions in FreeRTOS used to get and set task priority.

uxTaskPriorityGet() 函数用于获取任务的当前优先级。它接受一个参数,即任务句柄,返回一个 UBaseType_t 类型的值,表示任务的当前优先级。

vTaskPrioritySet() 函数用于设置任务的优先级。它接受两个参数,第一个参数是要设置优先级的任务句柄,第二个参数是要设置的优先级值。这个函数没有返回值。

The following is a sample code using the uxTaskPriorityGet() and vTaskPrioritySet() functions:

TaskHandle_t Task1Handle;
TaskHandle_t Task2Handle;

void Task1(void* pvParameters) {
    
    
  while (1) {
    
    
    // 获取任务优先级
    UBaseType_t priority = uxTaskPriorityGet(NULL);
    printf("Task1 priority: %u\n", priority);

    vTaskDelay(pdMS_TO_TICKS(1000));
  }
}

void Task2(void* pvParameters) {
    
    
  while (1) {
    
    
    // 获取任务优先级
    UBaseType_t priority = uxTaskPriorityGet(NULL);
    printf("Task2 priority: %u\n", priority);

    // 设置任务优先级
    vTaskPrioritySet(Task1Handle, 2);

    vTaskDelay(pdMS_TO_TICKS(5000));

    // 恢复任务优先级
    vTaskPrioritySet(Task1Handle, 1);
  }
}

int main(void) {
    
    
  xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, &Task1Handle);
  xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, &Task2Handle);

  vTaskStartScheduler();

  while (1) {
    
    
    // 主循环为空,所有的任务由 FreeRTOS 调度
  }

In this sample code, we create two tasks Task1 and Task2, and use uxTaskPriorityGet() and vTaskPrioritySet() to get and set the task priority.

In Task1, we first use uxTaskPriorityGet(NULL) to get the priority of the current task and print it out through printf. Then use vTaskDelay() to delay for 1 second.

In Task2, we first get the priority of the current task, and then set the priority of Task1 to 2 through vTaskPrioritySet(Task1Handle, 2). Then after a delay of 5 seconds, the priority of Task1 is restored to 1 through vTaskPrioritySet(Task1Handle, 1).

By running this sample code, you will see that during the execution of the task, the task's priority acquisition and setting operations are performed, and the task's priority information is output through the print statement.

注意,在使用 uxTaskPriorityGet() 和 vTaskPrioritySet() 函数时,需要确保任务句柄是正确的,并且函数的调用时机是合适的,以避免潜在的问题和不一致性。

Summarize

This article will explain it here.

Guess you like

Origin blog.csdn.net/m0_49476241/article/details/133385983