01.初识freeRTOS
02.FreeRTOS的移植
03.FreeRTOS系统配置
04.FreeRTOS任务创建与删除
05.FreeRTOS任务挂起与恢复
06.FreeRTOS中断管理
07.FreeRTOS列表与列表项
08.FreeRTOS任务调度与任务切换
09.FreeRTOS时间片调度与任务相关函数
10.FreeRTOS队列操作
11.FreeRTOS信号量操作
12.FreeRTOS队列集和事件标志组
13.FreeRTOS任务通知
14.FreeRTOS软件定时器
15.FreeRTOS低功耗
16.FreeRTOS内存管理
文章目录
05. FreeRTOS任务挂起与任务恢复
1. FreeRTOS 挂起和恢复任务相关 API 函数
函数 | 描述 |
---|---|
vTaskSuspend() | 挂起任务 |
vTaskResume() | 恢复被挂起的任务 |
xTaskResumeFromISR() | 在中断中恢复被挂起的任务 |
-
函数vTaskSuspend()
此函数用于挂起任务,若使用此函数,需要在
FreeRTOSConfig.h
文件中将宏NCLUDE_vTaskSuspend
配置为1
。无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复。此函数并不支持嵌套,不论使用此函数重复挂起任务多少次,只需调用一次恢复任务的函数,那么任务就不再被挂起。函数原型如下所示: -
函数vTaskResume()
此函数用于在任务中恢复被挂起的任务,若使用此函数,需要在
FreeRTOSConfig.h
文件中将宏INCLUDE_VTaskSuspend
配置为1
。不论一个任务被函数vTaskSuspend()
挂起多少次,只需要使用函数vTaskResume()
恢复一次,就可以继续运行。函数原型如下所示: -
函数xTaskResumeFromISR()
此函数用于在中断中恢复被挂起的任务,若使用此函数,需要在
FreeRTOSConfig.h
文件中将宏INCLUDE_xTaskResumeFromISR
配置为1
。不论一个任务被函数vTaskSuspend()
挂起多少次,只需要使用函数vTaskResumeFromISR()
恢复一次,就可以继续运行。函数原型如下所示:
2. vTaskSuspend源码分析
-
需将宏
INCLUDE_vTaskSuspend
配置为 1// 使能挂起任务 #define INCLUDE_vTaskSuspend 1
-
根据任务句柄获取任务控制块,如果任务句柄为NULL,表示挂起任务自身
pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
-
将要挂起的任务从状态列表中移除
//3.将要挂起的任务从状态列表中移除 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } else { mtCOVERAGE_TEST_MARKER(); } //3.将要挂起的任务从事件列表中移除 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); } else { mtCOVERAGE_TEST_MARKER(); }
-
将待挂起任务的任务状态列表插入挂起任务列表末尾
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); #if ( configUSE_TASK_NOTIFICATIONS == 1 ) { BaseType_t x; for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) { //如果待挂起任务在等待,停止等待,直接赋值为0 if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) { pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION; } } } #endif
-
判断任务调度器是否在运行
//如果在运行,则更新下一次阻塞时间,防止被挂起任务为下一次阻塞超时任务 if(xSchedulerRunning != pdFALSE) { taskENTER_CRITICAL(); { prvResetNextTaskUnblockTime(); } taskEXIT_CRITICAL(); } else { mtCOVERAGE_TEST_MARKER(); }
-
如果挂起的是当前任务,且调度器正在运行,需要进行一次任务切换,否则判断挂起任务数
if( pxTCB == pxCurrentTCB ) { //且调度器正在运行,需要进行一次任务切换 if( xSchedulerRunning != pdFALSE ) { configASSERT( uxSchedulerSuspended == 0 ); portYIELD_WITHIN_API(); } //若没有运行,判断挂起任务数是否等于任务总数 //若相等,当前控制块赋值为NULL //若不相等,寻找下一个最高优先级任务 else { if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) { pxCurrentTCB = NULL; } else {