异常发生时的硬件操作及异常返回时的处理
一、异常发生后,ARM Core会自动完成以下操作:
n 保存返回地址到 LR_<mode>
n 拷贝 CPSR 到 SPSR_<mode>
n 改变处理器模式进入相应的异常模式
n 设置适当的 CPSR 位
n 改变处理器状态进入 ARM 状态
n 设置中断禁止位禁止相应中断 (如果需要)
n 设置 PC 跳转到相应的异常向量表入口
用伪码来表示整个过程如下:
R14_<Exception_Mode> = Return Link
SPSR_<Exception_Mode> = CPSR
CPSR[4:0] = Exception Mode Number
CPSR[5] = 0 ;当运行于ARM 工作状态时
If <Exception_Mode> == Reset or FIQ then
;当响应FIQ 异常时,禁止新的FIQ 异常
CPSR[6] = 1
CPSR[7] = 1
PC = Exception Vector Address
异常向量表
地址 | 异常类型 | 进入异常模式 |
0x0000_0000或0xFFFF0000 | 复位 | SVC (管理模式) |
0x0000_0004或0xFFFF0004 | 未定义指令 | UND (未定义模式) |
0x0000_0008或0xFFFF0008 | 软件中断 | SVC (管理模式) |
0x0000_000C或0xFFFF000C | 中止(预取指令) | ABT (中止模式) |
0x0000_0010或0xFFFF0010 | 中止(数据) | ABT (中止模式) |
0x0000_0018或0xFFFF0018 | 外部中断 IRQ | IRQ (中断模式) |
0x0000_001C或0xFFFF001C | 快速中断 FIQ | FIQ (快速中断模式) |
二、ARM 处理器从异常中断处理程序中返回后的两个基本的操作:
1.恢复被中断的程序的处理器状态,即将SPSR_MODE寄存器捉的内容复制到当前程序状态寄存器CPSR中。
2.返回到发生异常中断的指令的下一条指令处执行,即将LR_MODE的寄存器的内容复制到程序计数器PC中。
指令预取异常中断与数据访问中止异常中断返回到产生指令预取异常中断与数据访问中止异常中断的指令处,而不是返回到发生异常中断的指令的下一条指令处执行。
根据ARM 的流水线结构,一条指令在执行时,下一条指令在译码,而再下一条指令在取指,因此PC值始终为当前执行指令地址加8,虽然在异常响应时,处理器自动进行了返回地址的修正;LR=PC-4(当前指令的下一条指令),但这个值并不一定就是异常处理返回后要执行的指令地址,具体情况取决于何种异常,分析如下:
复位异常中断的处理程序不需要返回,整个应用系统是从复位异常中断处理程序开始执行的,因而它不需要返回。
对于IRQ和FIQ异常中断,因为处理器是在执行完当前指令后,再去查询并响应中断的,此时的当前指令已为中断回后将要执行的指令,而非下一条指令,所以程序中要将返回地址中数值修正为LR-4。
对于预取指令异常中断,处理器首先将预取异常指令标记,中断则是在处理器执行到此被标记指令的产生,对于此种异常的处理,程序应重新读取并执行,因此返回地址应为当前指令,而非下一条指令,所以返回地址修正为LR-4。
对于数据访问中止异常,此异常发生时,数据访问指令已被执行,当前指令已更新为下一条指令,此异常的处理,程序应该返回到产生此异常的数据读取指令处(即当前指令的上一条指令)重新读取数据,因此返回地址就修正为LR-4-4。
对于SWI与未定义指令异常,此异常发生时,中断由当前执行的指令自身产生,当前指令未更新为下一条指令,程序应该返回到当前指令的下一条指令。
异常和返回地址
异常 | 地址 | 用途 | 中断产生时,PC值是否更新 |
复位 | — | 复位没有定义LR |
|
数据中止 | LR-8 | 指向导致数据中止异常的指令 | PC值更新 |
FIQ | LR-4 | 指向发生异常时正在执行的指令 | PC值更新 |
IRQ | LR-4 | 指向发生异常时正在执行的指令 | PC值更新 |
预取指令中止 | LR-4 | 指向导致预取指令异常的那条指令 | PC值未更新 |
SWI | LR | 执行SWI指向的下一条指令 | PC值未更新 |
未定义指令 | LR | 指向未定义指令的一打指令 | PC值未更新 |
当异常中断处理程序中使用了数据栈时,可以通过下面的指令在进入异常中断处理程序时保存被中断程序的执行现在,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断处理程序中使用的数据栈由用户提供。
返回的操作指令可以用下面的指令来实现:
MOV PC,LR 或者 SUBS PC,LR,#0x04或SUBS PC,LR,#0x08(三者选其一)
STMFD SP!,{reglist,LR}
;……..
LDMFD SP!, {reglist,LR}^
在上述指令中reglist是异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_MODE寄存器内容复制到程序状态寄存器CPSR中。该指令只能在特权模式(管理模式SVC)下使用。