44b0
的向量中斷響應過程是中斷發生後晶元會自動跳轉到
0x00000018
處執行指令
entry
b resethandler ; 0x00
b handlerundef ; 0x04
b handlerswi ; 0x08
b handlerpabort ; 0x0c
b handlerdabort ; 0x10
b . ; 0x14
b handlerirq ; 0x18
b handlerfiq ; 0x1c
ldr pc,=handlereint0 ; 0x20
ldr pc,=handlereint1
ldr pc,=handlereint2
ldr pc,=handlereint3
ldr pc,=handlereint4567
ldr pc,=handlertick ; 0x34
b .b .
ldr pc,=handlerzdma0 ; 0x40
ldr pc,=handlerzdma1
ldr pc,=handlerbdma0
ldr pc,=handlerbdma1
ldr pc,=handlerwdt
ldr pc,=handleruerr01 ; 0x54
b .b .
ldr pc,=handlertimer0 ; 0x60
ldr pc,=handlertimer1
ldr pc,=handlertimer2
ldr pc,=handlertimer3
ldr pc,=handlertimer4
ldr pc,=handlertimer5 ; 0x74
b .b .
ldr pc,=handlerurxd0 ; 0x80
ldr pc,=handlerurxd1
ldr pc,=handleriic
ldr pc,=handlersio
ldr pc,=handlerutxd0
ldr pc,=handlerutxd1 ; 0x94
b .b .
ldr pc,=handlerrtc ; 0xa0
b .b .
b .b .
b .b .
ldr pc,=handleradc ; 0xb4 根據
44b0
的dataseet
,0x18
處放置的指令為
b handlerirq ;
當程式跳轉到這裡執行時,晶元在這個位址取到的**已經被後面程式中的
branch instructions
取代了,舉個例子,如果晶元
eint3
發生中斷,晶元會跳轉到
0x18
處執行,先在
0x18
處取指,這時取到的指令已經不是
b handlerirq
,b handlerirq
已經被晶元自動替換成了
ldr pc,=handlereint3
,然後晶元再執行此條指令。
arm7tdmi
在向量模式下,當從
0x18
位址處取指令時候,中斷控制器會在資料匯流排上載入分支指令,這些分支指令使程式計數器能夠對應到每乙個中斷源的向量位址。這些跳轉到每乙個中斷源向量位址的分支指令由中斷控制器產生。
例如:假設
eint0
是irq
中斷,eint0
0x20
(見向量表),那麼中斷控制器必須產生
0x18---0x20
的分支指令。
中斷控制器產生的機器碼為:
0xea000000
。在各個中斷源對應的中斷向量位址中,存放著跳轉到相應中斷服務程式的程式**。在相應向量位址處分支指令的機器**如下計算:
向量中斷模式的機器指令**
=0xea000000+((<
目標位址
>-<
向量位址
>-0x8)>>2)
,機器**一般由反彙編後自動產生。
而非向量中斷的**如下
entry
b resethandler ; for debug
b handlerundef ; handlerundef
b handlerswi ; swi interrupt handler
b handlerpabort ; handlerpabort
b handlerdabort ; handlerdabort
b . ; handlerreserved
b isrirq
b handlerfiq
. . . . . .
isrirq
sub sp,sp,#4 ; reserved for pc
stmfd sp!,
ldr r9,=i_ispr
ldr r9,[r9]
mov r8,#0x0
0 movs r9,r9,lsr #1
bcs %f1
add r8,r8,#4
b %b0
1 ldr r9,=handleadc
add r9,r9,r8
ldr r9,[r9]
str r9,[sp,#8]
ldmfd sp!,
. . . . . .
handleadc # 4
handlertc # 4
handleutxd1 # 4
handleutxd0 # 4
. . . . . .
handleeint3 # 4
handleeint2 # 4
handleeint1 # 4
handleeint0 # 4 ; 0xc1(c7)fff84
當發生中斷時,晶元自動跳轉到
0x18
處執行,
0x18
處指令為
b isrirq
,isrirq
程式的作用是檢查
i_ispr
的各位,判斷是何種中斷發生,然後根據中斷的種類跳轉到相應的中斷服務程式去執行,各種中斷服務程式的位址定義如下:
handleadc # 4
handlertc # 4
handleutxd1 # 4
handleutxd0 # 4
. . . . . .
handleeint3 # 4
值得一提的是在
44binit
**中,向量中斷跳轉到
handlereint0
處而非向量中斷跳轉到
handleeint0
,程式利用乙個巨集將這兩個標號等同起來,無論採取向量中斷還是非向量中斷,無論是跳到
handleeint0
還是handlereint0
,得到的效果是一樣的
,都是跳到了中斷服務程式的位址去執行。
另外順便說一下飛利浦的
lpc系列
arm晶元的中斷的方法,當
lpc晶元得到中斷訊號後,在中斷初始化時,程式將中斷服務程式的入口位址放到中斷向量位址暫存器中,每個中斷源有乙個中斷向量位址暫存器和他相對應,另外還有乙個叫做
vicvectaddr(0xffff0030)
的暫存器,當發生中斷時,硬體自動判斷該執行哪乙個中斷,然後將該中斷源對應的中斷向量位址暫存器中的位址放到暫存器
vicvectaddr
中。程式中斷向量表裡的**為跳轉到
vicvectaddr
中的位址執行。一旦發生中斷,自動跳轉到
vicvectaddr
中的位址去執行,因為此時
vicvectaddr
已經被替換成中斷源的中斷服務程式位址了。
上述handleadc # 4是在資料區中分配4個位元組的儲存空間,等同於handleadc feild 4,這四個位元組的儲存空間中存的是中斷服務程式的位址。在c語言編寫的main程式中,如何將中斷服務程式的入口位址放入到這個儲存空間中呢?細心的讀者可以發現這段資料區的起始位址是_isr_startaddress,在main函式中只要讓(*(unsigned *)(_isr_startaddress+0x74)) =(int)myisr(myisr是中斷服務程式的名稱);但是_isr_startaddress是乙個非定值,這個值只有在聯結器連線的時候才賦值,在編譯階段他是個不定值,所以編譯的時候會報錯。#define _isr_startaddress 成乙個在sdram中的位址值。在本例中是0xc7fff00。
中斷的初始化包括對intmsk ,intcon進行初始化,如果是eint0~7 還需要對pcong、extint進行初始化,對(*(unsigned *)(_isr_startaddress+0x74(或者其他偏移量)))賦值。在中斷服務程式結尾要對i_ispc寫數清除intpnd。如果是eint0~7還要在寫i_ispc之前對extintpnd暫存器寫數。
44b0實驗 中斷實驗
之前也提到的過,區區乙個簡單的中斷實驗竟然讓我大動干戈,費了n久才搞定。現在把具體實驗寫寫吧。先把 貼出來吧 include include inc 44b.h include inc option.h include inc def.h include eint.h void irq eint45...
關於44b0的中斷呼叫的問題
關於44b0的中斷呼叫的問題 下面的 因為44b0中的各個中斷型別相似的,所以只是以timer為例。在init.s中有這樣的 首先是乙個巨集的定義 macro handlerlabel handler handlelabel handlerlabel sub sp,sp,4 decrement sp...
44b0學習日記
對44b0的學習,正在如火如荼的進行中。下面說說我今天的進步吧 1 將boatloader編譯成功 2 將編成的u boot.bin下到ram中執行 3 將編成的u boot.bin燒到了flash中 位址為0x0000 方法是先從pc上通過串列埠loadb到記憶體中,再cp到flash中。4 將測...