国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

超詳細(xì)的2440中斷機(jī)制分析!

發(fā)布時(shí)間:2011-3-24 13:47    發(fā)布者:techshare
關(guān)鍵詞: 2440 , 中斷
一直在看2440的中斷處理部分,不懂的實(shí)在太多了,百度到這篇文章,實(shí)在有聽(tīng)君一席話,勝養(yǎng)十年豬的感覺(jué)啊,下面上文章:

中斷向量

b HandlerIRQ ;handler for IRQ interrupt

很自然,因?yàn)樗械?a href="http://m.qingdxww.cn/keyword/單片機(jī)" target="_blank" class="relatedlink">單片機(jī)都是那樣,中斷向量一般放在開(kāi)頭,用過(guò)單片機(jī)的人都會(huì)很熟悉,那就不多說(shuō)了。

異常服務(wù)程序

這里不用中斷(interrupt)而用異常(exception),畢竟中斷只是異常的一種情況,

下面主要分析的是“中斷異常”說(shuō)白了,就是我們平時(shí)單片機(jī)里面用的中斷!!!所有由器件引起的中斷,例如TIMER中斷,UART中斷,外部中斷等等,都有一個(gè)統(tǒng)一的入口,那就是中斷異常 IRQ ! 然后從IRQ的服務(wù)函數(shù)里面分辨出,當(dāng)前究竟是什么中斷,再跳轉(zhuǎn)到相應(yīng)的中斷服務(wù)程序。這樣看來(lái),ARM比單片機(jī)要復(fù)雜一些了,不過(guò)原理是不變的。

上面說(shuō)的就是思路,跟著這個(gè)思路來(lái)接著分析。

HandlerIRQ 很明顯是一個(gè)標(biāo)號(hào),我們找到了

HandlerIRQ HANDLER HandleIRQ

這里是一個(gè)宏定義,我們?cè)僬业竭@個(gè)宏,看他是怎么定義的:

MACRO

$HandlerLabel HANDLER $HandleLabel

$HandlerLabel

sub sp,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

用 HandlerIRQ 將這個(gè)宏展開(kāi)之后得到的結(jié)果實(shí)際是這樣的

HandlerIRQ

sub sp,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,=HandleIRQ ;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)

至于具體的跳轉(zhuǎn)原理下面再說(shuō),

好了,這樣的話就容易看的多了,很明顯, HandlerIRQ 還是一個(gè)標(biāo)號(hào),IRQ異常向量就是跳轉(zhuǎn)到這里執(zhí)行的,這里粗略看一下,應(yīng)該是保存現(xiàn)場(chǎng),然后跳轉(zhuǎn)到真正的處理函數(shù),那么很容易發(fā)現(xiàn)了這么一句 ldr r0,=HandleIRQ ,沒(méi)錯(cuò),我們又找到了一個(gè)標(biāo)號(hào) HandleIRQ ,看來(lái)真正的處理函數(shù)應(yīng)該是這個(gè) HandleIRQ ,繼續(xù)尋找

AREA RamData, DATA, READWRITE

^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00

HandleReset # 4

HandleUndef # 4

HandleSWI # 4

HandlePabort # 4

HandleDabort # 4

HandleReserved # 4

HandleIRQ # 4

最后我們發(fā)現(xiàn)在這里找到了 HandleIRQ ,^ 其實(shí)就是 MAP ,這段程序的意思是,從 _ISR_STARTADDRESS 開(kāi)始,預(yù)留一個(gè)變量,每個(gè)變量一個(gè)標(biāo)號(hào),預(yù)留的空間為 4個(gè)字節(jié),也就是 32BIT,其實(shí)這里放的是真正的C寫的處理函數(shù)的地址,說(shuō)白了,就是函數(shù)指針 - - 這樣做的話就很靈活了


接著,我們需要安裝IRQ處理句柄,說(shuō)白了,就是設(shè)置處理函數(shù)的地址,讓PC指針可以正確的跳轉(zhuǎn)。

于是我們?cè)诮又恼业桨惭b句柄的語(yǔ)句


; 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]

