GNU ARM匯編--(五)中斷匯編之嵌套中斷處理
嵌套中斷處理的核心代碼如下:
本文引用地址:http://butianyuan.cn/article/201611/321726.htm- ;/*
- ;*____________________________________________________________________
- ;*
- ;*Copyright(c)2004,AndrewN.Sloss,ChrisWrightandDominicSymes
- ;*Allrightsreserved.
- ;*____________________________________________________________________
- ;*
- ;*NON-COMMERCIALUSELicense
- ;*
- ;*Redistributionanduseinsourceandbinaryforms,withorwithout
- ;*modification,arepermittedprovidedthatthefollowingconditions
- ;*aremet:
- ;*
- ;*1.ForNON-COMMERCIALUSEonly.
- ;*
- ;*2.Redistributionsofsourcecodemustretaintheabovecopyright
- ;*notice,thislistofconditionsandthefollowingdisclaimer.
- ;*
- ;*3.Redistributionsinbinaryformmustreproducetheabove
- ;*copyrightnotice,thislistofconditionsandthefollowing
- ;*disclaimerinthedocumentationand/orothermaterialsprovided
- ;*withthedistribution.
- ;*
- ;*4.Alladvertisingmaterialsmentioningfeaturesoruseofthis
- ;*softwaremustdisplaythefollowingacknowledgement:
- ;*
- ;*ThisproductincludessoftwaredevelopedbyAndrewN.Sloss,
- ;*ChrisWrightandDominicSymes.
- ;*
- ;*THISSOFTWAREISPROVIDEDBYTHECONTRIBUTORS``ASISANDANY
- ;*EXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE
- ;*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULAR
- ;*PURPOSEAREDISCLAIMED.INNOEVENTSHALLTHECONTRIBUTORSBE
- ;*LIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,
- ;*ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOTLIMITEDTO,
- ;*PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,DATA,
- ;*ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDANDONANY
- ;*THEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,OR
- ;*TORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUT
- ;*OFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITY
- ;*OFSUCHDAMAGE.
- ;*
- ;*Ifyouhavequestionsaboutthislicenseorwouldlikeadifferent
- ;*licensepleaseemail:
- ;*
- ;*andrew@sloss.net
- ;*
- ;*
- ;*/
- ;/***********************************************************************
- ;*
- ;*Module:nih9_9.s
- ;*Descriptions:NestedInterruptHandler
- ;*Example:9.9
- ;*OS:generic
- ;*Platform:generic
- ;*History:
- ;*
- ;*31thDecember2003
- ;*-addedheader
- ;*
- ;***********************************************************************/
- EXPORTnestedInterruptHandler
- MaskmdEQU0x1f;processormodemask
- SVC32mdEQU0x13;SVCmode
- I_BitEQU0x80;IRQbit
- FRAME_R0EQU0x00
- FRAME_R1EQUFRAME_R0+4
- FRAME_R2EQUFRAME_R1+4
- FRAME_R3EQUFRAME_R2+4
- FRAME_R4EQUFRAME_R3+4
- FRAME_R5EQUFRAME_R4+4
- FRAME_R6EQUFRAME_R5+4
- FRAME_R7EQUFRAME_R6+4
- FRAME_R8EQUFRAME_R7+4
- FRAME_R9EQUFRAME_R8+4
- FRAME_R10EQUFRAME_R9+4
- FRAME_R11EQUFRAME_R10+4
- FRAME_R12EQUFRAME_R11+4
- FRAME_PSREQUFRAME_R12+4
- FRAME_LREQUFRAME_PSR+4
- FRAME_PCEQUFRAME_LR+4
- FRAME_SIZEEQUFRAME_PC+4
- AREAnih9_9,CODE,readonly
- nestedInterruptHandler;instructionstate:comment
- SUBr14,r14,#4;2:
- STMDBr13!,{r0-r3,r12,r14};2:savecontext
- ;
- BLread_RescheduleFlag;3:moreprocessing
- CMPr0,#0;3:ifprocessing?
- LDMNEIAr13!,{r0-r3,r12,pc}^;4:thenreturn
- MRSr2,SPSR;5:copySPSR_irq
- MOVr0,r13;5:copyr13_irq
- ADDr13,r13,#6*4;5:resetstack
- MRSr1,CPSR;6:copyCPSR
- BICr1,r1,#Maskmd;6:
- ORRr1,r1,#SVC32md;6:
- MSRCPSR_c,r1;6:changeSVCmode
- SUBr13,r13,#FRAME_SIZE-FRAME_R4;7:makestackspace
- STMIAr13,{r4-r11};7:saver4-r11
- LDMIAr0,{r4-r9};7:r4-r9IRQstack
- BICr1,r1,#I_Bit;8:
- MSRCPSR_c,r1;8:enableint
- STMDBr13!,{r4-r7};9:saver4-r7SVC
- STRr2,[r13,#FRAME_PSR];9:savePSR
- STRr8,[r13,#FRAME_R12];9:saver12
- STRr9,[r13,#FRAME_PC];9:savepc
- STRr14,[r13,#FRAME_LR];9:savelr
- ;
- LDMIAr13!,{r0-r12,r14};11:restorecontext
- MSRSPSR_cxsf,r14;11:restoreSPSR
- LDMIAr13!,{r14,pc}^;11:return
- read_RescheduleFlag
- ;
- MOVr0,#0;moreprocessing
- MOVpc,r14;return
- END
代碼的關鍵就是在中斷后切換到SVC模式下,利用svc mode的stack來實現(xiàn)中斷嵌套過程的備份以及恢復操作.從代碼中可以看到,從R0到PC都在棧中有備份,這里我們叫棧幀.記得《深入理解計算機系統(tǒng)》一書在講x86匯編的函數(shù)調(diào)用時也是棧幀的概念.這點上中斷嵌套和函數(shù)調(diào)用有相似之處.有了這個棧幀,利用壓棧出棧操作就一切ok了.
剛看這個代碼,對有個地方有疑問,就是覺得中斷開早了:
BIC r1,r1,#I_Bit ; 8 :
MSR CPSR_c,r1 ; 8 : enable int
STMDB r13!,{r4-r7} ; 9 : save r4-r7 SVC
STR r2,[r13,#FRAME_PSR] ; 9 : save PSR
STR r8,[r13,#FRAME_R12] ; 9 : save r12
STR r9,[r13,#FRAME_PC] ; 9 : save pc
STR r14,[r13,#FRAME_LR] ; 9 : save lr
覺得開中斷的代碼應該放在后面,這樣才能保證svc mode下的stack frame不會被破壞.但在草稿紙上畫一下irq和svc下的stack圖,就發(fā)現(xiàn)堆棧操作并沒有問題.可以假設剛開中斷立馬就有新的中斷了,r4-r7 r8 r9都有在STMIA r13,{r4-r11} 中保存到svc的stack中,LDMIA r0,{r4-r9} 和STMDB r13!,{r4-r7} 保證了最初的r0-r3在棧中,而LDMIA r0,{r4-r9}和STR r8,[r13,#FRAME_R12] 以及STR r9,[r13,#FRAME_PC] 保證了R12和PC,保證正確返回.(這里的r9裝的是r14_irq,所以pc就是r14_irq,這樣就保證了從中斷服務例程中返回).至于STR r14,[r13,#FRAME_LR]中的r14是r14_svc,將其壓入svc的stack中,中斷例程用bl就不會出現(xiàn)錯誤了,在最后LDMIA r13!,{r14,pc}^ 中r14得到恢復.而r2保存的是spsr,也就是svc模式的狀態(tài),一直不變,不用擔心會被覆蓋.
最后,再看了一遍圖,覺得r10和r11的幀可以省去,因為r4-r9是用來存atpcs的r0-r3,r12,r14,而r10和r11用不到.貌似可以省點空間和時間,具體的待會實驗一下.
下面給出實際的嵌套中斷處理,利用r10來保存INTOFFSET的值,根據(jù)該值來判定是什么中斷,從而做不同的處理.具體的效果是:代碼會做流水燈的動作,Key1代表INT1,中斷處理動作是4個燈全全亮然后全滅,Key4代表代表INT0,中斷處理動作是第一個燈和第三個燈亮,然后第二個燈和第四個燈亮.
- /*
- simpleinterruption
- copyleft@dndxhej@gmail.com
- */
- .equMaskmd,0x1f@processormodemask
- .equSVC32md,0x13@SVCmode
- .equI_Bit,0x80@IRQbit
- .equFRAME_R0,0x00
- .equFRAME_R1,FRAME_R0+4
- .equFRAME_R2,FRAME_R1+4
- .equFRAME_R3,FRAME_R2+4
- .equFRAME_R4,FRAME_R3+4
- .equFRAME_R5,FRAME_R4+4
- .equFRAME_R6,FRAME_R5+4
- .equFRAME_R7,FRAME_R6+4
- .equFRAME_R8,FRAME_R7+4
- .equFRAME_R9,FRAME_R8+4
- .equFRAME_R10,FRAME_R9+4
- .equFRAME_R11,FRAME_R10+4
- .equFRAME_R12,FRAME_R11+4
- .equFRAME_PSR,FRAME_R12+4
- .equFRAME_LR,FRAME_PSR+4
- .equFRAME_PC,FRAME_LR+4
- .equFRAME_SIZE,FRAME_PC+4
- .equNOINT,0xc0
- .equWTCON,0x53000000
- .equGPBCON,0x56000010@led
- .equGPBDAT,0x56000014@led
- .equGPBUP,0x56000018@led
- .equGPFCON,0x56000050@interruptconfig
- .equEINTMASK,0x560000a4
- .equEXTINT0,0x56000088
- .equEXTINT1,0x5600008c
- .equEXTINT2,0x56000090
- .equINTMSK,0x4A000008
- .equEINTPEND,0x560000a8
- .equINTSUBMSK,0X4A00001C
- .equSRCPND,0X4A000000
- .equINTPND,0X4A000010
- .equINTOFFSET,0x4A000014
- .global_start
- _start:breset
- ldrpc,_undefined_instruction
- ldrpc,_software_interrupt
- ldrpc,_prefetch_abort
- ldrpc,_data_abort
- ldrpc,_not_used
- @birq
- ldrpc,_irq
- ldrpc,_fiq
- _undefined_instruction:.wordundefined_instruction
- _software_interrupt:.wordsoftware_interrupt
- _prefetch_abort:.wordprefetch_abort
- _data_abort:.worddata_abort
- _not_used:.wordnot_used
- _irq:.wordirq
- _fiq:.wordfiq
- .balignl16,0xdeadbeef
- reset:
- ldrr3,=WTCON
- movr4,#0x0
- strr4,[r3]@disablewatchdog
- ldrr0,=GPBCON
- ldrr1,=0x15400
- strr1,[r0]
- ldrr2,=GPBDAT
- ldrr1,=0x160
- strr1,[r2]
- bldelay
- msrcpsr_c,#0xd2@進入中斷模式
- ldrsp,=0xc00@中斷模式的棧指針定義
- msrcpsr_c,#0xd3@進入svc模式
- ldrsp,=0xfff@設置svc模式的棧指針
- @--------------------------------------------
- ldrr0,=GPBUP
- ldrr1,=0x03f0
- strr1,[r0]
-
評論