1. 程式人生 > >FreeRTOS筆記(八)任務切換

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中斷服務函式
  • 任務切換的過程為:儲存現場、跳轉到下一個任務、恢復現場