分类: 嵌入式
2011-05-22 15:03:15
ARM异常中断处理、lr寄存器、工作模式栈设计、中断服务程序ISR 中断和异常处理 中断是异常的一种。每种异常都有各自的异常处理(exception handler),handler存放在异常向量表(vector table)中,由于向量表比较小,handler里通常通过一句跳转语句跳转到实际的异常服务程序中去。 异常会引起处理器工作模式的变化,异常和工作模式的关系为: 当发生异常时,处理器会自动将: 1.当前模式的cpsr存放至异常模式的spsr 2.pc存放至异常模式的lr 3.改变cpsr的工作模式域 4.将pc设置成exception handler的地址 向量表里面存放着handler,handler里面通常是一句跳转语句: 之所以是跳转语句,是因为这几种异常handler的间隔只有4个字节的地址差,即存放一条32位指令,异常服务程序一条指令处理不完吧,所以放一条跳转语句在那里,通过跳转语句跳转到实际的异常服务程序。注意B和LDR使用的区别。 然而由于FIQ是向量表里面的最后异常,如果向量表后面没有其他内容的话,FIR的handler可以不用跳转,将FIQ服务程序直接放在地址0x0000001C的开始。 ---------------------------- 七种异常 reset:初始化内存、缓存、中断源、每种工作模式下的栈指针。 data abort:访问了无效内存地址,譬如某些内存地址上并没有挂载实际的物理器件。另外,可能访问了没有权限的内存。 IRQ:外设将IRQ引脚设为低电平时触发。 FIQ:外设将FIQ引脚设为低电平时触发,FIQ优先级比IRQ高,有更多的独立模式寄存器。 prefetch abort:取指令时造成内存错误时触发。 SWI:通过执行SWI指令触发。 undefined instruction:遇到了非法指令。 ---------------------------- 异常返回 lr寄存器保存着异常返回地址。 几种常用的处理lr的方式 ---------------------------- 中断 中断处理步骤:步骤2里面的都是处理器自动完成的,与其他异常有点不太一样的是它还会将中断掩码设为1,即屏蔽中断。 手动使能中断的方法 中断栈设计 中断时需要保护现场,即将当前工作模式下的数据压入栈。另外,在reset异常中,需要设置栈指针。为了避免栈溢出,可以每次都调用栈检查函数(见汇编篇),还可以采用内存保护机制。典型的栈分布为: B分布比A分布好的原因是,即使栈溢出了,不会损坏向量表。 譬如要设计以上的一个栈分布时,代码如下,不同工作模式下的栈指针应在reset异常下完成: 一开始设置SVC模式的栈,然后IRQ的,然后user的。通过MSR改变cpsr。 USR_Stack,Usr32md等都是宏定义,通过EQU来定义: 顺便说下DCD指令,DCD就是分配一个地址并初始化为指定的表达式,如: DCD 0x8000;就是分配一个32位的地址,其内容是0x8000 如果用上标号label,那么这个label相当于一个变量,如: label DCD 0X8000;这样引用label就是使用了0x8000这个数值。 ---------------------------- 简单的非递归的interrupt handler 中断服务程序ISR完成步骤的3和4,在步骤3中通过读取芯片内的中断状态寄存器,可以知道哪个中断源发生了中断,并调用相应的处理程序,所以ISR也像一个表一样的东西。可以用C编写。 |