vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
函數第一個參數為消息隊列等待插入鏈表,
void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
{
?? ?configASSERT( pxEventList );
?? ?/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
?? ?SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
?? ?/* Place the event list item of the TCB in the appropriate event list.
?? ?This is placed in the list in priority order so the highest priority task
?? ?is the first to be woken by the event. ?The queue that contains the event
?? ?list is locked, preventing simultaneous access from interrupts. */
?? ?vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );//將當前任務的事件屬性插入消息隊列等待插入鏈表
?? ?prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );//將當前任務的狀態屬性部分插入延時鏈表
}
結論:
也就是說一個任務有兩個屬性,
一個是狀態屬性,可能位于就緒列表,延時列表,掛起列表,其中一個
另一個是事件屬性,可能位于掛起等待列表,或者消息隊列等待列表
這種設計實現了事件與狀態管理的分離
以下是deepseek關于PendingReadyList的解釋,待證實供參考
FreeRTOS 會將?xPendingReadyList
(或類似機制)中的任務轉移出去,主要發生在以下兩個關鍵時機:
-
?調度請求發生時(任務切換前)?:當系統需要執行任務切換時(例如調用?
taskYIELD()
、調用某些可能導致任務切換的 API、中斷服務程序(ISR)結束時請求調度?portYIELD_FROM_ISR()
)18,調度器核心函數?vTaskSwitchContext()
?會被調用。在該函數的執行過程中,會檢查并處理?xPendingReadyList
28。 -
?系統節拍中斷(SysTick)結束時?:在系統節拍中斷服務程序(SysTick ISR)的執行流程中,當它處理完時間相關的任務(如更新阻塞任務的延時計時器、處理時間片輪詢)后,在退出中斷前通常會觸發一個 PendSV 中斷(通過向中斷控制寄存器寫入特定值)1。后續 PendSV 中斷服務程序被執行時,其主要工作就是執行上下文切換(任務切換),此時同樣會調用?
vTaskSwitchContext()
?函數,從而處理?xPendingReadyList
12。
?在?vTaskSwitchContext()
?中具體做了什么??
- ?檢查調度器狀態?:首先確認調度器未被掛起或鎖定,否則不能進行任務切換1。
- ?查找最高優先級就緒任務?:調用類似?
taskSELECT_HIGHEST_PRIORITY_TASK()
?的宏來查找下一個應該運行的任務18。 - ?處理 PendingReady List?:?正是在查找最高優先級就緒任務之前或過程中,調度器會檢查?
xPendingReadyList
?27。對于?xPendingReadyList
?中的每個任務:- 將其?
xEventListItem
?從?xPendingReadyList
?中移除。 - 根據該任務的優先級,將其?
xStateListItem
?插入到對應的優先級就緒列表 (pxReadyTasksLists[priority]
) 中2。至此,該任務就被真正轉移到了就緒態列表,具備了被調度執行的資格。
- 將其?
- ?選擇并切換任務?:完成?
xPendingReadyList
?的處理后,調度器繼續執行查找最高優先級就緒任務的操作(此時剛轉移過來的任務也參與了優先級比較),最終確定并切換到下一個要運行的任務 (更新?pxCurrentTCB
)18。
?為什么會有?xPendingReadyList
??
- ?分離事件與狀態管理?:
xEventListItem
?用于事件相關的阻塞和解阻塞操作(如等待信號量、隊列、事件組等),而?xStateListItem
?用于任務在狀態列表(就緒列表、阻塞列表等)中的管理2。 - ?效率與原子性?:當一個任務在?中斷服務程序(ISR)? 中被事件喚醒(如 ISR 釋放了一個信號量或向隊列發送了數據),該任務需要從阻塞態轉移到就緒態。直接在 ISR 中操作就緒列表 (
pxReadyTasksLists
) 會增加 ISR 執行時間,且可能涉及到復雜的臨界區管理。將其臨時放入?xPendingReadyList
?是一個輕量級的操作27。 - ?延遲處理?:實際的轉移操作(從?
xPendingReadyList
?到?pxReadyTasksLists
)被推遲到調度器下一次執行任務切換的上下文(在?vTaskSwitchContext()
?中)進行,這通常是在退出中斷后的任務級上下文或 PendSV 中斷中,此時進行復雜的狀態列表操作更安全、更高效,也確保了任務狀態變更的原子性28。
?總結:?
FreeRTOS 在 ?任務調度請求發生時(包括顯式調用?taskYIELD()
?或相關 API)? 和 ?系統節拍中斷(SysTick)觸發 PendSV 中斷后?,執行任務切換的核心函數?vTaskSwitchContext()
。?正是在?vTaskSwitchContext()
?函數中查找下一個要運行的任務之前,系統會檢查?xPendingReadyList
,將其中的所有任務轉移到它們對應優先級的就緒列表 (pxReadyTasksLists
) 中?。這種設計主要是為了高效、安全地處理從中斷上下文中喚醒的任務,分離事件處理和狀態管理12。