44B0的向量中斷

2021-05-23 17:05:42 字數 4457 閱讀 8910

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 將測...