CORTEX-M3中斷的現場保護問題

在《Cortex-M3 Devices Generic User Guide.pdf》中介紹了異常入棧和出棧的狀況,詳見2.3 Exception model。Cortex-M3內核的寄存器以下。 

異常發生時,入棧的寄存器是R0~R3+R12+PC+LR+SP。爲啥袒護R0‐R3以及R12呢, R4‐R11就是下等公民?(摘自《Cortex-M3權威指南 》第9章) 
原來,在ARM上,有一套的C函數調用標準約定(《 C/C++ rocedure Call Standard for the ARM Architecture》,AAPCS, Ref5)。箇中緣由就在它上面:它使得中斷服務例程能用C語言編寫,編譯器優先使用被入棧的寄存器來保存中間結果(固然,若是程序過大也可能要用到R4‐R11,此時編譯器負責生成代碼來push它們。可是, ISR應該短小精悍,不要讓系統如此操心——譯者注)。若是讀者再仔細看,會發現R0‐R3, R12是最後被壓進去的。這裏也有一番良苦用心:爲的是能夠更容易地使用SP基址來索引尋址,( 以及爲了LDM等多重加載指令,由於LDM必須加載地址連續的一串數據)。參數的傳遞也是受益者:使之能夠方便地經過壓入棧的R0‐R3取出( 主要爲系統軟件所利用,多見於SVC與PendSV中的參數傳遞)。 
這就是說,C編譯器中斷(異常)服務函數封裝的這樣的需求:當R0~R3+R12不夠用時會使用R4‐R11,在使用R4‐R11以前會進行入棧保護;在使用完以後進行出棧恢復現場。 
這也爲開發人員使用匯編語言編寫中斷服務函數提供了借鑑。好比,在uC/OS-III移植過程當中使用匯編編寫任務級/中斷級調度器。調度器須要觸發Cortex-M3的滴答定時器中斷來達到現場保護和任務切換的目的。而這個滴答定時器中斷就須要使用匯編編寫(詳見已經移植好了的os_cpu_a.s)。 
對uC/OS-III其餘中斷便可使用C編譯器提供的模板便可: 
void xxxxx_xxxHandler(void) ? 

OSIntEnter(); 
…… //中斷服務函數代碼 
OSIntExit();   

分析一下其過程 
響應xxxxx_xxxHandler以後,保存現場R0~R3+R12+PC+LR+SP,執行OSIntEnter()和中斷服務函數代碼(若這期間若是通用寄存器不夠用時會使用R4‐R11,使用前會先進行入棧保護,使用後出棧恢復現場),而後會在中斷級調度器OSIntExit()中斷定是否須要進行任務切換,若是須要則定位好待切換的任務,最後掛起由彙編編寫的滴答定時器中斷。這會引入「咬尾機制」直接轉而去執行滴答定時器中斷服務函數。 

經過對C編譯器封裝的中斷服務函數模型進行的「背地兒裏」的操做,能夠預見C編譯器對普通函數模型封裝的額外操做。至少不會比這個複雜吧....ide

 

 

 

 

 

 

 

----函數

相關文章
相關標籤/搜索