“野火FreeRTOS教程”第7章补充知识点-异常流程
一、知識點
1. Cortex-M3/4在復位后CONTROL寄存器初始值為0,也就是說MCU會處于線程模式、具有特權訪問權限且使用主棧指針(MSP)。
2. 當進入異常時CM3會自動入棧,如下圖所示:
?3. 當異常返回時CM3會自動出棧,如下圖所示:
?4. CM3進入異常或者中斷服務函數(ISR)時,R14(LR)會被自動更新為EXC_RETURN,且EXC_RETURN具有以下位域。
當發生程序調用后,LR為子程序的返回地址。(程序調用的實質是將PC賦值給LR,執行完子程序后,又將LR賦值給PC。這些由硬件自動完成)
二、教程分析
1. 文中指出任務棧在初始化完成后,如下狀態,可以看到此時棧頂指針指在最低地址處,當然這時PSP還沒有被賦值為棧頂指針。
圖、二-1?2. 接下來調用"SVC 0",產生SVC異常服務,教程中SVC異常服務函數如下。
按照出現順序,這里用到知識點2圖8.7、知識點4、知識點3圖8.10(#1出棧時)。進入SVC異常服務函數前,CPU會自動將R0,…,xPSR(8個32位寄存器)存儲到MSP指向空間,R4-R11不會自動入棧。當然在SVC異常服務函數中,我們是去啟動第一個任務,因此主要考慮出棧操作,如下。
- 上圖(2)-(4)是獲取任務棧頂指針,(5)LDMIA是指先加載指針指向內容至CPU寄存器中,然后增加指針(加載一個內容增加一個指針,!表示指針變量會更新),(6)把當前的棧指針賦值給PSP,(9)給EXC_RETURN或上0xd,表示“返回線程模式且返回后使用進程棧(PSP)”。
- 當使用"bx r14"后會觸發異常返回機制,CPU會使用PSP來完成自動出棧,即將R0,…,xPSR存儲到PSP指向空間,CPU也是使用LDMIA完成出棧操作的,因而此時PSP指向任務棧的位置如下。?
- 此后CPU會取走R15(PC),程序自然跳轉到任務1循環體中執行。
3.??任務1入棧
在任務1循環體的最后觸發了PendSVC異常服務,這里用到知識點2圖8.8,知識點3圖8.10(#1壓棧時和出棧時)。教程中PendSVC異常服務函數如下。
圖、二-3- ?進入PendSVC異常服務函數前,CPU會自動將R0,…,xPSR存儲到PSP指向空間,CPU是使用STMDB完成入棧操作的,R4-R11不會自動入棧,此時PSP還是指向第一個任務的棧空間,如下圖。STMDB是指先減小指針,然后存儲CPU寄存器值至指針指向空間中(減小一個指針存儲一個內容,!表示指針變量會更新)。
- 剩下的R4-R11也需要使用STMDB手動入棧,見圖二-3中的(4)、(7)。
- 然后將R0的值賦值給第一個任務的棧頂指針,見圖二-3中的(5)、(6)、(8),以恢復任務棧頂指針為初始狀態,如圖二-1。(其實可以不用重新賦值任務的棧頂指針,因為沒有變過,但考慮到要邏輯嚴謹,還是重新賦值比較好)。此時的PSP、R0和第一個任務的棧頂指針狀態如下。
- ?到這里任務1的入棧已經完成。
?4.??任務2出棧
- ?接著看圖二-3,(9)其實就是保護EXC_RETURN的bit2不會變成0,因為一旦發生程序調用,R14即為子程序的返回地址,原本的EXC_RETURN就會被打亂,導致異常返回時,CPU的SP不一定就是PSP,所以必須加以保護。
- R3也要加以保護,因為它保存了一個指針變量(pxCurrentTCB)的地址,指向要(或正在)執行的任務控制塊。
- (12)將pxCurrentTCB指向第二個任務控制塊。
- 進入異常或中斷后,CPU自動使用主棧,因此(9)和(14)使用的SP就是MSP。
- (15)-(19)與二-2(SVC異常服務)是一樣的。
- 至于為什么最后沒有給EXC_RETURN或上0xd,其實EXC_RETURN_bit2沒改變過,當然你要或上0xd也可以。
5. 總結
?
總結
以上是生活随笔為你收集整理的“野火FreeRTOS教程”第7章补充知识点-异常流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022.08.09-docker容器网
- 下一篇: 论文引发的思考