|
呵呵,找资料时找到了以前写的一篇日至,大家一起研究:)
a1m&b&a(n0IC开发网aV0zR^)n{;s4pjD
IC开发网9k RQQrH0F k.SSE
TroRF0
!SFe]cVJ9TE0
GW [N7q B0 今天花了点时间把中断的事又重新看了一遍,之前对中断的了解是模糊的。这下终于可以清楚地叙述中断的过程了,这都要感谢《基于arm的嵌入式程序开发要点.pdf》的作者,还有一部分关于重映射的的部分没看懂,其他的部分也不是都看明白了而是还没看,但看完了整篇文章也不知道作者是谁,让我怎么道谢呀。呵呵IC开发网)b&zj;]1Gx?H
IC开发网1Zr6dg7[7U!F"Q
#define IENABLE \
1Y}&jX:]r0__asm { MRS LR, SPSR } \ /* 在IRQ_mode读取SPSR_irq的内容 */
2Ek h)rg"g1?-t0__asm { STMFD SP!, {LR} } \ /* 在IRQ_mode将SPSR_irq的内容入栈 */
MVU/Y O0__asm { MSR CPSR_c,#0x1f } \ /* 将处理器模式由当前的中断IRQ_mode改为系统SYS_mode */IC开发网#@"C9cm9s-L
__asm { STMFD SP!,{LR} } /* 在SYS_mode将LR_sys入栈 */IC开发网lt'z2zp4])C
IC开发网'[t6a*a el2{
#define IDISABLE \
hF'Zd}d3d"[0__asm { LDMFD SP!,{LR} } \ /* 在SYS_mode将LR_sys出栈 */
[bJ@ I0@0__asm { MSR CPSR_c,#0x92} \ /* 将处理器模式由当前的系统SYS_mode改为中断IRQ_mode */
Kl(M3hH7@},N0f0__asm { LDMFD SP!,{LR} } \ /* 在IRQ_mode将SPSR_irq的内容出栈赋值给寄存器LR_irq */IC开发网.Dq#s#T,` b6Y
__asm { MSR SPSR_cxsf,LR} /* 由LR_irq将出栈后的内容赋给SPSR_cxsf */IC开发网uNq C4Z%N6P
H1Uv^:s0IC开发网%{4Y&Q!zw"H6A!Qo
上面这部分define是插在中断服务程序中的,所以在代码的开始就不需要重新修改LR的指针了,这部分功能已经在进入IC开发网'}V%Qk6|7UM.ZO
nYz.z%J"A r(_0H0IRQ时由IRQ中断的处理程序完成了。IC开发网)~&C-| j @,OY
IC开发网,m Z6Fu@,E
VL/Cy8C0O f:WG0
9R|2D)A,u'W%p.Lpy0在默认的状态中ARM的中断是不可重入的,一旦进入异常响应状态,处理器就会自动关闭中断使能。如果需要中断的嵌套,需要对中断用到的寄存器重新入栈。比如LR_irq和SPSR_irq和在中断中的调用BL的使用。IC开发网Q4S%uSPDZ
IC开发网 x3S'aAR Cji%E
在中断处理函数中发生函数调用(BL)是很常见的,假设有下面一种情况:IC开发网!?l*v|V&g
IRQ_Handler:IC开发网9o6bE~%D+X
…
4`E4\g%H.qQ0BL Foo -----------> Foo:
@R,N?h0ADD … STMFD SP!, {R0-R3, LR}
R ^+PyR^u2H0… …
9IMH4L7Q7]2|)vu0LDMFD SP!, {R0-R3, PC}IC开发网:a^4G6ol"IH
上述程序,在IRQ 处理函数IRQ_Handler() 中调用了函数Foo(),这是一个普通的异常处理函数。但若是在IRQ_Handler() 里面中断可重入的话,则可能发生问题,考察下面的情况:IC开发网GV%F \;F[eh
当新的中断请求恰好在“BL Foo”指令执行完成后发生。这时候LR 寄存器(因在IRQ 模式下,是LR_irq)的值将调整为BL 指令的下一条指令(ADD)地址,以期能从Foo() 正确返回;但是因为这时候发生了中断请求,接下去要进行新中断的响应,处理器为了能使新中断处理完成后能正确返回,也将进行LR_irq 保存。因为新中断是在指令流
n)k#Rd+\!_i!^ y0BL Foo --> STMFD SP!, {R0-R3, LR}IC开发网DY$sR C*p4~R
执行过程中插入的,完成跳转操作后,进行流水线刷新,最后LR_irq 保存的是STMFD 后面一条指令的地址;这样当新中断利用(PC = LR - 4)操作返回时,正好可以继续原来的流程执行STMFD 指令。这二次对LR_irq 的操作发生了冲突,当新中断返回后往下执行STMFD 指令,这时候压栈的LR 已不是原来需要的ADD 指令的地址,从而使子程序Foo() 无法正确返回。这个问题无法通过增加额外的现场保护指令来解决。一个巧妙的办法是在重新使能中断之前改变处理器的模式,也就是使上面程序中的“BL Foo”指令不要运行在IRQ 模式下。这样当新中断发生时就不会造成LR 寄存器的冲突了。考虑ARM 的所有运行模式,采用System 模式是最恰当的,因为它既是特权模式,又与中断响应无关。所以一个完整的可重入中断应该遵循以下流程:IC开发网5VcEh|B8P3A
IC开发网)KI)x#xv7f|L~
|
|