說(shuō)白了就是將 IsrIRQ 的地址填到 HandleIRQ對(duì)應(yīng)的地址里面,前面說(shuō)了 HandleIRQ 放的是中斷處理的函數(shù)的入口地址,我們繼續(xù)找 IsrIRQ

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}


要理解這個(gè)代碼,得先學(xué)學(xué)2440的中斷系統(tǒng)了,INTOFFSET存放的是當(dāng)前中斷的偏移號(hào),根據(jù)偏移就知道當(dāng)前是哪個(gè)中斷源發(fā)生的中斷。

注意了,我們說(shuō)的是中斷,而不是異常,看看原來(lái)的表是啥樣子的

^ _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

.......

可以看到,前面幾個(gè)是異常,從 HandleEINT0 就是 IRQ異常的向量存放的地方了,這樣就可以理解為什么上面 IsrIRQ 里面里面要執(zhí)行那條指令

ldr r8,=HandleEINT0

add r8,r8,r9,lsl #2

道理很簡(jiǎn)單, HandleEINT0 就是所有IRQ中斷向量表的入口,在這個(gè)地址上面,加上一個(gè)適當(dāng)?shù)钠屏浚琁NTOFFSET ,那么我們知道現(xiàn)在,到底是哪個(gè)IRQ在申請(qǐng)中斷了。

至于具體怎么跳轉(zhuǎn)的?

首先,我們說(shuō)了,HandleEINT0 開(kāi)始的一段內(nèi)存里面,存放的就是中斷服務(wù)函數(shù)的函數(shù)指針,ARM的體系的話,每個(gè)指針變量就是占4個(gè)字節(jié),這里就解釋了,為什么這里為每個(gè)標(biāo)號(hào)分配了4個(gè)字節(jié)的空間,里面放的就是函數(shù)指針!!!下面再看看怎么跳轉(zhuǎn),繼續(xù)看 IsrIRQ 里面就實(shí)現(xiàn)了跳轉(zhuǎn)了

str r8,[sp,#8]

ldmfd sp!,{r8-r9,pc}

其實(shí)最核心就是這兩句了,先查找到當(dāng)前中斷服務(wù)程序的地址,將他放到 R8 里面,然后出棧,彈出給PC那么PC很自然就跳到中斷服務(wù)程序了。至于這里的堆棧問(wèn)題又是一個(gè)非常棘手的,需要好好的參透ARM的中斷架構(gòu),需要了解的可以自己仔細(xì)的閱讀 《ARM體系結(jié)構(gòu)與編程》里面說(shuō)的很詳細(xì)。我們這里的重點(diǎn)是研究怎么跳轉(zhuǎn)。

最后,我們看看在C代碼中是怎么安裝終端向量的,例如看 按鍵的外部中斷,是怎么具體設(shè)置的,參看/src/keyscan.c 里面的代碼很簡(jiǎn)單,里面只有3個(gè)函數(shù)

KeyScan_Test 是按鍵測(cè)試的主函數(shù)

Key_ISR 是按鍵中斷服務(wù)函數(shù)

在 KeyScan_Test里面,我們發(fā)現(xiàn)了有這么一句

pISR_EINT0 = pISR_EINT2 = pISR_EINT8_23 = (U32)Key_ISR;

可以理解否? Key_ISR就是上面提到的按鍵中斷服務(wù)函數(shù),函數(shù)的名字,代表的就是函數(shù)的地址!!!!

將中斷服務(wù)函數(shù)的地址,注意了,是地址,這是一個(gè) U32型的變量。送到幾個(gè)變量,我們以pISR_EINT0 作為例子,查看頭文件定義,在 2440addr.h 里面找到

// Interrupt vector

#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))

_ISR_STARTADDRESS有沒(méi)有似曾相識(shí)的感覺(jué)?沒(méi)錯(cuò),剛才分析的匯編代碼里面就提到了

^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00

HandleReset # 4

HandleUndef # 4

......

對(duì),地址就是這里,然后 _ISR_STARTADDRESS+0x20 就是跳過(guò)前面的異常向量,進(jìn)入IRQ中斷向量的入口,所以說(shuō)到尾

pISR_EINT0 = (U32)Key_ISR;

完成的操作就是,將 Key_ISR 的地址存放到

HandleEINT0 # 4

這個(gè)IRQ向量表里面!!!!

當(dāng)按鍵中斷發(fā)生的時(shí)候,發(fā)生IRQ異常中斷當(dāng)前PC值-4 保存到LR_IRQ里面,然后執(zhí)行

b HandlerIRQ

然后是執(zhí)行

HandlerIRQ

sub sp,sp,#4 ; 預(yù)留一個(gè)用來(lái)存放PC地址

stmfd sp!,{r0} ; 保存R0,因?yàn)橄旅媸褂昧?br />
ldr r0,=HandleIRQ ; 將HandleIRQ(服務(wù)程序)的地址裝載到R0

