CM3 的堆棧分為兩個:主堆棧和進程堆棧。
那么,這兩個棧分別在什么情況下使用呢?
我們看一下CM3的控制寄存器(CONTROL):控制寄存器用於定義特權級別,還用於選擇當前使用哪個堆棧指針。
CONTROL[1]
在 Cortex‐M3 的 handler 模式中, CONTROL[1]總是 0。在線程模式中則可以為 0 或 1。
僅當處於特權級的線程模式下,此位才可寫,其它場合下禁止寫此位。改變處理器的模式也有其它的方式:在異常返回時,通過修改 LR 的位 2,也能實現模式切換。
而在uC/OS-II中利用的就是 LR 的位 2 來進行堆棧模式的切換,其實我們在上一篇文中也有說到,就是 PendSV_Handler_Nosave 中的這條指令 ORR LR, LR, #0x04 將位 2 賦 1,這樣退出異常時切換回 PSP ,之后就可以完成任務的切換。
響應異常的第一個動作,就是自動保存現場的必要部分:依次把 xPSR, PC, LR, R12 以及 R3‐R0 由硬件自動壓入適當的堆棧中:如果當響應異常時,當前的代碼正在使用 PSP,則壓入 PSP,即使用線程堆棧;否則壓入 MSP,使用主堆棧。
大家要記住,一旦進入了中斷服務程序,CPU 就將一直使用主堆棧(MSP)。
uC/OS-II 的任務,也可以叫做它的線程,使用的堆棧就是 PSP,低優先級任務到高優先級任務的切換也正是由 PSP 完成的。
當開發的程序比較簡單(CM3不跑系統的時候)時,可以從頭到尾都只使用 MSP。這時,只需要保證開出一個容量夠大的堆棧,再把 MSP 初始化到其頂即可——這也是單片機開發最常見的做法。