|
复位异常处理程序执行完后,不需要返回,因为系统复位后将开始整个用户程序的执行。复位异常之外的异常一旦处理完毕,使须恢复用户任务的正常执行,这就要求异常处理程序代码能精确地恢复异常发生时的用户状态。从异常中断处理程序中返回时,需要执行以下4个基本操作:
① 所有修改过的用户寄存器必须从处理程序的保护堆栈中恢复(即出栈)
② 将SPSR_mode寄存器内容复制到CPSR中,使得CPSR从相应的SPSR中恢复,即恢复被中断的程序工作状态。
③ 根据异常类型将PC变回到用户指令流中相应指令处。
④ 最后清除CPSR中的中断禁止标志位I/F。
需要强调的是,第2、3不能独立完成。这是因为,如果先恢复CPSR,则保存返回地址的当前异常模式的R14就不能再访问了;如果先恢复PC,异常处理程序将失去对指令流的控制,使得CPSR不能恢复。
为确保指令总是按正确的操作模式读取,以保证存储器保护方案不被绕过,还有更加微妙的困难。因此,ARM提供了2种返回处理机制,利用这些机制,可使上述2步作为一条指令的一部分同时完成。当返回地址保存在当前异常模式的R14时,使用其中一种机制;当返回地址保存在堆栈时,使用另一种机制。
首先看一看返回地址保存在R14的情形。
从SWI或未定义指令陷阱返回,使用:
MOVS PC,R14
从IRQ、FIQ或预取指中止返回,使用:
SUBS PC,R14,#4
从数据中止返回并重新存取数据,使用:
SUBS PC,R14,#8
当目的存储器时PC时,操作码后面的S修饰符表示特殊形式的指令。注意返回指令如何在必要时对返回地址进行调整:
IRQ和FIQ必须返回前一条指令,以便执行因进入异常而被“占据”的指令。
预取指中止必须返回前一条指令,以便执行在初次请求访问时造成存储器故障的指令。
数据中止必须返回前面第二条指令,以便重新执行因进入异常而被占用的指令之前的数据传送指令。
如果异常处理程序把返回地址拷贝到堆栈,可使用一条如下的多寄存器传送指令来恢复用户寄存器并实现返回:
LDMFD R13!,(R0-R3,PC);恢复和返回
这里,寄存器列表后面的“^”表示这是一条特殊形式的指令。在从存储器中装入PC的同时,CPSR也得到恢复。由于寄存器是按照升序装入的,所以PC是从寄存器传送的最后一个数据。
这里使用的堆栈指针R13是属于特权操作模式的寄存器;每个特权模式都可有它自己的堆栈指针;这个堆栈指针必须在系统启动时进行初始化。
显然,只有当R14的值在存入堆栈之前进行调整,才可使用堆栈的返回机制。
凌阳教育,专注嵌入式人才培养13年,完善的培养方案,强大的师资,合理的课程安排,成功从小白蜕变为嵌入式工程师。想了解凌阳教育,或者获得更多嵌入式学习资料的免费下载,请点击www.sunplusedu.com访问凌阳教育官网。