首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ARM 异常处理过程讲解(2)

ARM 异常处理过程讲解(2)

我们知道在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发生的是IRQFIQ中断
因为指令不可能被中断打断,所以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
以上就是ARM异常的CPU操作部分,接下来就是程序员应该完成的操作。
1.         由于CPU会自动跳转到对应的异常向量中,因此只需要在在各个异常向量中存放对应的操作,最简单的都是存放一个B指令跳转到对应的异常处理函数的操作即可。但由于B指令的跳转返回只有+-32M,而异常处理函数的地址可能会超过+-32M,因此可以采用另一种方式实现方式:在异常向量中保存一条指令LDR PC [addr],其中的addr中就保存了异常处理函数的地址,当然addr的相对地址要小于+-32M。这样也就解决了跳转范围的问题。
2.         接下来就是异常处理函数对应的操作,可以在进入异常处理之前就进行返回地址的调整,这样后面就不用进行处理啦,当然也可以在返回过程中再调整。一般都是在这个过程中进行调整。进行压栈操作,保存对应的环境变量。调用实际的处理过程等。
3.         出栈,恢复CPU的状态和寄存器的值。由于第一步中已经调整好返回地址,这一步不需要再次调整。当然如果之前没有调整,这里则需要进行相应的调整。
返回列表