FreeRTOS任务挂起与解除
生活随笔
收集整理的這篇文章主要介紹了
FreeRTOS任务挂起与解除
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?任務掛起的主要工作包括:
將任務從狀態列表中移除并掛接到掛起列表中
更新任務喚醒時間
如果掛起當前任務,需要請求切換
/* 掛起任務 */ void vTaskSuspend(TaskHandle_t xTaskToSuspend) {TCB_t *pxTCB;/* 進入臨界區 */taskENTER_CRITICAL();{/* 通過任務句柄獲取任務TCB */pxTCB = prvGetTCBFromHandle(xTaskToSuspend);traceTASK_SUSPEND(pxTCB);/* 將任務從狀態列表中移除,狀態列表中沒有任何任務 */if(uxListRemove(&(pxTCB->xStateListItem)) == (UBaseType_t)0){/* 檢查該優先級就緒列表中是否有任務,如果沒有將該優先級從當前任務優先級記錄中清除 */taskRESET_READY_PRIORITY(pxTCB->uxPriority);}else{mtCOVERAGE_TEST_MARKER();}/* 任務被掛接在事件列表中 */if(listLIST_ITEM_CONTAINER(&(pxTCB->xEventListItem)) != NULL){/* 將任務從事件列表中移除 */(void)uxListRemove(&(pxTCB->xEventListItem));}else{mtCOVERAGE_TEST_MARKER();}/* 將任務掛接到掛起列表中 */vListInsertEnd(&xSuspendedTaskList, &(pxTCB->xStateListItem));#if (configUSE_TASK_NOTIFICATIONS == 1){if(pxTCB->ucNotifyState == taskWAITING_NOTIFICATION){pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;}}#endif}/* 退出臨界區 */taskEXIT_CRITICAL();/* 當前調度器正在運行 */if(xSchedulerRunning != pdFALSE){/* 進入臨界區 */taskENTER_CRITICAL();{/* 更新下一個要解除阻塞的時間,防止該任務就是最近需要喚醒的任務 */prvResetNextTaskUnblockTime();}/* 退出臨界區 */taskEXIT_CRITICAL();}else{mtCOVERAGE_TEST_MARKER();}/* 該任務為當前任務 */if(pxTCB == pxCurrentTCB){/* 調度器正在運行 */if(xSchedulerRunning != pdFALSE){configASSERT(uxSchedulerSuspended == 0);/* 請求切換任務 */portYIELD_WITHIN_API();}/* 調度器沒有正在運行 */else{/* 所有任務都被掛起 */if(listCURRENT_LIST_LENGTH(&xSuspendedTaskList) == uxCurrentNumberOfTasks){/* 沒有當前任務可以運行了 */pxCurrentTCB = NULL;}/* 有部分任務沒有被掛起 */else{/* 任務切換上下文 */vTaskSwitchContext();}}}else{mtCOVERAGE_TEST_MARKER();} }?
?
解除任務掛起主要工作包括:
將任務從掛起列表重新加入就緒列表
任務優先級高于當前任務優先級,請求切換
/* 解除任務掛起 */ void vTaskResume(TaskHandle_t xTaskToResume) {TCB_t *const pxTCB = xTaskToResume;configASSERT(xTaskToResume);/* 當前任務不能被解除掛起,因為當前任務肯定正在運行 */if((pxTCB != pxCurrentTCB) && (pxTCB != NULL)){/* 進入臨界區 */taskENTER_CRITICAL();{/* 任務確實被掛起 */if(prvTaskIsTaskSuspended(pxTCB) != pdFALSE){traceTASK_RESUME(pxTCB);/* 將任務從掛起列表中移除 */(void)uxListRemove(&(pxTCB->xStateListItem));/* 將任務重新加入就緒列表 */prvAddTaskToReadyList(pxTCB);/* 任務優先級大于當前任務優先級 */if(pxTCB->uxPriority >= pxCurrentTCB->uxPriority){/* 請求切換 */taskYIELD_IF_USING_PREEMPTION();}else{mtCOVERAGE_TEST_MARKER();}}else{mtCOVERAGE_TEST_MARKER();}}taskEXIT_CRITICAL();}else{mtCOVERAGE_TEST_MARKER();} }?
?
帶中斷的任務掛起解除和不帶中斷的任務掛起解除之間的差別,在于任務優先級高于當前任務優先級的情況下也不可以立即請求切換任務,而是要等到下一節拍才能切換。
/* 在中斷中解除任務掛起 */ BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume) {BaseType_t xYieldRequired = pdFALSE;TCB_t * const pxTCB = xTaskToResume;UBaseType_t uxSavedInterruptStatus;configASSERT(xTaskToResume);portASSERT_IF_INTERRUPT_PRIORITY_INVALID();/* 進入臨界區(意味著不能進入SysTick中斷) */uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();{/* 任務確實被掛起 */if(prvTaskIsTaskSuspended(pxTCB) != pdFALSE){traceTASK_RESUME_FROM_ISR(pxTCB);/* 調度器沒有被掛起 */if(uxSchedulerSuspended == (UBaseType_t)pdFALSE){/* 該任務優先級高于當前任務優先級 */if(pxTCB->uxPriority >= pxCurrentTCB->uxPriority){/* 在下一個節拍時進行任務切換 */xYieldRequired = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}/* 將任務從掛起列表中移除 */(void)uxListRemove(&(pxTCB->xStateListItem));/* 將任務重新加入就緒列表 */prvAddTaskToReadyList(pxTCB);}/* 調度器被掛起 */else{/* 將任務加入掛起時就緒列表 */vListInsertEnd(&(xPendingReadyList), &(pxTCB->xEventListItem));}}else{mtCOVERAGE_TEST_MARKER();}}/* 退出臨界區 */portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);return xYieldRequired; }?
總結
以上是生活随笔為你收集整理的FreeRTOS任务挂起与解除的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu搭建nfs服务器
- 下一篇: STM32之定时器原理