S3C2440中断跳转分析
2440init.s中斷跳轉(zhuǎn)分析
????最近準備自己寫一個S3C2440的啟動代碼。參閱了一下2440init.s這一啟動代碼。發(fā)現(xiàn)有很多人對于這個啟動代碼中的異常,特別是像外部中斷這樣的異常,到底在2440init.s中是如何實現(xiàn)跳轉(zhuǎn)的這一問題有很大的疑惑。現(xiàn)在就我的理解對這個過程做一下解說。說的不一定很好,呵呵,權(quán)當消遣吧。另外,這里面的錯誤肯定會有,大家盡管給我提吧。
??????首先要大家要明白,特別是初學者,當S3C2440發(fā)生異常時,其程序指針是會被強制轉(zhuǎn)換的,這個是硬件自己完成的,不需要我們的干涉。下面這個表格就是具體的強制指針轉(zhuǎn)化表。
| ??????地址 | ???????異常名稱 | ???????2440init.s?中的指令 |
| 0x00? | 復位異常 | b???ResetHandler |
| 0x04 | 未定義指令異常 | b???HandlerUndef |
| 0x08 | 軟件中斷異常 | b HandlerSWI |
| 0x0c | 指令預取異常 | b HandlerPabort |
| 0x10 | 數(shù)據(jù)預取異常 | b HandlerDabort |
| 0x14 | 保留 | b . |
| 0x18 | IRQ中斷異常 | b HandlerIRQ |
| 0x1c | FIQ中斷異常 | b HandlerFIQ |
?????現(xiàn)在可以很清楚的知道了。如果S3C2440剛上電或者是復位,那么pc指針被硬件強制轉(zhuǎn)換到0x00地址處,那么按照2440init.s中的指令“b???ResetHandler”,pc會跳轉(zhuǎn)到ResetHandler處繼續(xù)執(zhí)行程序。同樣,當發(fā)生外部中斷時,pc指針會被強制轉(zhuǎn)換到0x18處,執(zhí)行“b HandlerIRQ”這條指令。
????接下去,便是討論程序跳轉(zhuǎn)之后如何運行的了。首先,我們做一個設想,假設S3C 2440只有一個中斷(當然這是不可能的了,就連51也有5個中斷源。),那么可想而知,程序跳轉(zhuǎn)到HandlerIRQ處就應該執(zhí)行中斷處理函數(shù)了。也就是說,我們在C語言中寫的中斷處理函數(shù)的地址應該就是HandlerIRQ的內(nèi)容了。雖然這個假設不可能,但它可以幫助我們理解。本質(zhì)上其實就是類似于這樣的一個過程,只不過因為S3C2440有那么多的中斷源,所以不可能把中斷函數(shù)的地址直接賦給HandlerIRQ就行了。這中間應該還有一個轉(zhuǎn)換。就是根據(jù)不同的、具體的中斷源,讓HandlerIRQ對應于不同的中斷處理函數(shù)的地址。
???那么接下來看看HandlerIRQ標號后面的內(nèi)容吧。
???HandlerIRQ??????HANDLER?HandleIRQ
???很明顯,這里還有一個宏定義在里面,要知道HANDLER的內(nèi)容,我們可以在2440init.s中查到:
???MACRO??
$HandlerLabel?HANDLER?$HandleLabel
$HandlerLabel
sub sp,sp,#4
stmfd sp!,{r0}
ldr?????r0,=$HandleLabel
ldr?????r0,[r0]
str?????r0,[sp,#4]??
ldmfd???sp!,{r0,pc}??
MEND
下面對這個宏定義做一下說明。首先是MACRO表明了宏定義的開始,MEND則表示了宏定義的結(jié)束。這個宏的作用其實就是在不改變?nèi)魏渭拇嫫鞯那疤嵯?#xff0c;把pc指針指向$HandleLabel。
?????明白了這個以后,我們就可以把這個宏去掉再來理解一遍:
?????首先是當S3C2440發(fā)生外部中斷時,pc指針被強制指向了0x18處:??????????????????????
??b HandlerIRQ
??……
??HandlerIRQ
??????sub sp,sp,#4
??????stmfd sp!,{r0}
??ldr?????r0,=HandleIRQ
??ldr?????r0,[r0]
??str?????r0,[sp,#4]??
??ldmfd???sp!,{r0,pc}
經(jīng)過上面的程序后,此時的pc指針已經(jīng)指向了HandleIRQ處。呵呵,挺簡單的吧。然后
呢。我們就得關注一下HandleIRQ這個標號了。它在2440init.s中設這樣定義的:
^???_ISR_STARTADDRESS ;?_ISR_STARTADDRESS=0x33FF_FF00
HandleReset? #???4
HandleUndef? #???4
HandleSWI #???4
HandlePabort????#???4
HandleDabort????#???4
HandleReserved??#???4
HandleIRQ #???4
HandleFIQ #???4
HandleEINT0 #???4
HandleEINT1 #???4
HandleEINT2 #???4
HandleEINT3 #???4
……
很簡單,這里定義了一個文字池,首地址:_ISR_STARTADDRESS代表了地址為0x33FF_FF00的內(nèi)存區(qū)域,每隔4個字節(jié),定義一個標號。很很容易就找到了?HandleIRQ這個我們需要找的標號。那么它所代表的內(nèi)存區(qū)域自然就是0x33FF_FF00+0x04*6的內(nèi)存地址了。那么接下來的工作就是要把真正的、具體的中斷處理函數(shù)的地址賦給HandleIRQ了。這里大家先看一下下面的兩端代碼:
(1):
???ldr r0,=HandleIRQ???????;This?routine?is?needed
???ldr r1,=IsrIRQ ??;if?there?isn't?'subs?pc,lr,#4'?at?0x18,?0x1c
???str r1,[r0]
(2):
???IsrIRQ
sub sp,sp,#4???????;reserved?for?PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl?#2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
首先我們來看一下第(1)段程序,前面已經(jīng)提到,此時的的pc已經(jīng)指向了HandeIRQ所表示的內(nèi)存了,但是現(xiàn)在該內(nèi)存還是空的,pc跳轉(zhuǎn)到這里也不能接著往下運行了。所以才有了第1段代碼,它的作用就是給HandleIRQ安裝句柄了,把IsrIRQ的入口地址填充到了HandeIRQ里面了。所以程序接著就會跳轉(zhuǎn)到IsrIRQ處執(zhí)行。也就是上面的第(2)段程序了。這段程序具體講解我就不說了,跟最上面的宏定義很類似,其實就是讓PC跳轉(zhuǎn)到另外一個地方(pc=HandleEINT0+INTOFFSET*4)。而那個地方正是真正的中斷函數(shù)。那我們再來看看這個地址是怎么算出來的。首先HandleEINT0就是上面那個MAP定義里面的一個內(nèi)存區(qū)域,有沒有發(fā)現(xiàn)它是第一個中斷源,緊接著它,就是其它各種類型的中斷源了。而INTOFFSET則是S3C2440的一個特殊功能寄存器了,某個類型的中斷發(fā)生了,它的值就會發(fā)生變化。而后面為什么要乘以4呢,因為文字池中定義的標號都是4字節(jié)的,其實是因為S3C2440中指針變量就是占據(jù)4個字節(jié)的,這個可以用sizeof(*p)來驗證。所以此時pc指針就指向了另外一個地方,那就是剛才說的中斷表了。而在c語言中,我們通常會有這樣的中斷函數(shù)句柄安裝語句:pISR_EINTn?=?(unsigned?int?)key_interrupt;
這里的pISR_EINTn其實是有定義的,我們以pISR_EINT0為例,宏定義如下:
??#define?pISR_EINT0????_ISR_STARTADDRESS+0X20
看這個地址,其實就是上面那個中斷表里面的:
^???_ISR_STARTADDRESS ;?_ISR_STARTADDRESS=0x33FF_FF00
……
HandleEINT0 #???4
HandleEINT1 #???4
HandleEINT2 #???4
HandleEINT3 #???4
……
大家發(fā)現(xiàn)了吧,HandleEINT0的地址是不是就是?_ISR_STARTADDRESS+0X20,所以說c語言中我們寫的中斷函數(shù)安裝句柄,就是這個作用。
???好的,現(xiàn)在讓我們來總結(jié)一下吧。(以外部中斷0為例)
首先是在c語言的函數(shù)中,我們已經(jīng)執(zhí)行了這樣一條語句pISR_EINTn?=?(unsigned?int?)key_interrupt;它的作用是把中斷處理函數(shù)key_interrupt的地址賦給了中斷表中的HandleEINT0。
然后當某個時刻,發(fā)生了外部中斷0,那么pc指針被強制指向了0x18處,執(zhí)行指令:??
??b? HandlerIRQ
跳轉(zhuǎn)到HandlerIRQ之后,執(zhí)行如下代碼:(已經(jīng)把宏定義屏蔽)
HandlerIRQ
??????sub sp,sp,#4
??????stmfd sp!,{r0}
??ldr?????r0,=HandleIRQ
??ldr?????r0,[r0]
??str?????r0,[sp,#4]??
??ldmfd???sp!,{r0,pc}
然后pc之爭有指向了HandleIRQ這個內(nèi)存區(qū)域。而又由于HandlerIRQ已經(jīng)被安裝了IsrIRQ的句柄,所以緊接著pc又跳轉(zhuǎn)到IsrIRQ處執(zhí)行如下程序:
?????IsrIRQ
sub sp,sp,#4???????;reserved?for?PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl?#2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
它的作用是讓pc指針根據(jù)INTOFFSET的值跳轉(zhuǎn)到中斷向量表中的HandleEINT0處。而在此處已經(jīng)被安裝了c語言中的中斷處理函數(shù)的句柄,所以pc又跳到了中斷處理函數(shù)中區(qū)執(zhí)行中斷函數(shù)了。
總結(jié)
以上是生活随笔為你收集整理的S3C2440中断跳转分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 元气骑士攻略有哪些(『元气骑士』5.0.
- 下一篇: 杠杆收购比例 什么是杠杆收购