ldr r0,[r0]

str r0,[sp,#4] ; 保存到剛才預(yù)留的地方

ldmfd sp!,{r0,pc} ; 彈出堆棧,恢復(fù)R0,并且將剛才計(jì)算好的 HandleIRQ 地址彈出到 PC堆棧是向下生長(zhǎng)的,所以 SUB SP,SP,#4 就相當(dāng)于 PUSH XX,但是這個(gè)XX這個(gè)時(shí)候并沒(méi)有用,因?yàn)檫@里用的是強(qiáng)制移動(dòng) SP 指針實(shí)現(xiàn)的。然后得到服務(wù)程序的地址,再將這個(gè)值放回剛才預(yù)留的棧的空位上面,最后就是POP出R0恢復(fù),并且將剛才得到的服務(wù)程序的地址送到 PC,那么實(shí)現(xiàn)的效果就是跳轉(zhuǎn)到 HandleIRQ 里面了。

接著看剛才是怎么安裝的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]

可以看出,這里將 IsrIRQ 的地址的值保存到 HandleIRQ 中,也就是說(shuō),上面的 IRQ 服務(wù)程序,這個(gè)時(shí)候?qū)嶋H上就是指 IsrIRQ !

所以接著的事情就是轉(zhuǎn)移到 IsrIRQ 中執(zhí)行:

IsrIRQ

sub sp,sp,#4 ; 預(yù)留一個(gè)值來(lái)保存PC

stmfd sp!,{r8-r9}

ldr r9,=INTOFFSET ; 計(jì)算偏移量,下面解釋

ldr r9,[r9]

ldr r8,=HandleEINT0

add r8,r8,r9,lsl #2

ldr r8,[r8]

str r8,[sp,#8] ; 因?yàn)楸4媪?個(gè)寄存器R8 R9 ,所以SP下移了8位

ldmfd sp!,{r8-r9,pc} ; 恢復(fù)寄存器,彈出到PC,同上面的一樣怎么保存,操作SP,跟最后彈出到PC的部分和上面的例子一樣,下面說(shuō)說(shuō)中間的計(jì)算部分計(jì)算偏移量,其實(shí)原理很簡(jiǎn)單,首先 INTOFFSET 保存著當(dāng)前是哪個(gè)IRQ中斷,例如 0代表著 HandleEINT0,1代表HandleEINT1 ..... 等等,這不是亂來(lái),有一個(gè)表的,這個(gè)是由 S3C2440 的datasheet說(shuō)的,自己可以去查看。

然后得到 中斷處理函數(shù)的向量表,這個(gè)表的首地址就是 HandleEINT0,那么很自然的想到,怎么查表?那還不簡(jiǎn)單?HandleEINT0 + INTOFFSET 不就完了?基地址加偏移量就得到表中某項(xiàng)了,當(dāng)然,因?yàn)檫@里是中斷處理向量

每一項(xiàng)占用4個(gè)字節(jié),所以用lsl #2處理一下,左移2位相當(dāng)于乘以4,偏移量乘以4,這應(yīng)該很好理解的。

我們這個(gè)例子找到的就是 HandleEINT0 ,將里面的值讀出來(lái),里面放的是 HandleEINT0 服務(wù)函數(shù)的地址,這個(gè)地址怎么來(lái)的?是在C程序里面設(shè)置的。我們看 keyscan.c 程序,找到一個(gè) void KeyScan_Test(void) 函數(shù),

里面有這么一句:

