ARM微处理器的编程模型之:异常中断处理
0x8000+8=0x8008,即等于指令C的地址。假设指令A是BL指令,则当执行时,会把PC值(0x8008)保存到LR寄存器。但是,接下来处理器会对LR进行一次自动调整,使LR=LR-0x4。所以,最终保存在LR里面的是图3.5中所示的B指令地址。所以当从BL返回时,LR里面正好是正确的返回地址。 同样的跳转机制在所有的LR自动保存操作中都存在。当进入中断响应时,处理器对保存的LR也进行一次自动调整,并且跳转动作也是LR=LR-0x04。由此,就可以对不同异常类型的返回地址依次比较。 假设在指令B处(地址0x8004)发生了异常,进入异常相应后,LR经过跳转保存的地址值应该是C的地址0x8008。 (1)软中断异常 如果发生软中断异常,即指令B为SWI指令,从SWI中断返回后下一条执行指令就是C,正好是LR寄存器保存的地址,所以只有直接把LR恢复给PC即可。 (2)IRQ或FIQ异常 如果发生的是IRQ或FIQ异常,因为外部中断请求中断了正在执行的指令B,当中断返回后,需要重新回到B指令执行,也就是说,返回地址应该是B(0x8004),需要把LR减4送PC。 (3)Data Abort数据中止异常 在指令B处进入数据异常的相应,但导致数据异常的原因却应该是上一条指令A。当中断处理程序恢复数据异常后,要回到A重新执行导致数据异常的指令,因此返回地址应该是LR加8。 为方便起见,表3.7总结了各异常和返回地址的关系 表3.7 异常和返回地址 异 常 地 址 用 途 复位 - 复位没有定义LR 数据中止 LR-8 指向导致数据中止异常的指令 FIQ LR-4 指向发生异常时正在执行的指令 IRQ LR-4 指向发生异常时正在执行的指令 预取指令中止 LR-4 指向导致预取指令异常的那条指令 SWI LR 执行SWI指令的下一条指令 未定义指令 LR 指向未定义指令的下一条指令 如果系统启动不依赖于Debug或Debug monitor软件,可以使用汇编语言在系统启动时直接安装异常处理程序。 下面的例子显示了系统从0x0地址启动,直接安装异常处理程序的方法。 Vector_Init_Block LDR PC, Reset_Addr LDR PC, Undefined_Addr LDR PC, SWI_Addr LDR PC, Prefetch_Addr LDR PC, Abort_Addr NOP ;保留向量 LDR PC, IRQ_Addr LDR PC, FIQ_Addr Reset_Addr DCD Start_Boot Undefined_Addr DCD Undefined_Handler SWI_Addr DCD SWI_Handler Prefetch_Addr DCD Prefetch_Handler Abort_Addr DCD Abort_Handler DCD 0 ;保留向量 IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler 有些情况下,系统0x0地址不一定是ROM。如果0x0地址为RAM,那么就系统将中断向量表从ROM复制RAM,下面的例子显示了这样一个过程。 MOV R8, #0 ADR R9, Vector_Init_Block LDMIA R9!,{r0-r7} ;复制中断向量表 (8 words) STMIA R8!,{r0-r7} LDMIA R9!,{r0-r7} ;复制由伪操作 DCD定义的地址 STMIA R8!,{r0-r7} 注意 可以使用Scatter文件定义加载向量表的地址,这样上述代码的拷贝工作由C库函数完成。 程序中有时需要在main()函数中使用C语言安装中断向量表。这就要求指令经编译后的解码能安装在内存的正确位置。 (1)向量表中使用跳转指令的情况 如果在向量表中使用跳转指令,使用下面的步骤完成向量表的安装。 ① 读取异常处理程序的地址。 ② 从异常处理程序地址中减去向量表中的偏移。 ③ 为适应指令流水线,将上一步得到的地址减8。 ④ 将得到的结果右移2位,得到以字为单位的地址偏移量。 ⑤ 将结果的高8位清零,得到跳转指令的24位偏移量。 ⑥ 将上一步得到的结果和0xea000000(无条件跳转指令编码)做逻辑与操作,从而得到要写到向量表中的跳转指令的正确编码。 下面的例子显示了这样一个标准过程。 unsigned Install_Handler (unsigned routine, unsigned *vector) { unsigned vec, oldvec; vec = ((routine - (unsigned)vector - 0x8)>>2); if ((vec 0xFF000000)) { /* diagnose the fault */ prinf (Installation of Handler failed); exit (1); } vec = 0xEA000000 | vec; oldvec = *vector; *vector = vec; return (oldvec); } (2)在向量表中使用加载PC指令 在向量表中使用加载PC指令,按照下面的步骤完成。 ① 读取异常处理程序地址。 ② 从异常处理程序地址中减去向量表中的偏移。 ③ 为适应指令流水线,将上一步得到的地址减8。 ④ 保留结果的后12位。 ⑤ 将结果与0xe59ff000(LDR PC, [PC,#offset])做逻辑或操作,从而得到要写到向量表中的跳转指令的正确编码。 ⑥ 将异常处理程序的地址放到相应的存储单元。 下面的例子显示了一个标准的C语言过程。 unsign3.4.6 在应用程序中安装异常处理程序
1.使用汇编语言安装异常处理程序
2.使用C语言安装异常处理程序
微处理器 异常中断处理 ARM 复位异常 数据异常 相关文章:
- 用8位微处理器实现数字低通滤波器设计(05-15)
- 如何构造嵌入式Linux系统(05-23)
- 基于嵌入式Linux的便携式RFID信息采集与处理系统(07-01)
- SPARC微处理器综述(05-29)
- Motorola32位嵌入式微处理器MPC860的开发应用(06-02)
- 基于ARM和uClinux的家庭网关系统(09-14)