2440中断解析
$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)
MEN
将sp减少一个字节,使其在堆栈高端留出存储返回地址,因为pc在寄存器组 中的位置大于r0,出栈时装入的是栈的高端的内容
保存r0
装载中断处理函数的指针
装载中断处理函数的地址
将中断处理函数的地址存入刚才预留的位置,r0的上面
出栈后,pc指向的既是中断处理函数的地址
以上是个宏,用于把中断服务程序的首地址装载到pc中,我称它为“加载程序”。
本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字空间都有一个标号,以Handle***命名。
在向量中断模式下使用“加载程序”来执行中断服务程序。
下面是每个中断源的“加载程序”
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
下面这段程序的首地址将要被放到HandleIRQ中,在非向量中断模式下发生IRQ中断时,执行此程序来判断中断源以执行相应的中断服务程序。
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}
下面就是把IsrIRQ的首地址装载到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]
ALIGN
AREA RamData, DATA, READWRITE
异常向量表
^
_ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
HandleReset #
4
HandleUndef #
4
HandleSWI #
4
HandlePabort
#
4
HandleDabort
#
4
HandleReserved
#
4
HandleIRQ #
4
HandleFIQ #
4
中断向量表
;Do not use the label IntVectorTable,
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable
;@0x33FF_FF20
HandleEINT0 #
4
HandleEINT1 #
4
HandleEINT2 #
4
HandleEINT3 #
4
HandleEINT4_7 #
4
HandleEINT8_23 #
4
HandleCAM #
4 ; Added for
2440.
HandleBATFLT #
4
HandleTICK #
4
HandleWDT #
4
HandleTIMER0 #
4
HandleTIMER1 #
4
HandleTIMER2 #
4
HandleTIMER3 #
4
HandleTIMER4 #
4
HandleUART2
#
4
;@0x33FF_FF60
HandleLCD #
4
HandleDMA0 #
4
HandleDMA1 #
4
HandleDMA2 #
4
HandleDMA3 #
4
HandleMMC #
4
HandleSPI0 #
4
HandleUART1 #
4
HandleNFCON #
4 ; Added for 2440.
HandleUSBD #
4
HandleUSBH #
4
HandleIIC #
4
HandleUART0 #
4
HandleSPI1 #
4
HandleRTC #
4
HandleADC #
4
;@0x33FF_FFA0
END
本程序的初始化中断部分实现的很巧妙,基于34个字单元将向量中断和非向量中断的实现结合在一起。
向量中断直接使用“加载程序”,把相应的中断服务程序首地址(存放于Handle***)加载到PC。
非向量中断通过执行IsrIRQ判断中断源,并同时计算出相应Handle***的地址,再将此地址的内容加载到PC。
我有两个问题:
问题一,非向量中断有个缺点,它始终从优先级最低的中断源开始识别,且是通过过分析I_ISPR寄存器的每一位来识别,但是尽管有多个中断同时发生,I_ISPR只有一位置1。如此一来,频繁发生低优先级中断是否会屏蔽其他中断?
我有过一次试验,设置两个中断INT_TICK和INT_TIMER5,两个中断服务程序都使用串口打印一串字符。当TIMER5以频率为1KHz(每毫秒一次)中断时,TICK中断服务程序毫无反应。
问题二,本代码中有这样一段
b HandlerIRQ
b HandlerFIQ
;***IMPORTANT NOTE***
;If the H/W vectored interrutp mode is enab
led, The above two instructions should
;be changed like below, to work-around with H/W bug of S3C44B0X
interruptcontroller.
; b HandlerIRQ -> subs pc,lr,#4
; b HandlerIRQ -> subs pc,lr,#4
大意是如果使用向量中断模式,必须用subs pc,lr,#4代替b HandlerIRQ。
首先我不太确定发生向量中断时,CPU是否执行b HandlerIRQ,还是直接转向相应中断源的向量地址。如果不执行b HandlerIRQ,那么subs pc,lr,#4有何意义?如果执行b HandlerIRQ,那subs pc,lr,#4岂不是又使CPU从IRQ模式转换回SVC模式,继续执行被中断了的代码,这又是何意义?
另外,我按照他的方法试过,设置INTCON为向量中断,但一运行系统就重起,改回非向量中断一切正常。
评论