1. 程式人生 > >ARM異常處理(IRQ中斷處理)總結1

ARM異常處理(IRQ中斷處理)總結1

之間 roc 圖片 寫法 stack cat 舉例 log 地址

ARM A8的異常處理表如下
技術分享圖片
可以看到vector table的基地址是不固定的但是所有異常的偏移地址是固定的。這張表也為了體現這個偏移量,還有要從硬件角度理解的是在CPU設計的時候這些異常就已經定義好了在發生相應的異常時候CPU就自動的轉到在異常向量表裏的地址處去執行這個過程是不需要軟件幹預的因此就簡單了我們只要把出現相應的異常時候處理過程的函數名(函數名就是這個函數體的指針)放在相應的地址裏邊就可以執行了舉例說明。以三星S5PV210為例,我們根據官方的Application Node可以查到在iROM中定義的Exeception vector table的基地址是0xD003_7400(其實這個地址在移植操作系統後會更改)那麽我們就根據上圖中的偏移地址可以把定義好的異常處理函數直接放在相對應的地址上代碼可以寫成
#define Exception_base 0xd0037400
#defien Exception_rest (Exception_base + 0x00)

#define rException_rest ((volatile unsigned int)Exception_rest)

假如用C語言定義了一個void ex_rest(void)函數那麽就可以rException_rest=ex_rest;
這樣的話就可以在產生REST異常的時候直接跳轉到ex_rest這個函數執行了。
但是中斷就要不一樣一些因為中斷是需要返回的因此需要考慮的問題是如何保存CPU的上下文,這個一般都在匯編中實現(其實也是格式化了的已經)一般的寫法都是

ldr sp, =IRQ_STACK
sub lr, lr, #4
stmfd sp!, {r0-r12, lr}
bl irq_handler
ldmfd sp!, {r0-r12, pc}^
這個段代碼要理解需要了解三個知識點:
第一:ldr sp, =IRQ_STACK這是在給C語言提供棧的保障可以讓C語言運行。
第二:sub lr, lr, #4和 stmfd sp!, {r0-r12, lr}
先要了解下面這張圖
技術分享圖片
我們現在要從SVC轉換模式到IRQ因此需要保存的寄存器是R0~R12因為是共用的這兩個模式之間,還有一個就是SVC下的PC(在模式跳轉的時候硬件會把SVC下的PC直接保存到IRQ下的lr裏邊)因為不保存這個就沒辦法返回了但是要減4個字節這是因為ARM的流水線的緣故(大概了解流水線反正你記住ARM的流水線都是提前4個字節就可以了)這條語句就把所有的需要保存的數據都保存到了IRQ下的棧裏邊了,其實同時CPU也幫你把CPSR保存到了SPSR裏邊去了這個過程是自動的。
第三: ldmfd sp!, {r0-r12, pc}^
這個過程和上面的壓棧過程正好是相反的這個好理解主要是後邊的‘^’符號的作用這個符號就是把SPSR裏的內容直接回復給CPSR這樣就完全回到了SVC模式中斷完美返回了。

ARM異常處理(IRQ中斷處理)總結1