ARM微處理器的編程模型之:異常中斷處理
有些情況下,系統(tǒng)0x0地址不一定是ROM。如果0x0地址為RAM,那么就系統(tǒng)將中斷向量表從ROM復(fù)制RAM,下面的例子顯示了這樣一個(gè)過(guò)程。
MOV R8, #0
ADR R9, Vector_Init_Block
LDMIA R9!,{r0-r7} ;復(fù)制中斷向量表 (8 words)
STMIA R8!,{r0-r7}
LDMIA R9!,{r0-r7} ;復(fù)制由偽操作 DCD定義的地址
STMIA R8!,{r0-r7}
注意 | 可以使用Scatter文件定義加載向量表的地址,這樣上述代碼的拷貝工作由C庫(kù)函數(shù)完成。 |
2.使用C語(yǔ)言安裝異常處理程序
程序中有時(shí)需要在main()函數(shù)中使用C語(yǔ)言安裝中斷向量表。這就要求指令經(jīng)編譯后的解碼能安裝在內(nèi)存的正確位置。
(1)向量表中使用跳轉(zhuǎn)指令的情況
如果在向量表中使用跳轉(zhuǎn)指令,使用下面的步驟完成向量表的安裝。
① 讀取異常處理程序的地址。
② 從異常處理程序地址中減去向量表中的偏移。
③ 為適應(yīng)指令流水線,將上一步得到的地址減8。
④ 將得到的結(jié)果右移2位,得到以字為單位的地址偏移量。
⑤ 將結(jié)果的高8位清零,得到跳轉(zhuǎn)指令的24位偏移量。
⑥ 將上一步得到的結(jié)果和0xea000000(無(wú)條件跳轉(zhuǎn)指令編碼)做邏輯與操作,從而得到要寫(xiě)到向量表中的跳轉(zhuǎn)指令的正確編碼。
下面的例子顯示了這樣一個(gè)標(biāo)準(zhǔn)過(guò)程。
unsigned Install_Handler (unsigned routine, unsigned *vector)
{ unsigned vec, oldvec;
vec = ((routine - (unsigned)vector - 0x8)>>2);
if ((vec 0xFF000000))
{
/* diagnose the fault */
prinf (Installation of Handler failed);
exit (1);
}
vec = 0xEA000000 | vec;
oldvec = *vector;
*vector = vec;
return (oldvec);
}
(2)在向量表中使用加載PC指令
在向量表中使用加載PC指令,按照下面的步驟完成。
① 讀取異常處理程序地址。
② 從異常處理程序地址中減去向量表中的偏移。
③ 為適應(yīng)指令流水線,將上一步得到的地址減8。
④ 保留結(jié)果的后12位。
⑤ 將結(jié)果與0xe59ff000(LDR PC, [PC,#offset])做邏輯或操作,從而得到要寫(xiě)到向量表中的跳轉(zhuǎn)指令的正確編碼。
⑥ 將異常處理程序的地址放到相應(yīng)的存儲(chǔ)單元。
下面的例子顯示了一個(gè)標(biāo)準(zhǔn)的C語(yǔ)言過(guò)程。
unsigned Install_Handler (unsigned location, unsigned *vector)
{ unsigned vec, oldvec;
vec = ((unsigned)location - (unsigned)vector - 0x8) | 0xe59ff000;
oldvec = *vector;
*vector = vec;
return (oldvec);
}
3.4.7 FIQ和IRQ中斷處理函數(shù)的設(shè)計(jì)
1.中斷分支
ARM內(nèi)核只有兩個(gè)外部中斷輸入信號(hào)nFIQ和nIRQ。但對(duì)于一個(gè)系統(tǒng)來(lái)說(shuō),中斷源可能多達(dá)幾十個(gè)。為此,在系統(tǒng)集成的時(shí)候,一般都會(huì)有一個(gè)異??刂破鱽?lái)處理異常信號(hào),如圖3.8所示。
圖3.8 中斷系統(tǒng)
這時(shí)候用戶程序可能存在多個(gè)IRQ/FIQ的中斷處理函數(shù)。為了使從向量表開(kāi)始的跳轉(zhuǎn)始終能找到正確的處理函數(shù)入口,需要設(shè)置一套處理機(jī)制和方法。
多數(shù)情況下是由軟件來(lái)處理異常分支的,因?yàn)檐浖梢酝ㄟ^(guò)讀取中斷控制器來(lái)獲得中斷源的信息,如圖3.9所示。
有些芯片可能支持特殊的硬件分支功能,這需要查看具體的芯片說(shuō)明。
因?yàn)檐浖撵`活性,可以設(shè)計(jì)出比圖3.9更好的流程控制方法,如圖3.10所示。
Int_vector_table是用戶自己開(kāi)辟的一塊存儲(chǔ)器空間,里面按次序存放異常處理函數(shù)的地址。IRQ_Handler()從中斷控制器獲取中斷源信息,然后再?gòu)腎nt_vector_table中的對(duì)應(yīng)地址單元得到異常處理函數(shù)的入口地址,完成一次異常響應(yīng)的跳轉(zhuǎn)。這種方法的好處是用戶程序在運(yùn)行過(guò)程中,能夠很方便地動(dòng)態(tài)改變異常服務(wù)內(nèi)容。
圖3.9 軟件控制中斷分支
圖3.10 靈活的軟件分支設(shè)計(jì)
進(jìn)入異常處理程序后,用戶可以完全按照自己的意愿來(lái)進(jìn)行程序設(shè)計(jì),包括調(diào)用Thumb狀態(tài)的函數(shù)等。但對(duì)于絕大多數(shù)的系統(tǒng)來(lái)說(shuō),有兩個(gè)步驟必須處理,一是現(xiàn)場(chǎng)保護(hù),二是要把中斷控制器中對(duì)應(yīng)的中斷狀態(tài)標(biāo)識(shí)清除,表明該中斷請(qǐng)求已經(jīng)得到響應(yīng),否則,中斷函數(shù)退出以后,又會(huì)被再一次觸發(fā),從而進(jìn)入周而復(fù)始的死循環(huán)。
評(píng)論