新闻中心

2440中断解析

作者: 时间:2016-11-21 来源:网络 收藏
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)
MEN
将sp减少一个字节,使其在堆栈高端留出存储返回地址,因为pc在寄存器组 中的位置大于r0,出栈时装入的是栈的高端的内容
保存r0
装载中断处理函数的指针
装载中断处理函数的地址
将中断处理函数的地址存入刚才预留的位置,r0的上面
出栈后,pc指向的既是中断处理函数的地址
以上是个宏,用于把中断服务程序的首地址装载到pc中,我称它为“加载程序”。
本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字空间都有一个标号,以Handle***命名。
在向量中断模式下使用“加载程序”来执行中断服务程序。

sub sp,sp,#4是把SP的地址减4字节,而这个地方需要存放跳转地址也就是第5行的HandleSWI指向的内容(ISR),将此内容写入pc,实现跳转

本文引用地址: //m.amcfsurvey.com/article/201611/319269.htm

接下来是压栈所需要的寄存器r0,因为接下来需要使用r0所以先压栈r0,这也是为什么刚刚先把SP加四字节的原因,第6句话就是跳转到刚刚第5句所压栈的地址处,也就是HandleSWI指向的内容(ISR)处

下面是每个中断源的“加载程序”
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为向量中断,但一运行系统就重起,改回非向量中断一切正常。



关键词:2440中断解

评论


技术专区

关闭