FreeRTOS筆記(八)任務切換
文章目錄
上一文連結:FreeRTOS筆記(七)開啟排程器
在上一文中,提到了pxCurrentTCB
會在任務建立和任務切換的時候被改變,並且查看了任務建立,現在再來檢視任務切換,FreeRTOS的任務切換依賴一個PendSV
PendSV
,不得不提一個相關的中斷SVC
。
01 - SVC和PendSV
1.1 - SVC中斷
SVC
是系統服務呼叫,這是一個改名,在ARM7~ARM11這些系列中,系統服務呼叫稱為SWI
,可以進入ARM處理器的其中一個異常模式,作業系統特權模式,在這個模式下可以操作任何硬體資源。
在ARM針對高效能低功耗的新系列CM3/4中,SWI
被改名為SVC
,只是名字變了,其餘內容都一樣。
1.2 - PendSV中斷
與SVC
相關的是PendSV
中斷,稱為可懸起的系統呼叫。兩者不同之處在於響應速度,SVC
中斷是要求被立刻得到響應的,而PendSV
PendSV
中斷可以先“懸起”,待其它重要中斷被執行完成後再處理它。
懸起PendSV的方法是:手工往NVIC的PendSV懸起暫存器中寫1,懸起後,如果優先順序不夠其它中斷高,則將延遲等待執行。
PendSV
中斷這種可以被延遲執行的特性,非常適合用於任務切換。原因很簡單,當一個外部中斷正在被執行的時候,如果此時進行任務切換,意味著要先執行任務,而中斷要被延遲執行,這違背了FreeRTOS實時作業系統的概念,所以絕不允許在中斷活躍期進行任務切換。
一個簡單的解決辦法是使用SysTick
週期性中斷進行任務切換,而在切換之前檢查是否有中斷執行,但是弊端在於,如果這個中斷的頻率和SysTick
改良的辦法是在
SysTick
中斷裡面懸起PendSV
中斷,等這些重要的中斷執行完成後,再進行任務切換,《M3 權威指南》中的一個圖片很好地解釋了這個過程
02 - 任務切換
2.1 - 上下文
任務切換的本質是任務上下文的切換,上文其實就是待切出任務(當前正在執行)的TCB
和相關暫存器狀態,下文就是待切入(搶佔)任務的TCB
和相關暫存器狀態。
暫存器是寶貴資源,某個時刻只能儲存某個任務的值,要使得當前任務的暫存器狀態得到保留,需要把當前的暫存器壓棧,恢復的時候再彈出到暫存器,這樣一個暫存器就可以不斷使用了。
2.2 - 切換場合
發生任務切換的場合有2個,一個是優先順序搶佔,另一個是時間片輪轉。在FreeRTOS中的表達為:
系統呼叫 ⇌ 優先順序搶佔
SysTick中斷 ⇌ 時間片輪轉
其中優先順序搶佔不一定是高優先順序搶佔,可能的情況還有任務呼叫系統API主動放棄CPU,讓其它任務先行等等。而時間片輪轉發生在相同優先順序的任務中,SysTick
中斷是FreeRTOS的週期性中斷,每隔一段時間就會發生中斷,排程器需要在裡面執行一些自身的程式。
無論是哪個場合,最終都需要PendSV
中斷的處理,比如系統呼叫taskYIELD()
,跟蹤原始碼可以發現設定如下
taskYIELD()
portYIELD()
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
而跟蹤SysTick
中斷服務函式最終也會發現有一樣的設定
SysTick_Handler()
xPortSysTickHandler();
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
最終都是portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
,意思是手工往NVIC的PendSV懸起暫存器中寫1。
2.3 - PendSV_Handler
因為任務切換最終都會發生PendSV
中斷,在PendSV
中斷服務函式中進行,中斷服務函式為PendSV_Handler
,但是在FreeRTOSConfig.h中被改名為xPortPendSVHandler
,內容使用匯編編寫的,它主要的工作如下
比較關心的是改變pxCurrentTCB
(回顧上一文),用到了一個函式vTaskSwitchContext()
,呼叫層次下
vTaskSwitchContext()
taskSELECT_HIGHEST_PRIORITY_TASK()
portGET_HIGHEST_PRIORITY() //得到高優先順序任務
listGET_OWNER_OF_NEXT_ENTRY() //設定pxCurrentTCB
到此,在PendSV_Handler
中斷服務函式中,就完成了任務的切換。
03 - 總結
- SVC中斷就是軟中斷,給使用者提供一個訪問硬體的介面
- PendSV中斷相對SVC來說,是可以被延遲執行的,用於任務切換
- 任務切換可以發生在系統呼叫中,也可以發生在時間片輪轉中
- 無論哪個情況,任務切換最終都會進入PendSV中斷服務函式
- 任務切換的過程為:儲存現場、跳轉到下一個任務、恢復現場