FreeRTOS入门教程(任务优先级,Tick)

简介: FreeRTOS入门教程(任务优先级,Tick)

前言

本篇文章将带大家学习FreeRTOS中的任务优先级,并且了解什么是任务优先级,

一、什么是任务优先级

在FreeRTOS中,任务优先级用于确定任务的执行顺序和调度顺序。任务优先级越高,任务被调度执行的频率越高。FreeRTOS支持使用整数值来表示任务优先级,整数值越高,优先级越高。

FreeRTOS中任务优先级的范围通常是从0到configMAX_PRIORITIES-1,其中configMAX_PRIORITIES是一个配置常量,表示系统中支持的最大任务优先级数量。

在FreeRTOSconfig.h中可以查看到任务优先级的配置宏:

二、FreeRTOS如何分辨出优先级最高可运行的任务

1.通用方法:

使用C函数实现,对所有的架构都是同样的代码。对configMAX_PRIORITIES的取值没有限制。但

是configMAX_PRIORITIES的取值还是尽量小,因为取值越大越浪费内存,也浪费时间

configUSE_PORT_OPTIMISED_TASK_SELECTION被定义为0、或者未定义时,使用此方法。

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

架构相关的汇编指令,可以从一个32位的数里快速地找出为1的最高位。使用这些指令,可以快速

找出优先级最高的、可以运行的任务。

使用这种方法时,configMAX_PRIORITIES的取值不能超过32。

configUSE_PORT_OPTIMISED_TASK_SELECTION被定义为1时,使用此方法

三、FreeRTOS中的时钟节拍Tick

FreeRTOS中的时钟节拍(Tick)是一个基本的时间单位,用于管理任务调度和时间相关功能。时钟节拍的概念在实时操作系统中非常重要,因为它提供了时间的基本度量单位,允许任务和定时器按照预定的时间间隔执行。

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

1.时钟节拍的单位:时钟节拍是一个抽象的时间单位,通常表示为一个整数值。它可以映射到实际时间,但时钟节拍的精度和长度是可配置的。在大多数情况下,时钟节拍是以毫秒为单位的,但它可以配置为更短或更长的时间间隔,具体取决于应用程序的需求。

2.时钟节拍计数器:FreeRTOS维护一个时钟节拍计数器,用于跟踪已经过去的时钟节拍数。这个计数器通常是一个32位的值,可以支持大范围的时间跟踪。

3.任务调度:任务的调度和切换通常发生在时钟节拍的倍数上。当时钟节拍计数器达到任务的时间间隔(通常称为任务的延迟或周期)时,任务可能会被置于就绪状态,以便在下一个任务切换点执行。

4.定时器:时钟节拍也用于定时器功能。通过设置定时器的周期为时钟节拍的倍数,可以实现定时任务和事件的触发。

5.配置和定制:FreeRTOS允许用户配置时钟节拍的频率和精度,以适应特定应用的需求。这可以通过修改FreeRTOS配置文件中的参数来完成。例如,可以配置时钟节拍为1毫秒,10毫秒,甚至更短的时间间隔,以满足实时性要求。

6.时钟节拍在FreeRTOS中扮演了关键的角色,它不仅用于任务调度,还用于实现定时等待、超时操作和时间相关的功能。

FreeRTOS中的Tick值通常被配置为1ms:

四、什么是时间片

时间片(Time slice)是操作系统调度算法中的概念,用于分配处理器时间给多个可运行的任务。它是指操作系统将处理器的执行时间划分为固定长度的小段,每个任务在一个时间片内获得处理器的执行时间。

五、相同优先级任务怎么进行切换

在FreeRTOS默认采用了时间片轮转调度的策略,给每一个任务都分配一个固定的时间片,这个时间片的大小也就是1ms,可以通过修改configTICK_RATE_HZ这个宏来修改时间片的大小。

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

Task1执行完一个时间片后会发生一次tick中断,然后进入tick中断处理函数中,在tick中断中选择要执行的下一个中断,当执行完tick中断后就切换Task2执行。

六、任务优先级实验

// 任务句柄
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 调度
  }
}

因为任务2的优先级比任务1的优先级高所以会先打印Task2 is running,然后再打印Task1 is running,以此往复。

七、修改任务优先级

uxTaskPriorityGet() 和 vTaskPrioritySet() 是FreeRTOS中用于获取和设置任务优先级的函数。

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

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

以下是一个使用 uxTaskPriorityGet() 和 vTaskPrioritySet() 函数的示例代码:

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 调度
  }

在这个示例代码中,我们创建了两个任务 Task1 和 Task2,并使用 uxTaskPriorityGet() 和 vTaskPrioritySet() 进行任务优先级的获取和设置。

在 Task1 中,我们首先使用 uxTaskPriorityGet(NULL) 获取当前任务的优先级,并通过 printf 打印出来。然后使用 vTaskDelay() 延迟1秒钟。

在 Task2 中,我们首先获取当前任务的优先级,然后通过 vTaskPrioritySet(Task1Handle, 2) 将 Task1 的优先级设置为2。接着延迟5秒钟后,再通过 vTaskPrioritySet(Task1Handle, 1) 恢复 Task1 的优先级为1。

通过运行这个示例代码,将会看到在任务的执行过程中,任务的优先级获取和设置操作被执行,并通过打印语句输出任务的优先级信息。

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

总结

本篇文章就讲解到这里。


相关文章
|
传感器 调度 开发者
【Freertos基础入门】freertos任务的优先级
【Freertos基础入门】freertos任务的优先级
2097 0
|
7月前
|
芯片
MicroPython+ESP32 C3+ST7735S LCD屏 WIFI联网并显示时间
本案例基于ESP32 C3与ST7735S驱动的1.8寸TFT屏,实现WIFI连接显示、实时时间展示及中英文字符渲染。通过MicroPython驱动屏幕,支持自定义字库与彩色文字输出,适用于嵌入式图形显示应用。
971 1
MicroPython+ESP32 C3+ST7735S LCD屏 WIFI联网并显示时间
|
消息中间件 调度
FreeRTOS入门教程(任务状态)
FreeRTOS入门教程(任务状态)
1355 0
|
调度 开发者
【Freertos基础入门】2个Freertos的Delay函数
【Freertos基础入门】2个Freertos的Delay函数
2248 1
|
机器学习/深度学习 人工智能 编解码
【AI系统】MobileNet 系列
本文详细介绍 MobileNet 系列模型,重点探讨其轻量化设计原则。从 MobileNetV1 开始,通过深度可分离卷积和宽度乘数减少参数量,实现低延迟、低功耗。后续版本 V2、V3、V4 逐步引入线性瓶颈、逆残差、Squeeze-and-Excitation 模块、新型激活函数 h-swish、NAS 搜索等技术,持续优化性能。特别是 MobileNetV4,通过通用倒瓶颈(UIB)和 Mobile MQA 技术,大幅提升模型效率,达到硬件无关的 Pareto 最优。文章结合最新深度学习技术,全面解析各版本的改进与设计思路。
4286 8
|
存储 安全 开发工具
基于ESP32的便携式游戏机
基于ESP32的便携式游戏机
581 2
|
Ubuntu 网络协议 关系型数据库
|
存储 API 调度
FreeRTOS深入教程(任务创建的深入和任务调度机制分析)
FreeRTOS深入教程(任务创建的深入和任务调度机制分析)
2480 0
|
Linux
diff与patch的使用
diff与patch的使用
287 1
|
消息中间件 资源调度 算法
FreeRTOS最全教程(目录)
FreeRTOS最全教程(目录)
1816 1

热门文章

最新文章