arm嵌套中断

arm异发生时,硬件会自动保存pc到异常模式下的lr,以及保存cpsr到spsr,把cpsr设置为相应异常模式,把pc设置为相应异常处理程序的入口。这个问题就来了,如果发生嵌套中断,那么会覆盖之前中断的lr,无法返回。

为了避免这个问题,在执行ISR之前,会进行模式切换,切换到SVC货系统模式。在相应的模式下构造一个帧,就像一般的函数调用栈帧,保存现场,保存lr,sp等等。接着调用ISR,如果发生中断就继续构造栈帧。这样返回的时候就会像函数调用那样一层一层返回。。


分析arm-linux里面的中断,也是用的这个方法。

vector_irq:

   .if 4

   sub   lr, lr, #4

   .endif

 

   @

   @ Save r0, lr_<exception> (parent PC) and spsr_<exception>

   @ (parent CPSR)

   @

   stmia sp, {r0, lr}    @ save r0, lr

   mrs   lr, spsr

   str   lr, [sp, #8]    @ save spsr

 

   @

   @ Prepare for SVC32 mode.  IRQs remain disabled.

   @

   mrs   r0, cpsr

   eor   r0, r0, #(IRQ_MODE ^ SVC_MODE | PSR_ISETSTATE)

   msr   spsr_cxsf, r0

 

   @

   @ the branch table must immediately follow this code

   @

// lr中当前存储了进入异常处理程序之前的状态寄存器的值,宏定义的前面部

// 分有从spsr取值到lr的代码,对后几位做与,即是获取在中断前处理器所

// 处的状态,这个值在后面会被用作跳转表的索引。

   and   lr, lr, #0x0f

// 用做他用,sp值当第一个参数传给后面函数

   mov   r0, sp

// pc是当前执行指令地址加8,即跳转表的基地址,lr是索引,很好的技巧,

// 取pc获取当前指令地址什么时候都没错

ARM(   ldr   lr, [pc, lr, lsl #2]  )

   movs  pc, lr      @ branch to handler in SVC mode

ENDPROC(vector_irq)

后面会跳入到__irq_svc   entry_armv.S里面看。

开始就会调用svc_entry,里面会构造栈帧。最后调用svc_exit恢复。


你可能感兴趣的:(arm嵌套中断)