分类: 嵌入式
2009-09-22 13:41:02
第一套:在ARM体系中,本来有SWI,FIQ,IRQ等这些中断的定义,并且已经定义了这些中断的开关控制位,就是在CPSR寄存器中,该寄存器包含了一个I位和一个F位,I位用于控制IRQ中断的开关,F用于控制FIQ的开关,但是值得注意的是CPSR的读取和修改在用户模式下是不能完成的,必须要通过SWI指令进入到特权模式下才可以进行修改。
第二套:在LPC的SFR(特殊功能寄存器)中,也提供了一套寄存器用于控制相应的中断的进行,这组控制器叫做VIC寄存器(都以VIC开头),改组寄存器包括了所有的与中断有关的设置,开启,分类等功能,仅仅是将外部中断引脚对应的部分功能分离出去,由EXT系列的寄存器来处理,因此,对这一个系列的寄存器的掌握是非常重要的!
两者间的关系:仅仅在第二套控制渠道下打开FIQ,IRQ中断是不够的,如果ARM内核没有开中断的话,整个系统就不会有中断产生,因此,常见的做法是这样:先将第二套渠道的控制内容处理好,然后通过SWI软件中断指令,将ARM处理器的模式切换为特权模式,在特权模式下,对CPSR进行“读出-修改-写回”的操作,将中断打开,然后在返回到用户模式。
LPC的中断的特殊性:FIQ的中断和普通的ARM规定是没有任何区别的,即是在产生中断时,指令跳转到0x0000001C处开始执行,这个是没有什么疑问的。但是IRQ的响应过程就不同了,先看下面一段代码,这个是写在程序的头部的部分字节:
Reset
LDR PC, ResetAddr ;// 0x00000000,Reset --->Supervisor Mode
LDR PC, Und_Addr ;// 0x00000004,Undefined Instruction --->Undefined Mode
LDR PC, SWI_Addr ;// 0x00000008,Software Interrupt --->Supervisor Mode
LDR PC, PAbort_Addr ;// 0x0000000c,Abort(Prefetch) --->Abort Mode
LDR PC, DAbort_Addr ;// 0x00000010,Abort(Data) --->Abort Mode
DCD 0xB9205F80 ;// 0x00000014,Reserved --->
LDR PC, [PC,#-0xFF0] ;// 0x00000018,IRQ --->IRQ Mode
LDR PC, FIQ_Addr ;// 0x0000001c,FIQ
指令为“LDR PC, [PC,#-0xFF0]”非常特殊,其并没有跳转到IRQ中断程序的入口处,而是进行了一个PC的运算后赋值,这里就要说明其缘由。在LPC系列中,IRQ的响应过程,程序的入口地址并不是直接写在这条语句中,而是放在一个寄存器中,该寄存器是:VICVectAddr,其地址是0xFFFFF030,现在就很明白了,在执行语句“LDR PC, [PC,#-0xFF0]”时,PC的值已经变为该语句的后面第二条语句的地址了,也就是0x00000020,而0x00000020-0xFF0时,发生借位,其结果恰好为0xFFFFF030,也就是说,通过这个简单的运算,使PC跳转到了寄存器VICVectAddr中包含的值为地址的位置上,这样就简单的完成了IRQ的跳转。
当然,IRQ中断源不止一个,其中断服务程序也不止一个,这个寄存器的值是自动更新的,另有一组寄存器VICVectAddr0~15(后面有数字)将IRQ的16个中断源的地址分别放在对应的位置上(优先级等内容有另外的寄存器来控制,这里不多说),当IRQ中断发生时,硬件自动将对应的VICVectAddr0~15中的某个对应的地址传给VICVectAddr寄存器,这个过程不用我们来编程实现。