一、前言

在 FreeRTOS 中,任务(Task)是系统运行的基本单位。

当系统中存在多个任务时:

  • 哪个任务先运行?
  • 哪个任务更重要?
  • 如何保证关键任务及时执行?

这些问题都由 任务优先级(Priority) 决定。

但是很多初学者会有一个误区:

优先级越高越好,所有重要任务都设置最高优先级。

这种理解是不正确的。

正确理解:

任务优先级表示任务竞争 CPU 时的优先权,而不是简单代表任务的重要程度。


二、任务优先级是什么?

创建任务时:

xTaskCreate(
    TaskFunction,
    "TaskName",
    StackSize,
    NULL,
    Priority,
    NULL
);

其中 Priority 就是任务优先级。

例如:

xTaskCreate(
    ControlTask,
    "Control",
    512,
    NULL,
    5,
    NULL
);

表示 ControlTask 优先级为 5


三、高优先级任务会发生什么?

假设:

  • Task A 的 Priority = 5
  • Task B 的 Priority = 2

两个任务同时处于 Ready 状态:

  • Task A Ready
  • Task B Ready

那么 FreeRTOS 会优先运行 Task A,因为 5 > 2

但是,高优先级任务并不会永久占用 CPU。

原因:任务运行过程中会:

  • 延时
  • 等待消息
  • 等待信号量
  • 等待事件

进入阻塞状态。

例如:

void ControlTask(void *argument)
{
    while(1)
    {
        Control();

        vTaskDelayUntil(
            &lastWakeTime,
            pdMS_TO_TICKS(1)
        );
    }
}

执行过程:

  1. 执行控制算法
  2. 等待 1ms
  3. CPU 运行其他任务
  4. 1ms 后继续执行

所以:

高优先级 + 合理阻塞,才是正确设计。


四、Task 的四种状态

1. Running

正在运行:

CPU
 |
 ↓
Task

2. Ready

准备运行。

例如:

  • Task A Ready
  • Task B Ready

等待 CPU 调度。

3. Blocked

阻塞状态。

例如:

vTaskDelay();

或者:

xQueueReceive(
    Queue,
    &data,
    portMAX_DELAY
);

任务暂停等待。

4. Suspended

挂起状态:

vTaskSuspend();

任务停止运行。


五、为什么控制任务通常需要高优先级?

例如控制算法 1ms 执行一次,要求:

  • 周期稳定
  • 延迟小
  • 实时性高

如果控制任务经常被低优先级任务影响,可能导致:

  • 控制周期波动
  • 系统响应变差

所以通常:

  • 控制任务 → 较高优先级

六、通信任务优先级设计

通信任务例如:

  • UART
  • CAN
  • SPI

特点:可能不是固定周期运行。

更多情况:

  1. 等待数据
  2. 数据到达
  3. 处理

所以通常使用 中等优先级 即可。


七、调试任务优先级设计

例如串口打印:

printf();

特点:

  • 不影响核心功能
  • 可以延迟

因此通常使用 低优先级,例如 DebugTask 的 Priority = 1。


八、一个常见优先级设计

例如:

优先级任务类型
10控制任务
8通信任务
6传感器任务
3普通处理任务
1调试任务

设计原则:

实时性越高,优先级越高。


九、不要所有任务使用同一个优先级

错误示例:

ControlTask = 10
CommunicationTask = 10
DebugTask = 10
SensorTask = 10

问题:系统无法体现任务差异。

也不要所有任务都设为 1,因为关键任务和普通任务没有区别。


十、优先级不是越多越好

例如 STM32 可能支持 0~15,但是工程中不需要全部使用。

建议留出调整空间:

  • 10
  • 8
  • 5
  • 2
  • 1

十一、优先级反转问题

假设:

  • 低优先级任务 Task A 获取了 Mutex 资源锁
  • 此时高优先级任务 Task B 也需要这个资源

结果:

  • Task B 等待
  • Task A 慢慢执行

导致高优先级任务反而被低优先级任务影响,这叫 优先级反转

FreeRTOS 的 Mutex 提供 Priority Inheritance(优先级继承) 机制解决这个问题。


十二、任务优先级设计原则总结

原则 1

实时性越高,优先级越高。

例如:

  • 控制
  • 传感器
  • 通信
  • 显示
  • 打印

原则 2

高优先级任务不能一直运行。

应该:

  1. 执行
  2. 阻塞
  3. 让出 CPU

原则 3

优先使用阻塞机制。

例如不要:

while(1)
{
    if(flag)
    {

    }
}

而使用:

xSemaphoreTake();

或者:

xQueueReceive();

十三、本节总结

FreeRTOS 中 Priority 表示:

任务竞争 CPU 时的优先权。

优秀的系统设计不是所有任务高优先级,而是根据实时性合理分配。

最终目标:让系统稳定、实时、易维护。

控制任务
    ↑
高优先级

通信任务

普通任务

调试任务
    ↑
低优先级

下一节将学习:

STM32 + FreeRTOS 课程(4):Task 设计方法与系统架构

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