ARM处理器异常处理的返回地址分析

来源:互联网 发布:linux拷贝文件夹到u盘 编辑:程序博客网 时间:2024/05/06 08:22

转自新浪博客:http://blog.sina.com.cn/bukeyanlongzhiyou

作者:于连庆,华清远见嵌入式学院讲师。

ARM 处理器一共有7 种类型的异常,按优先级从高到低排列如下:

Reset
Data Abort
FIQ
IRQ
Prefetch Abort
SWI
Undefined instruction

当任何一个异常发生并得到响应时,ARM内核自动完成以下动作:

1、拷贝CPSR到SPSR_<mode>
2、设置适当的CPSR位:
             改变处理器状态进入ARM状态;
             改变处理器模式进入相应的异常模式;
             设置中断禁止位禁止相应中断。
3、更新LR_<mode>
4、设置PC到相应的异常向量

当一个异常处理返回时,一共有3 件事情需要处理:通用寄存器的恢复、状态寄存器的恢复以及PC 指针的恢复。

通用寄存器的恢复采用一般的堆栈操作指令,而PC和CPSR的恢复可以通过一条指令来实现,下面是3 个例子:

MOVS pc, lr 或 SUBS pc, lr, #4 或LDMFD sp!, {pc}^

这几条指令都是普通的数据处理指令,特殊之处就是把PC寄存器作为了目标寄存器,并且带了特殊的后缀“S”或“^”,在特权模式下,“S”或“^”的作用就是使指令在执行时,同时完成从 SPSR 到CPSR 的拷贝,达到恢复状态寄存器的目的。

异常返回时另一个非常重要的问题是返回地址的确定,在前面曾提到进入异常时处理器会有一个保存LR 的动作,但是该保存值并不一定是正确的返回地址,下面以一个简单的指令执行流水状态图来对此加以说明。

ARM处理器异常处理的返回地址分析

我们知道在ARM 架构里,PC值指向当前执行指令的地址加8处,也就是说, 当执行指令A(地址0x8000)时,PC 等于指令C 的地址(0x8008)。假如指令A 是“BL”指令,则当执行该指令时,会把PC(=0x8008)保存到LR 寄存器里面,但是接下去处理器会马上对LR 进行一个自动的调整动作:LR=LR-0x4。这样,最终保存在 LR 里面的是 B 指令的地址,所以当从 BL 返回时,LR 里面正好是正确的返回地址。同样的调整机制在所有LR自动保存操作中都存在,比如进入中断响应时,处理器所做的LR 保存中,也进行了一次自动调整,并且调整动作都是LR=LR-0x4。

下面,我们对不同类型的异常的返回地址依次进行说明:

假设在指令A 处(地址0x8000)发生了异常,进入异常响应后,LR 上经过调整保存的地址值应该是B 的地址0x8004。

1、 如果发生的是软件中断,即A 是“SWI”指令

异常是由指令本身引起的,从 SWI 中断返回后下一条执行指令就是B,正好是LR 寄存器保存的地址, 所以只要直接把LR 恢复给PC。

MOVS pc, lr

2、 发生的是Undefined instruction异常

异常是由指令本身引起的,从异常返回后下一条执行指令就是B,正好是LR 寄存器保存的地址, 所以只要直接把LR 恢复给PC。

MOVS pc, lr

3、 发生的是IRQ或FIQ中断

因为指令不可能被中断打断,所以A指令执行完以后才能响应中断,此时PC已更新,指向指令D的地址(地址0x800C),LR 上经过调整保存的地址值是C 的地址0x8008。中断返回后应该执行B指令,所以返回操作是:

SUBS pc, lr, #4

4、 发生的是Prefetch Abort异常

该异常并不是处理器试图从一个非法地址取指令时触发,取出的指令只是被标记为非法,按正常处理流程放在流水线上,在执行阶段触发Prefetch Abort异常,此时LR 上经过调整保存的地址值是B 的地址0x8004。异常返回应该返回到A指令,尝试重新取指令,所以返回操作是:

SUBS pc, lr, #4

5、 发生的是“Data Abort”

CPU访问存储器时触发该异常,此时PC指向指令D的地址(地址0x800C),LR 上经过调整保存的地址值是C 的地址0x8008。异常返回后,应回到指令A,尝试重新操作存储器,所以返回操作是:

SUBS pc, lr, #8

原创粉丝点击