深入講解IRQ中斷過(guò)程
標(biāo)準(zhǔn)中斷步驟(IRQ):
1. AIC已經(jīng)正確編程,AIC_SVR也已經(jīng)寫(xiě)入正確的中斷服務(wù)程序的入口地址。且中斷已經(jīng)使能
2. 地址0x18(IRQ的中斷向量地址)的指令為
LDR PC,[PC,#&F20]
當(dāng)NIRQ到來(lái),且CPSR的I位為0時(shí),步驟如下:
① CPSR被拷貝到SPSR_irq,當(dāng)前程序計(jì)數(shù)器PC的值被保存到IRQ鏈接寄存器(R14_irq),同時(shí)PC(R15)自身也被賦予了新值0x18。在接下來(lái)的時(shí)鐘里(處理器向0x1C取指令),ARM核使R14_ irq減4
②ARM內(nèi)核進(jìn)入IRQ模式
③當(dāng)指令LDR PC,[PC,#&F20]得到執(zhí)行(ARM為流水線結(jié)構(gòu),當(dāng)前PC之前還有兩條指令)后,PC被賦予了AIC_IVR的內(nèi)容。讀取AIC_IVR具有如下作用:
·將當(dāng)前中斷設(shè)置為被掛起的最高優(yōu)先級(jí)中斷,并把它作為最高優(yōu)先級(jí)的中斷;當(dāng)前中斷級(jí)別則設(shè)置為此中斷的優(yōu)先級(jí)。
·將NIRQ的信號(hào)撤消(即使系統(tǒng)沒(méi)有用到向量功能,也必須去讀AIC_IVR,以便將NIRQ撤消)。
·如果中斷為邊沿觸發(fā),則讀取AIC_IVR會(huì)自動(dòng)將中斷清除
·將當(dāng)前的中斷的優(yōu)先級(jí)推入堆棧
·返回當(dāng)前中斷的AIC_SVR的值。
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)??


④上述步驟將程序跳到了對(duì)應(yīng)的中斷服務(wù)程序。接下來(lái)的第一步是保存鏈接寄存器LR(R14_irq)和SPSR(SPSR_irq)。如果需要在中斷返回時(shí),把LR的值直接賦給程序計(jì)數(shù)器,則LR首先要減去4 才能保存。否則在中斷返回時(shí),LR要首先減去4之后才能拷貝給PC。
⑤清零CPSR的位I就可以使其他中斷不被屏蔽,再施加的NIRQ可以被內(nèi)核接受。只要發(fā)生的中斷的優(yōu)先級(jí)高于當(dāng)前中斷的優(yōu)先級(jí),嵌套中斷就會(huì)發(fā)生。
⑥接著中斷例程可以保存相應(yīng)的寄存器以保護(hù)現(xiàn)場(chǎng)。如果此時(shí)有高優(yōu)先級(jí)中斷發(fā)生,則處理器將重復(fù)執(zhí)行從步驟①開(kāi)始的動(dòng)作。要注意的是,如果中斷是電平敏感的,那么在中斷結(jié)束前要清除中斷源。
⑦在退出中斷前要首先置位CPSR的位I,以便屏蔽其他中斷,保證多個(gè)中斷有序地完成。
⑧在結(jié)束中斷之前還必須執(zhí)行一次對(duì)AIC_EOICR的寫(xiě)操作,向AIC表明中斷已經(jīng)完成。存放于堆棧的前一個(gè)當(dāng)前中斷優(yōu)先級(jí)將被彈出并作為當(dāng)前中斷優(yōu)先級(jí)。如果此時(shí)系統(tǒng)又有一個(gè)掛起的中斷,其優(yōu)先級(jí)比剛才結(jié)束的中斷的優(yōu)先級(jí)低(或相等)、但又高于從堆棧彈出來(lái)的中斷的優(yōu)先級(jí),則將重新施加NIRQ;但是,中斷步驟不會(huì)立即開(kāi)始,因?yàn)榇藭r(shí)CPSR的I位是置位的。
⑨SPSR(SPSR_irq)被恢復(fù)。最后是鏈接寄存器LR恢復(fù)到PC。程序返回到中斷發(fā)生前之處。 SPSR也恢復(fù)為CPSR,中斷屏蔽狀態(tài)恢復(fù)為SPSR所指明的狀態(tài)。
注:SPSR的位I是很重要的。如果在SPSR恢復(fù)之后為置位狀態(tài),則表明ARM核正要屏蔽中斷,在執(zhí)行屏蔽指令時(shí)被中斷。因此,SPSR恢復(fù)后,屏蔽指令得以完成,亦即I被置位,
因而IRQ 被屏蔽。
