UCOS學習筆記——堆棧
堆棧
Cortex-M3堆棧操作
Cortex-M3使用的是“向下生長的滿棧”模型。堆棧指針SP指向最后一個被壓入堆棧的32位數值。在下一-次壓棧時,
SP先自減4
,再存入新的數值,如圖2.3.1所示。
POP操作剛好相反:先從SP指針處讀出,上一次被壓入的值,再把
SP指針自增4
。如圖2.3.2所示。
在進入ISR時,CM3會自動把一些寄存器壓棧,這里使用的是進入ISR之前使用的SP指針(MSP或者是PSP)。離開ISR后,只要ISR沒有更改過CONTROL[1],就依然使用先前的SP指針來執行出棧操作。
雙堆棧機制
我們已經知道了CM3的堆棧是分為兩個:主堆棧和進程堆棧, CONTROL[1]決定如何選擇。當CONTROL[1]=0時,只使用MSP, 此時用戶程序和異常handler 共享同一個堆棧。這也是復位后的缺省使用方式,如圖2.3.3所示。
當CONTROL[1]=1時,線程模式將不再使用PSP,而改用MSP(handler模式永遠使用MSP)
。此時,進入異常時的自動壓棧使用的是進程堆棧,進入異常handler后才自動改為MSP,退出異常時切換同psp,并日從講程堆棧十彈出數據,如圖2.3.4所示:
在特權級下,可以指定具體的堆棧指針,而不受當前使用堆棧的限制,示例代碼如下:
MRS RO,MSP ; 讀取主堆棧指針到RO MSR MSP,RO ; 寫入RO的值到主堆棧中 MRS RO,PSP ;讀取進程堆棧指針到RO MSR RO ;寫入RO的值到進程堆棧中
通過讀取PSP的值,OS就能夠獲取用戶應用程序使用的堆棧,進一一步地就知道了在發生異常時,被壓入寄存器的內容,而且還可以把其它寄存器進一步壓棧的書寫形式)。OS還可以修改PSP,用于實現多任務中的任務上下文切換。
Stack frames
在進入異常服務程序的時候會將一些數據壓入堆棧中,這些數據所占用的數據塊被稱為Stack frames,由于M3沒有FPU所以其Stack frames總是8個字(一個字32bit)如圖2.3.5所示。
在符合AAPCS的應用程序中,對于響應異常時的堆棧操作是要進行雙字對齊的在M3處理器中如果堆棧指針SP未雙字對齊的話,那么就會在堆棧中自動的增加一個填充位使其雙字對齊。雙字對齊是一一個可選項,欲使能此特性,需要把NVIC配置控制寄存器的STKALIGN置位,如下面
匯編代碼
所演示:
LDR RO,=0xE0O0ED1 4; R0=NVIC CCR的基址 LDR R1,[R0] ORR.W R1,R1, #0x200;設置STKALIGN位 STR R1,[R0];更新NVIC CCR
如果用C語言:
#define NVIC_ CCR ((volatile unsigned long *)(0xE000ED14)) *NVIC_ CCR= *NVIC_ CCR | 0x200; //設置 STKALIGN位
xPSP寄存器的bit9 被用來指示SP是否需要對齊,bit9 如果為1的話就需要雙字對齊,如果為0的話就不需要雙字對齊,未使用FPU時采用雙字對齊的Stack frame如圖2.3.6所示。
我們可以看到這里只是將xPSR、PC、LR、R12、R0-R3這8個寄存器自動入棧,其余的8個寄存器R4-R11就需要我們自己手動入棧了,入棧順序不能亂了。
我們可以看出還有R4-R11這些寄存器沒有做處理,那么我們就要手動對這些寄存器做入棧和出棧處理。
單片機
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。