S3C2440中斷代碼的深層次分析
異常處理的基本過(guò)程如下:異常產(chǎn)生(在指令的臨界中檢測CPU的狀態(tài),一般實(shí)質(zhì)在這條指令被執行完成,但是還沒(méi)有執行下一條指令之前檢測)——>保存狀態(tài)寄存器,切換狀態(tài)寄存器,保存LR=PC-4,強制PC跳轉到對應異常向量(以上的過(guò)程都是CPU自動(dòng)完成)——》調整返回地址,在棧中保存寄存器,便于恢復寄存器的值——》異常處理函數——》退出異常。
中斷處理機制的兩種形式:
1、采用在中斷向量中存儲簡(jiǎn)單的跳轉指令,跳轉到異常處理函數中,但是這種方式存在的缺點(diǎn)就是跳轉指令的范圍是有局限性的。
2、采用更新PC值的方法進(jìn)行,具體的實(shí)現形式是在另一個(gè)固定地址處(handle_addr)保存對應異常處理函數的地址,然后采用LDR PC [PC, offset],其中offset = handle_addr – vect – 0x08;這種機制只要保證選擇的地址恰當就能實(shí)現不同距離的跳轉。
以上的分析和處理在上一次中已經(jīng)分析,這次分析中斷的處理過(guò)程,中斷只是異常的一種特殊情況,對異常的處理得到了好的理解,那么對中斷的處理也就比較方便了。
在A(yíng)RM內核中只支持IRQ和IFQ兩種類(lèi)型的中斷,但是不同的廠(chǎng)商提供不同類(lèi)型的中斷控制器實(shí)現對中斷的擴展,使得實(shí)際的芯片更加適合我們的使用。但是中斷控制器的差別也使得不同廠(chǎng)商的中斷處理也有差別,但是基本的思想是一致的。

