STM32 + FreeRTOS 课程(3):任务优先级设计详解
一、前言
在 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)
);
}
}
执行过程:
- 执行控制算法
- 等待 1ms
- CPU 运行其他任务
- 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
特点:可能不是固定周期运行。
更多情况:
- 等待数据
- 数据到达
- 处理
所以通常使用 中等优先级 即可。
七、调试任务优先级设计
例如串口打印:
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
高优先级任务不能一直运行。
应该:
- 执行
- 阻塞
- 让出 CPU
原则 3
优先使用阻塞机制。
例如不要:
while(1)
{
if(flag)
{
}
}
而使用:
xSemaphoreTake();
或者:
xQueueReceive();
十三、本节总结
FreeRTOS 中 Priority 表示:
任务竞争 CPU 时的优先权。
优秀的系统设计不是所有任务高优先级,而是根据实时性合理分配。
最终目标:让系统稳定、实时、易维护。
控制任务
↑
高优先级
通信任务
普通任务
调试任务
↑
低优先级
下一节将学习:
STM32 + FreeRTOS 课程(4):Task 设计方法与系统架构
更多推荐



所有评论(0)