pISR_EINT0 = pISR_EINT2 = pISR_EINT8_23 = (U32)Key_ISR;

這里是安裝了3個(gè)按鍵中斷服務(wù)程序,我們只關(guān)注 0號(hào)中斷,也就是

pISR_EINT0 = (U32)Key_ISR;

這句話什么意思?先看看pISR_EINT0的定義,在 2440addr.h 中定義

#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))

看到?jīng)]有?_ISR_STARTADDRESS 不就是剛才說(shuō)的那個(gè)異常向量的入口地址?加上一個(gè) 0x20 之后實(shí)際上指向的,就是 HandleEINT0 !!!這么說(shuō)來(lái),上面的意思就是,將 Key_ISR 處理函數(shù)的入口地址,送到 HandleEINT0 中。

再來(lái)看 Key_ISR ,這是一個(gè)典型的服務(wù)程序,加了_irq 作為編譯關(guān)鍵字,告訴編譯器,這個(gè)函數(shù)是中斷服務(wù)程序

得保存需要的寄存器,免得被破壞。具體可以參考 《ARM體系結(jié)構(gòu)與編程》P283 頁(yè)的描述。

static void __irq Key_ISR(void)

{

.......

}

加上 _irq 關(guān)鍵字之后,編譯器就會(huì)處理好所有的保存動(dòng)作了,并不需要多關(guān)心。但是這個(gè)是 ARM-CC 編譯器的關(guān)鍵字,GCC中并沒(méi)有這個(gè)東西,所以GCC處理中斷的時(shí)候最好還是自己保存一下。

到這里為止,整個(gè)中斷的過(guò)程就解釋完畢。分析的過(guò)程中確實(shí)學(xué)習(xí)了很多。
本文地址:http://m.qingdxww.cn/thread-59734-1-1.html     【打印本頁(yè)】

本站部分文章為轉(zhuǎn)載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé);文章版權(quán)歸原作者及原出處所有,如涉及作品內(nèi)容、版權(quán)和其它問(wèn)題,我們將根據(jù)著作權(quán)人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評(píng)論 登錄 | 立即注冊(cè)

廠商推薦

  • Microchip視頻專區(qū)
  • 使用SAM-IoT Wx v2開(kāi)發(fā)板演示AWS IoT Core應(yīng)用程序
  • 使用Harmony3加速TCP/IP應(yīng)用的開(kāi)發(fā)培訓(xùn)教程
  • 集成高級(jí)模擬外設(shè)的PIC18F-Q71家族介紹培訓(xùn)教程
  • 探索PIC16F13145 MCU系列——快速概覽
  • 貿(mào)澤電子(Mouser)專區(qū)

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號(hào) | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产在线视频自拍 | 免费羞羞网站 | 成人一区二区免费中文字幕 | 日日摸日日添夜夜爽97 | 直接进入免费看黄的网站 | 韩国免费网站成人 | 亚洲欧美成人中文在线网站 | 久久精品免费观看 | 手机看片午夜 | 亚洲大胆美女人体一二三区 | wwwwww色| 日韩a无吗一区二区三区 | 日日摸夜夜摸狠狠摸日日碰夜夜做 | 免费自拍偷拍 | 国产乱对白刺激视频在线观看 | 国产综合久久久久影院 | 无限看片动漫的视频在线观看免费 | 天天操天 | 亚洲区欧美中文字幕久久 | 可以免费看污视频的网站 | 国产精品一区三区 | 国产在线一区二区三区四区 | 久久996re热这里只有精品 | 亚洲色图在线观看视频 | 欧美高清网站 | 在线观看国产精美视频 | 小叔用力插插深点 | 亚洲黄色片免费看 | 韩国一级特黄清高免费大片 | 我的女儿韩国电视剧在线观看 | 亚洲男人的天堂久久无 | 国产福利一区二区在线观看 | 国产视频久久久久 | 国产精品国产三级国产普通话对白 | 欧美日韩一区二区三区视频播 | 欧美精品国产日韩综合在线 | 久久免费视频播放 | 人成午夜免费大片在线观看 | 国产一卡二卡3卡4卡无卡下载 | 99热这里只有免费国产精品 | 欧洲在线观看在线视频吗 |