RTOS 暂停任务-任务挂起与恢复
概述
FreeRTOS 提供了让任务暂停(也称为“挂起”)执行、恢复执行的 API。
任务暂停的API:
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
任务恢复执行的API:
void vTaskResume( TaskHandle_t xTaskToResume )
当对一个任务调用 vTaskSuspend()后,该任务将从执行处暂停执行。除非对该任务调用vTaskResume()否则该任务无法恢复执行。
注意:对一个任务多次调用vTaskSuspend()暂停,仅需要在一处调用vTaskResume()即可恢复该任务。
需求及功能解析
本小节主要介绍任务的暂停与恢复。
1)其中任务可以在自己的 TaskCode 中调用 vTaskSuspend(NULL) 自己挂起自己:
void process_event(void)
{
printf("suspend task1!\n");
vTaskSuspend(NULL);
}
2)在一个任务中强制挂起另一个任务:
// Use the handle to suspend the task.
if(task2 != NULL) {
vTaskSuspend(task2);
printf("Suspend task2!\n");
}
3)恢复任务:
vTaskResume(task2);
**注意,**恢复任务后,任务只是重新能够被任务调度器发现,即有机会得到执行;任务是否立即执行,取决于被恢复的任务的优先级别是否足够高,请回顾上一节关于任务调度器中对优先级的调度策略。
示例解析
示例输出:
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, Minimum free heap size: 295356 bytes
I (338) TASK2: task2_flag = 0, arg2 = 2
suspend task1!
Suspend task2!
Resume in 3 seconds...
Resume in 2 seconds...
Resume in 1 seconds...
Resume in 0 seconds...
I (4348) TASK2: task2_flag = 1, cnt= 0
task1 wakeup!
示例输出与程序的执行顺序一致,即挂起任务 task1、task2 后,两者停止输出 log,待计时结束后,任务恢复后,两任务从暂停处继续向下执行:
// code
if(task2 != NULL) {
vTaskSuspend(task2);
printf("Suspend task2!\n");
}
for (int i = 3; i >= 0; i--) {
printf("Resume in %d seconds...\n", i);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
vTaskResume(task2);
vTaskResume(task1);
讨论
可以通过延时函数改变任务挂起、恢复的时机,或者改变任务的优先级,观察对两任务的 log 的影响,理解挂起、恢复的运行机制。
总结
1)当对一个任务调用 vTaskSuspend()后,该任务将从执行处暂停执行。除非对该任务调用vTaskResume()否则该任务无法恢复执行。
2)对一个任务多次调用vTaskSuspend()暂停,仅需要在一处调用vTaskResume()即可恢复该任务。
3)任务暂停后,调度器将不会赋予该任务CPU使用权,任务恢复后,调度器将根据该任务的优先级决定任务是否可以使用CPU而得到执行。
4)任务恢复后,任务从暂停处继续向下执行。
资源链接
1)Learning-FreeRTOS-with-esp32 系列博客介绍
2)对应示例的 code 链接 (点击直达代码仓库)
3)下一篇:RTOS 删除任务