關於rtos中任務切換時的程序流程


今天和一個小伙伴討論了一下基於cortex-m3內核的RTOS在任務切換時的程序流程,小伙伴說國內某搜索引擎都搜不到這類的信息,所以我才打算寫下來,硬件平台是stm32f1​。

這里的切換有兩種情況:

第一種:從main函數跳到任務一時的程序流程;

第二種:從任務一跳到任務二時的程序流程。

 

先說第一種:從stm32f1上電復位說起吧,上電復位之后,CPU執行以下代碼:

Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

可見代碼先去執行SystemInit()這個函數,執行結束之后去執行main()函數。我為什么要說這個呢,因為在《cortex-m3權威指南》里面有這樣一句:“主堆棧指針( MSP):復位后缺省使用的堆棧指針,用於操作系統內核以及異常處理例程(包括中斷服務例程)

也就是說當cpu復位之后執行的SystemInit()和main()函數時用的都是MSP。我為什么要提MSP,因為下面還有個PSP。

 

繼續說main()函數,執行main()函數的時候,肯定會執行一大堆初始化(這里就不多贅述初始化了些啥),然后去找優先級最高的任務,並把這個找到的任務賦給nextTask變量,這時會啟動任務調度——也就是觸發PendSV異常。注意到這里用的都是MSP

這里插一句任務切換的本質:“保存上一個任務的運行狀態,恢復下個任務的運行狀態”

觸發PendSV異常必然會去執行PendSV_Handler()異常處理函數,在這個函數里執行的就是上面這句紅字,但是從main函數到任務一的時候,是沒有上一個任務的,所以不需要保存上一個任務,直接恢復下一個任務就行。恢復下一個任務就是把下一個任務的運行狀態(這時任務一的運行狀態是該任務初始化完成的狀態)通過彈棧彈入CPU的寄存器里面然后占據CPU的控制權運行該任務,這時就不用MSP了(因為有專門給任務跑的棧),通過下面這句代碼 ORR LR, LR, #0x04  切換到PSP堆棧,就是下圖的第二位 並把它置1,這個PSP是啥呢,同樣在《cortex-m3權威指南》里面有這句解釋,進程堆棧指針( PSP):由用戶的應用程序代碼使用。這個PSP就是專門給任務用的棧指針,這個時候任務就在PSP上運行了。

 

 

這時就是任務一占據CPU的控制權在運行!

 

再來說第二種:當任務一占據了CPU的使用權在運行時,PendSV異常觸發需要切換到任務二。這時CPU會通過壓棧的方式把當前任務一的運行狀態(就是任務一占據cpu控制權時寄存器的值)壓入只屬於任務一的獨立棧中,這就是保存上一個任務的運行狀態;然后恢復下一個任務,任務二的運行狀態就是一開始在main()函數中初始化的狀態,cpu通過彈棧的方式這些保存在任務二獨立棧中的運行狀態數據  彈入CPU的寄存器,讓任務二占據CPU的控制權並運行。

 

當然了,在這里多說一句,觸發PendSV異常時執行的PendSV_Handler()函數時 用的是MSP指針運行的,任務一與任務二運行時用的是PSP指針。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM