FreeRTOS学习(十):任务调度器挂起与恢复机制详解
文章目录
- FreeRTOS学习(十):任务调度器挂起与恢复机制详解
- 简介
- 一、 任务挂起与恢复的API函数
- 1.1 任务挂起函数
- 1.2 任务恢复函数
- 二、重要特性
- 与临界区的区别
- 资源保护
- 三、任务切换实例
- 生活中的类比
- 实际代码示例
- 共享资源场景
- 为什么需要任务挂起?
- 数据一致性问题
- 使用任务挂起后
- 运行效果
- 总结
简介
在FreeRTOS中,任务挂起和恢复是重要的任务管理机制。通过使用vTaskSuspendAll()和xTaskResumeAll()这两个API函数,我们可以实现任务的挂起和恢复操作
一、 任务挂起与恢复的API函数
1.1 任务挂起函数
vTaskSuspendAll();
这个函数用于挂起任务调度器。
1.2 任务恢复函数
xTaskResumeAll();
这个函数用于恢复任务调度器的运行。
二、重要特性
与临界区的区别
与临界区保护不同,任务挂起机制具有以下特点:
- 挂起调度器时不会关闭中断
- 更加灵活的任务管理方式
- 适用于需要临时暂停任务调度的场景
资源保护
- 任务挂起机制主要用于防止任务间的资源争夺
- 中断仍然可以正常响应,不影响系统的实时性
- 提供了一种轻量级的任务同步方式
三、任务切换实例
生活中的类比
想象你正在一家餐厅工作,需要同时处理多个任务:
- 任务1:接待顾客点餐
- 任务2:制作饮品
- 任务3:结算账单
就像一个服务员需要在这些工作之间切换一样,FreeRTOS也需要在不同的任务之间进行切换
实际代码示例
共享资源场景
假设我们有一个简单的温度监控系统,包含两个任务:
- 温度采集任务
- 数据显示任务
// 定义共享资源
float currentTemperature = 0.0;
// 温度采集任务
void vTaskTemperatureSample(void *pvParameters)
{
float tempValue;
while(1)
{
// 读取温度传感器
tempValue = ReadTemperatureSensor(); // 假设这是读取传感器的函数
// 更新共享资源前挂起调度器
vTaskSuspendAll();
currentTemperature = tempValue; // 更新全局温度变量
xTaskResumeAll(); // 恢复调度器
vTaskDelay(pdMS_TO_TICKS(1000)); // 每秒采样一次
}
}
// 显示任务
void vTaskDisplay(void *pvParameters)
{
float tempToDisplay;
while(1)
{
// 读取共享资源前挂起调度器
vTaskSuspendAll();
tempToDisplay = currentTemperature; // 读取全局温度变量
xTaskResumeAll(); // 恢复调度器
// 显示温度值
printf("Current Temperature: %.2f°C\n", tempToDisplay);
vTaskDelay(pdMS_TO_TICKS(500)); // 每500ms更新一次显示
}
}
// 主函数
int main(void)
{
// 创建任务
xTaskCreate(vTaskTemperatureSample, "TempSample", 1000, NULL, 2, NULL);
xTaskCreate(vTaskDisplay, "Display", 1000, NULL, 1, NULL);
// 启动调度器
vTaskStartScheduler();
return 0;
}
为什么需要任务挂起?
数据一致性问题
如果不使用任务挂起机制,可能会出现以下问题:
假设正在执行这样的操作序列:
- 温度采集任务正在更新currentTemperature
- 还没更新完,任务切换发生
- 显示任务读取了一个"更新到一半"的温度值
- 导致显示错误的数据
使用任务挂起后
使用vTaskSuspendAll()和xTaskResumeAll()后:
- 温度采集任务在更新温度时挂起调度器
- 确保温度更新操作不会被打断
- 显示任务在读取温度时也挂起调度器
- 确保读取到的是完整的温度数据
运行效果
Current Temperature: 25.30°C
Current Temperature: 25.31°C
Current Temperature: 25.32°C
每次显示的温度值都是完整的、一致的数据。
总结
FreeRTOS的任务挂起与恢复机制提供了一种灵活的任务管理方式,相比临界区保护更加轻量级,同时保持了中断响应能力。在需要防止任务切换但又不想完全关闭中断的场景下,可以很好的保证这个任务做完为止。