如果您阅读ARM手册,您会发现,在ARM中,经常强调Exception(异常)这个概念,在ARM里,Interrupt(中断)也是一种形式的异常。ARM的Exception同其所定义的5种异常模式是密切相关的,CPU在捕获到任何一个Exception后,必定会进入某个异常模式,异常类型及捕获到该异常后CPU所进入的异常模式之间的对应关系是ARM所预先定义好的。 如果您对X86比较熟悉,您会发现,不象X86,系统定义了不同的中断,比如键盘中断,鼠标中断等等,并且系统也定义了这些中断所对应的中断向量。ARM没有定义这些,ARM只会告诉你,有外部中断产生,并切换到IRQ或FIQ模式,然后执行IRQ或FIQ所对应的中断向量。至于到底是键盘中断,还是鼠标中断,这得由操作系统提供的中断函数自己去判断,比如通过查询中断控制器的某个或某些寄存器。ARM这样做的原因是:ARM只是一个CORE,它并不定义也不去假想其外部环境,这样可以使得ARM CORE更加紧凑和简洁,同时也给SOC设计者提供了更多的灵活性和发挥空间。您一定要相信,ARM被如此广泛使用不是“盖”的,从系统开发者角度看,ARM是一种最简单、最灵活的CPU,它的优雅和简洁性就像C语言一样。呵呵,C语言是我最喜欢的语言。 好了,“臭屁”了这么多,我们言归正传。对ARM异常处理的研究务必要弄清楚以下几个方面: (1) 异常类型 (2) 异常类型及处理该异常时CPU的执行模式 (3) 异常向量地址 (4) 异常处理过程 异常类型 ARM定义了如下类型的异常(江南七怪,这样好记): (1) RESET异常:由于执行RESET指令或外部RESET信号产生的异常 (2) SWI异常:执行SWI指令产生的异常,通常用于提供系统调用接口 (3) IRQ异常:ARM的IRQ Signal被触发所产生的异常 (4) FIQ异常:ARM的FIQ Signal被触发所产生的异常 (5) Prefetch Abort异常:预取指令时产生的异常 (6) Data Abort异常:存取内存数据时产生的异常 (7) Undefined instruction异常:执行unknown指令时产生的异常 执行模式 当产生异常后,CPU会进入相应的异常模式并处理该异常: (1) RESET和SWI异常:CPU进入Supervisor模式 (2) IRQ异常:CPU进入IRQ模式 (3) FIQ异常:CPU进入FIQ模式 (4) Prefetch Abort和Data Abort异常:CPU进入Abort模式 (5) Undefined instruction异常:CPU进入Undefined模式 向量地址 ARM的异常向量地址可以处于4G物理空间的低端(0x00000000起),也可以处于高端(0xffff0000起),具体是哪种情况,根据具体的CPU及其配置而定。下面是7种异常的向量地址(挎弧内为高端情形): (1) RESET异常:0x00000000 (0xffff0000) (2) Undefined instruction异常: 0x00000004 (0xffff0004) (3) SWI异常:0x00000008 (0xffff0008) (4) Prefetch Abort异常: 0x0000000c (0xffff000c) (5) Data Abort异常: 0x00000010 (0xffff0010) (6) IRQ异常: 0x00000018 (0xffff0018) (7) FIQ异常: 0x0000001c (0xffff001c) 每个中断向量为4字节,一般的操作系统在该地址处放置一条跳转指令“LDR PC,终端处理函数地址”。另外要注意的是,在IRQ异常和Data Abort异常之间空了4个字节,这4个字节是保留的。 处理过程 处理过程包括两个部分: (1) 进入:这个过程由CPU负责 (2) 退出:这个过程由OS负责 在捕获到某个异常后,启动“进入”过程,该过程内CPU执行如下动作: (1) 将当前PC的值(或PC + 4,或PC + 8)保存到R14的某个影子寄存器中。到底选择哪个影子寄存器由该异常的执行模式而定;另外R14影子寄存器的值同异常类型相关。比如Data Abort异常,对应的影子寄存器就是Abort模式的影子寄存器R14_abt,R14_abt的值为异常产生时PC值 + 8。 (2) 将CPSR保存到CPSR的某个影子寄存器SPSR中,同样,具体选择哪个影子寄存器由该异常的执行模式而定。 (3) 执行对因的中断向量 退出过程由操作系统自己负责,只要确保退出后的PC和CPSR同进入之前是一样就可以了。有时候操作系统在处理某种特定情况的异常后会将退出后PC值变为进入前PC值 + 4(即下一条指令地址),这仅仅是一个提醒,其目的是说明退出过程是完全由软件自己决定的。
|