大家好,我是痞子衡,是正經搞技術的痞子,今天痞子衡給大家介紹的是ARM Cortex-M堆疊機制,
今天給大家分享的這篇依舊是2016年之前痞子衡寫的技術檔案,花了點時間重新編排了一下格式,前面痞子衡講過 《嵌入式里的堆疊原理》,本篇算是堆疊原理的工程實踐,更具體點說是在ARM Cortex-M上的應用,ARM Cortex-M家族發展至今已經很多代,我們且以最簡單的Cortex-M0為例來講述堆疊機制:
1.基本規則
1.1 R13 / sp暫存器

R0-R12為通用暫存器,R13為系統堆疊指標sp,堆疊指標是用于訪問堆疊,也即系統的RAM區,Cortex-M0中采用了兩個堆疊指標:主堆疊指標(MSP)和行程堆疊指標(PSP),R13在任何時刻只能是其中一個,默認情況為MSP,可以通過控制暫存器(CONTORL)來改變,

MSP是系統復位后(即其處于Handler Mode)的指定sp(vector table的前4Byte自動載入),用于處理例外中斷,當結束Reset_Handler后,cpu進入正常運行狀態(即其處于Thread Mode),僅在此狀態下PSP才能被使用,當然MSP也可以使用,其后如有硬中斷來臨,則進入Handler Mode,如果硬體中斷結束,則回傳Thread Mode,

關于MSP和PSP的選用,其是通過CONTORL暫存器來配置,僅在Thread Mode下才可設定CONTORL暫存器,一般情況下,沒有必要使用PSP,除非是有os存在時,MSP用于os內核的sp,而PSP用于thread級app的sp,這兩個sp需嚴格分開,
在編譯器中,可以通過r13(R13)或sp(SP)來訪問堆疊(具體是MSP和PSP由當時環境決定);也可以通過指定的MRS、MSR指令來訪問MSP和PSP,
1.2堆疊結構
無OS的堆疊結構:

有OS的堆疊結構:

1.3堆疊操作
Cortex-M0中堆疊方向是向低地址方向增長,為滿堆疊機制,堆疊操作是通過PUSH和POP來完成操作的,

堆疊一般放在ARM的 RAM高位區,如某MCU中RAM地址為0x20000000-0x20007fff,共32KByte,堆疊大小設為4KByte的話,其地址一般就放在0x20007000-0x20007fff,其中0x20007000為絕對堆疊頂,0x20007ffc為絕對堆疊底,sp總是指向相對堆疊頂,第一個PUSH資料被存在絕對堆疊底(此時絕對堆疊底也是相對堆疊頂),實際上,除了POP指令可以從堆疊頂中取資料外;MOV指令也可從任意位置取資料,但不會影響堆疊結構(即不影響其sp),
由于ARM暫存器均是32bit,故PUSH和POP指令均是32bit訪問,故sp指標總是至少4Byte對齊(低2bit永遠為0),有時編譯器也會分配8Byte對齊的堆疊,這是由于double浮點型別需要占用8Byte,為了處理方便,故將堆疊設為8Byte對齊,
2.入堆疊順序
入堆疊順序因編譯器、處理器系統、OS而異,C語言中并沒有強制規定入堆疊順序,此處主要是講ARM Cortex-M系列處理器在指定編譯器情況下的入堆疊順序,
2.1一般函式呼叫(通用)

上圖展示了在一般函式(無參無區域變數無回傳值)嵌套呼叫時,關于sp的操作,在執行BL FunctionA指令時,LR記錄的是BL FunctionA的下一條順序指令,在進入FunctionA后執行的第一條操作便是PUSH 即將下一條順序指令壓入堆疊中,然后才開始執行FunctionA函式體,函式體執行結束之后,使用POP 指令將堆疊頂資料彈到PC中,即可回傳繼續執行BL FunctionA的下一條順序指令,
2.2極端函式呼叫(平臺而異)
考慮一種極端情況來詳細講述入堆疊順序,即函式含有4個引數以上,函式體內定義了多個區域變數,并且還有回傳值,這個情況比較特殊,痞子衡專門在IAR上做過一次實驗,詳見下圖:

至此,ARM Cortex-M堆疊機制痞子衡便介紹完畢了,掌聲在哪里~~~
歡迎訂閱
文章會同時發布到我的 博客園主頁、CSDN主頁、微信公眾號 平臺上,
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦,

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/17253.html
標籤:嵌入式
