天天看點

堆記憶體操作

在cortex-m3中,除了可以使用PUSH和POP指令來處理堆在外,核心還會在異常處理的始末自動地執行PUSH與POP操作。

1.堆棧的基本操作

堆棧操作就是對記憶體的讀寫操作,通路位址由SP給出。寄存器的資料通過PUSH操作存入堆棧,以後用POP操作從堆棧中取回。在PUSH與POP的操作中寄存器的值會按堆棧的使用法自動調整,以保證後續的PUSH不會破壞先前進去的内容。

堆棧的功能就是把寄存器的資料臨時備份在記憶體中,以便将來能恢複——在一個任務段或一段子程式執行完畢後恢複。正常情況下,PUSH與POP必須成對的使用,而且參與的寄存器,不困是身份還是先後順序都必須完全一直。當PUSH/POP指令執行時,SP指針的值也跟着自減/自增。

堆記憶體操作

 2.cortex-m3的堆棧實作

cortex-m3使用的是“向下生長的滿載”模型。堆棧指針SP指向最後一個被壓入堆棧的32位數值。在下一次壓棧時,SP先自減4,再存入新的數值。

堆記憶體操作

 注:雖然POP後被壓入的數值還儲存在棧中,但它已經無效了,因為下次的PUSH将覆寫它的值!

在進入ESR(異常服務例程)時,CM3會自動把一些寄存器壓棧,這裡使用的是發生本異常的瞬間正在使用的SP指針(MSP或者是PSP)。離開ESR後,隻要ESR沒有更改過CONTROL[1],就依然使用本次異常的瞬間正在使用的SP指針來執行出棧操作。

3.再論Cortex-M3的雙堆棧機制

CM3的堆棧分為兩個:主堆棧與程序堆棧,CONTROL[1]決定如何選擇。

當CONTROL[1]=0時,隻使用MSP,此時使用者程式和異常handler共享一個堆棧。這也是的複位後的預設使用方式。

堆記憶體操作

 當CONTROL[1]=1時,縣城模式将不在使用MSP,而改用PSP(handler模式永遠使用MSP)。在使用OS的環境下,隻要OS核心僅在handler模式下執行,使用者應用程式僅在使用者模式下執行,這種雙堆棧機制派上拉用場——防止使用者程式的堆棧錯誤破壞OS使用的堆棧。

注:此時,進入異常時的自動壓棧使用的是程序堆棧,進入異常handler後才自動改為MSP,退出異常時切換回來PSP,并且從程序堆棧上彈出資料。

堆記憶體操作

 4.複位序列

再離開複位狀态後,CM3做的第一件事就是讀取下列兩個32位整數的值:

(1)從位址0x0000,0000處取出MSP的初始值

(2)從位址0x0000,0000處取出PC的初始值——這個值是複位向量,LSB必須是1.然後從這個值所對應的位址處取指

堆記憶體操作

 這與傳統的ARM架構不同——其實也和絕大多數的其他單片機不同。傳統的ARM架構總是從0位址開始執行第一條指令。他們的0位址處總是一條跳轉指令。在CM3中,在0位址處提供MSP的初始值,然後緊跟着就是向量表(向量表在以後還可以被移至其他位置)。向量表中的數值是32位的位址,而不是跳轉指令。向量表的第一個條目指向複位後應執行的第一條指令。

堆記憶體操作

 因為CM3使用的是向下生長的滿棧,是以MSP的初始值必須是堆棧記憶體的末位址加1。(如果你的堆棧區域在0x20007c00-0x20007FFF之間,那麼MSP的初始值就必須是0x2000800

繼續閱讀