ARM处理器架构异常/中断处理
首先,中断是异常的一种。当发生一种异常时,处理器会进入不同的工作模式。ARM的异常和相应的模式之间的对应关系见下表:
当一个异常导致模式的改变时,ARM核自动地:
1、把cpsr保存到相应模式下的spsr
2、把pc保存到相应模式下的lr
3、设置cpsr为相应异常模式
4、设置pc为相应异常处理程序的入口地址
对于IRQ或者FIQ而言,还多一项变化:禁用相关的中断IRQ或FIQ,禁止同类型的其他中断被触发。(这也是自动实现的,因此正常情况下,ARM中断不可嵌套)
从异常中断处理程序退出时,需要我们在程序中用软件实现下面两个操作:
1、从spsr_mode中恢复数据到cpsr中
2、从lr_mode中恢复内容到pc中,返回到异常中断的指令的下一条政令处执行.
2440默认的有一个异常向量表,即发生某一个异常后,会根据异常向量表设置pc为相应的处理函数入口地址。
地址 | 异常名称 | 指令 |
0x00 | 复位异常 | B RestHandler |
0x04 | 未定义指令异常 | B HandlerUndef |
0x08 | 软件中断异常 | B HandlerSWI |
0x0C | 指令预取异常 | B HandlerPabort |
0x10 | 数据预取异常 | B HandlerDabort |
0x14 | 保留 | |
0x18 | IRQ中断异常 | B HandlerIRQ |
0x1C | FIQ中断异常 | B HandlerFIQ |
上表中的 指令都是在2440init.s中的程序表示。
下面,我们结合板子自带的2440test源代码中的2440init.s中的异常处理,来分析arm中断处理的实现。
首先,在2440init.s中有:
__ENTRYb ResetHandlerb HandlerUndef ;handler for Undefined modeb HandlerSWI ;handler for SWI interruptb HandlerPabort ;handler for PAbortb HandlerDabort ;handler for DAbortb . ;reservedb HandlerIRQ ;handler for IRQ interruptb HandlerFIQ ;handler for FIQ interrupt
这里就是相应的 异常处理向量表。程序正常启动就跳转到resethandler,如果是发生中断就跳转到handlerIRQ。对于handlerIRQ,它是用一个宏实现的。
MACRO$HandlerLabel HANDLER $HandleLabel$HandlerLabelsub sp,sp,#4 ;decrement sp(to store jump address)stmfd sp!,{r0} ;PUSH the work register to stack(lr doest push because it return to original address)ldr r0,=$HandleLabel;load the address of HandleXXX to r0ldr r0,[r0] ;load the contents(service routine start address) of HandleXXXstr r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stackldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)MEND上面是宏的声明。下面是具体用到宏的地方。
HandlerFIQ HANDLER HandleFIQHandlerIRQ HANDLER HandleIRQHandlerUndef HANDLER HandleUndefHandlerSWI HANDLER HandleSWIHandlerDabort HANDLER HandleDabortHandlerPabort HANDLER HandlePabort上面的这段程序在编译的时候会被编译器展开,我们可以将其中的IRQ相关的展开如下:
HandlerIRQ HANDLER HandleIRQ 会被下面的代码段替换:
HandlerIRQ sub sp,sp,#4 ;decrement sp(to store jump address)stmfd sp!,{r0} ;PUSH the work register to stack(lr doest push because it return to original address)ldr r0,=HandleIRQ ;load the address of HandleXXX to r0ldr r0,[r0] ;load the contents(service routine start address) of HandleXXXstr r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stackldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
因此,发生中断时,就会b HandlerIRQ,跳转到上面的代码进行执行。按照上面的流程,处理器会把HandleIRQ地址中所存储的数 付给pc指针,作为下一条指令的地址,然后执行。那么HandleIRQ地址中存储的数是什么呢?
在2440init.s中有这样一段程序:
ldr r0,=HandleIRQ ;This routine is neededldr r1,=IsrIRQ ;if there isnt subs pc,lr,#4 at 0x18, 0x1cstr r1,[r0]从这里,可以看出,HandleIRQ中存的是IsrIRQ。所以处理器会跳转到isrIRQ中执行。
IsrIRQsub sp,sp,#4 ;reserved for PCstmfd sp!,{r8-r9}ldr r9,=INTOFFSETldr r9,[r9]ldr r8,=HandleEINT0add r8,r8,r9,lsl #2ldr r8,[r8]str r8,[sp,#8]ldmfd sp!,{r8-r9,pc}
在上面的程序中,INTOFFSET表示的是中断号对于EINT0的偏移号。这样计算得到中断向量号之后,跳转到中断函数进行处理。对于,上面的程序奇怪的一点是没有看到恢复cpsr和pc指针。因
ARM处理器架构异常中断处 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)