5.1 对异常的响应 当一个异常出现以后,ARM微处理器会执行以下几步操作:
• 将下一条指令的地址存入相应连接寄存器LR,以便程序在处理异常返回时能从正确的位置重新开始执行。
• 将CPSR复制到相应的SPSR中。
• 根据异常类型,强制设置CPSR的运行模式位。
• 强制PC从相关的异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序处。
处理器处于Thumb状态,则当异常向量地址加载入PC时,处理器自动切换到ARM状态。ARM微处理器对异常的响应过程用伪码可以描述为:
- R14_tion_Mode> = Return Link
- SPSR_ = CPSR
- CPSR[4:0] = Exception Mode Number
- CPSR[5] = 0 // 在ARM状态下执行
- If == Reset or FIQ then
- CPSR[6] = 1 // 禁止FIQ
- CPSR[7] = 1 // 禁止IRQ
- PC = Exception Vector Address // 转入异常入口地址
复制代码
5.2 从异常返回 异常处理完毕之后,ARM微处理器会执行以下几步操作从异常返回:
• 将连接寄存器LR的值减去相应的偏移量后送到PC中。
• 将SPSR复制回CPSR中。
• 若在进入异常处理时设置了中断禁止位,要在此清除。
• 可以认为应用程序总是从复位异常处理程序开始执行的,因此复位异常处理程序不需要返回。
5.2.1 FIQ (Fast Interrupt Request) FIQ异常是为了支持数据传输或者通道处理而设计的。
若将CPSR的F位置为1,则会禁止FIQ中断,若将CPSR的F位清零,处理器会在指令执行时检查FIQ的输入。注意只有在特权模式下才能改变F位的状态。
可由外部通过对处理器上的nFIQ引脚输入低电平产生FIQ。不管是在ARM状态还是在Thumb状态下进入FIQ模式,FIQ处理程序均可以执行以下指令从FIQ模式返回:
SUBS PC,R14_fiq ,#4
5.2.2 IRQ (Interrupt Request) IRQ异常属于正常的中断请求,可通过对处理器的nIRQ引脚输入低电平产生,IRQ的优先级低于FIQ,当程序执行进入FIQ异常时,IRQ可能被屏蔽。
若将CPSR的I位置为1,则会禁止IRQ中断,若将CPSR的I位清零,处理器会在指令执行完之前检查IRQ的输入。注意只有在特权模式下才能改变I位的状态。
不管是在ARM状态还是在Thumb状态下进入IRQ模式,IRQ处理程序均可以执行以下指令从IRQ模式返回:
SUBS PC , R14_irq , #4
5.2.3 ABORT(中止) 产生中止异常意味着对存储器的访问失败。ARM微处理器在存储器访问周期内检查是否发生中止异常。
中止异常包括两种类型:
• 指令预取中止:发生在指令预取时。
• 数据中止:发生在数据访问时。
当指令预取访问存储器失败时,存储器系统向ARM处理器发出存储器中止(Abort)信号,预取的指令被记为无效,但只有当处理器试图执行无效指令时,指令预取中止异常才会发生,如果指令未被执行,例如在指令流水线中发生了跳转,则预取指令中止不会发生。
若数据中止发生,系统的响应与指令的类型有关。
当确定了中止的原因后,Abort处理程序均可以执行以下指令从中止模式返回,无论是在ARM状态还是Thumb状态:
SUBS PC, R14_abt, #4 ;指令预取中止
SUBS PC, R14_abt, #8 ;数据中止
5.2.4 Software Interruupt(软件中断) 软件中断指令(SWI)用于进入管理模式(svc),常用于请求执行特定的管理功能。软件中断处理程序执行以下指令可以从SWI模式返回,无论是在ARM状态还是Thumb状态:
MOVS PC , R14_svc
以上指令恢复PC(从R14_svc)和CPSR(从SPSR_svc) 的值,并返回到SWI的下一条指令。
5.2.5 Undefined Instruction(未定义指令) 当ARM处理器遇到不能处理的指令时,会产生未定义指令异常。采用这种机制,可以通过软件
仿真扩展ARM或Thumb指令集。
处理器执行以下程序返回,无论是在ARM状态还是Thumb状态:
MOVS PC, R14_und
以上指令恢复PC(从R14_und)和CPSR(从SPSR_und)的值,并返回到未定义指令后的下一条指令。
5.2.6 异常向量表(Exception Vectors)
5.2.7 异常优先级(Exception Priorities)
5.2.8 应用程序中的异常处理 当系统运行时,异常可能会随时发生,为保证在ARM处理器发生异常时不至于处于未知状态,在应用程序的设计中,首先要进行异常处理,采用的方式是在异常向量表中的特定位置放置一条跳转指令,跳转到异常处理程序,当ARM处理器发生异常时,程序计数器PC会被强制设置为对应的异常向量,从而跳转到异常处理程序,当异常处理完成以后,返回到主程序继续执行。
我们需要处理所有的异常,尽管我们可以简单的在某些异常处理程序处放置死循环。