S3C2440的中斷控制器一個(gè)支持60種中斷源,基本的實(shí)現如上圖所示?;镜募拇嫫靼⊿RCPND、INTPND(有且僅有1bit會(huì )被置位,可以通過(guò)這個(gè)寄存器判斷中斷源,找出那個(gè)IRQ源發(fā)生中斷)、INTMOD、INTMSK、PRIORITY(用來(lái)改變中斷的優(yōu)先級順序,但是其中還是存在一些固有的順序,具體的參看手冊)、INTOFFSET(用來(lái)表示IRQ中INTPND的那個(gè)bit被置位,這樣每一類(lèi)的中斷源都存在一個(gè)固定的偏移量,這個(gè)寄存器可以用來(lái)用來(lái)計算偏移量以及通過(guò)這個(gè)偏移量找到對應的中斷處理函數地址存儲位置等),當然也存在一些關(guān)于多個(gè)中斷源構成的子中斷寄存器,SUBSRCPND、INTSUBMSK。
在S3C2440的啟動(dòng)代碼中描述了關(guān)于中斷處理過(guò)程的基本過(guò)程和原理。
首先需要搞清楚下面的一個(gè)宏定義:
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
subsp,sp,#4;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)
ldr r0,=$HandleLabel;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
1、搞清楚ARM中的MACRO偽指令,這個(gè)偽指令就是我們在匯編中的宏定義,我們都知道宏的實(shí)現能夠避免代碼的重復型以及代碼的可修復性。關(guān)于A(yíng)RM匯編中的宏定義基本的形式如下:
MACRO
{$label} macroname {$parameter} {$parameter}…
Code
MEND
其中$label 宏指令被展開(kāi)時(shí),label可被替換為相應的符號,一般為一個(gè)標號
macroname所定義的宏的名稱(chēng)
$parameter宏指令的參數,當宏指令被展開(kāi)時(shí)被替換成對應的值。
2、依據上面的定義我們可以知道當前這段代碼定義了一個(gè)宏指令,HANDLER,其中標號為$HandlerLabel,參數為$HandleLabel
基本的實(shí)現代碼分析如下:
subsp,sp,#4;在棧中預留一個(gè)區域,用來(lái)保存PC的值
stmfd sp!,{r0};由于r0還需要被使用,因此需要被壓棧
ldr r0,=$HandleLabel ;這里的ldr是一個(gè)偽指令,主要是將標號$HandleLabel的地址加載到r0中,這也是壓棧r0的原因。
ldr r0,[r0] ;這是ARM的ldr指令,主要是將$HandleLabel對應地址中的內容加載到r0中。如果在$HandleLabel中保存的是一個(gè)中斷處理函數的地址,那么只需要將這個(gè)值加載到PC即可實(shí)現了中斷任務(wù)跳轉,實(shí)際上這個(gè)過(guò)程就是采用了異常處理的第二種方式:
即加載PC的方式,而不是簡(jiǎn)單的跳轉方式。
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
這兩句代碼正是這段代碼的精髓?;拘问饺缦拢?/div>
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
str r0,[sp,#4],是指將r0的內容,也就是異常處理函數的地址保存到棧中的SP-4位置處,這個(gè)位置也恰好是之前sub sp,sp,#4;用來(lái)預留給保存PC值的位置,這時(shí)將異常處理函數的地址保存在這個(gè)地址處,接下來(lái)的ldmfd sp!,{r0,pc}剛好就是將棧中的內容加載到R0和PC中,這樣也就實(shí)現了將異常處理函數地址加載到PC.實(shí)現了跳轉過(guò)程。
高地址 | |
SP_0/SP_3 | … |
SP_1 | Handle_addr |
SP_2 | R0 |
低地址 |
從上面的分析可以知道這種中斷處理的方式,并不是中斷處理中的簡(jiǎn)單跳轉方式(因為跳轉范圍的局限性)而是采用更新PC值的形式實(shí)現的。
接下來(lái)分析IRQ,這種在我們實(shí)際開(kāi)發(fā)中使用比較多的中斷形式進(jìn)行分析。
首先可以發(fā)現存在:
1、b HandlerIRQ;handler for IRQ interrupt
這種情況下發(fā)生在中斷產(chǎn)生過(guò)程中,是在IRQ向量中執行的,也就是在0x18處執行,其中HandlerIRQ實(shí)質(zhì)上是一個(gè)標號,對應一個(gè)具體的地址。其中保存的內容就是對應IRQ處理函數的地址。但是在代碼中只有一個(gè)HandlerIRQ,形式如下:
HandlerIRQHANDLER HandleIRQ
2、HandlerIRQ HANDLER HandleIRQ
根據上面的宏定義,可以將這句代碼進(jìn)行擴展,得到如下的形式:
HandlerIRQ
subsp,sp,#4
stmfd sp!,{r0}
ldr r0,= HandleIRQ
ldr r0,[r0]
str r0,[sp,#4]
ldmfd sp!,{r0,pc}
3、關(guān)于HandleIRQ其中存放的內容可以從下面的代碼中得到。
; Setup IRQ handler
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ ;if there is not subs pc,lr,#4 at 0x18, 0x1c
str r1,[r0]
其中可以看到,在HandleIRQ中保存的內容是IsrIRQ的地址,而IsrIRQ我們可以知道是一個(gè)中斷服務(wù)函數,因為在寫(xiě)代碼的過(guò)程中進(jìn)程會(huì )遇到這個(gè)特殊字符__ISR,這段代碼是在啟動(dòng)代碼中執行的。
4、IsrIRQ實(shí)現問(wèn)題
IsrIRQ
subsp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
addr8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
還是一句一句的分析:
subsp,sp,#4 ;為保存PC值預留一個(gè)棧區域,這個(gè)區域與上面的處理過(guò)程是異曲同工的。
stmfd sp!,{r8-r9} ;保存r8,r9中的值,因為接下來(lái)將使用這兩個(gè)寄存器
ldr r9,=INTOFFSET;這是一個(gè)偽指令操作,實(shí)質(zhì)上是將寄存器INTOFFSET的地址加載到r9中。
ldr r9,[r9];得到寄存器中的值,這個(gè)寄存器中的值恰好保存了當前最高優(yōu)先級中斷的中斷號(優(yōu)先級是可以調節的,而中斷號是一個(gè)固定值,因此選擇中斷號比較恰當),這樣也就知道了具體是那個(gè)中斷源產(chǎn)生了中斷。
ldr r8,=HandleEINT0;這句的ldr是偽指令,意思是將標號的地址加載到r8中
addr8,r8,r9,lsl #2;從指令的意義分析:r8 = r8 + r9>>2 = r8+r9*4;
其實(shí)這兩句結合一下S3C2440的中斷資料就不難分析得出,因為HandleEINT0實(shí)質(zhì)上是指存儲外部中斷0處理函數地址的地方,那么我們可以將這一塊內存地址看做是一個(gè)IRQISR中斷向量表,而EINT0恰好是中斷優(yōu)先級最高的中斷,那么可以將這個(gè)地址HandleEINT0作為IRQ中斷向量表的入口地址,其他中斷號的地址,只需要通過(guò)偏移地址就能得到,由于指針的大小恰好為4個(gè)字節,因此得到的相應中斷號的入口地址是
HandleEINT0 = HandleEINT0 + INTOFFSET*4,
這些地址中都保存了對應中斷處理函數的函數地址。
ldr r8,[r8]是指將r8的內容加載到r8中,也就是將對應中斷處理函數的地址加載到r8中。
str r8,[sp,#8];這句代碼的作用實(shí)質(zhì)上就是和上面的分析一樣,也就是將r8的值保存到之前為PC預留的區域中。
關(guān)鍵詞:
S3C2440中斷代碼深層次分
相關(guān)推薦
技術(shù)專(zhuān)區
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線(xiàn)
- 開(kāi)關(guān)電源
- 單片機
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開(kāi)發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機控制
- 藍牙
- PLC
- PWM
- 汽車(chē)電子
- 轉換器
- 電源管理
- 信號放大器
評論