第八章 中断控制实验
一.背景
实际上ARM的中断与51单片机的中断类似,都有类似的中断入口地址(ARM称异常向量表)。只不过 51给两个相互的中断入口之间留有足够的空间(如外部中断0的中断入口在03H处,而定时器0的中断入口在0BH处),在这段空间中可以放多条指令,这样在编写中断处理程序时非常灵活。ARM总共有7种中断(或异常)类型,它们的入口分别为00H、04H ┄┄ 1CH,入口与入口之间只够放一条指令,这条通常为“B  XX”或者“LDR   PC, ResetAddr”的跳转指令。
二.实验目的
在IRQ中断向量地址(0x18)处设置一个断点后全速运行,用按钮产生PIO中断输入信号,使产生中断,而跳转到设置的断点处。
三.实验程序和参数设置
  1> 连接器选项设置与上个实验相同
  2> 启动代码

与前几个实验相比,使能了IRQ中断后再跳到C语言的主函数。
AREA init,CODE,READONLY
CODE32
Mode_USR EQU  0x10 ;CPSR中各种处理器模式对应的控制位
USR_Stack EQU  0x00204000 ;定义RAM的最高地址,无重映射
ENTRY
                B           InitReset           ; 0x00 Reset handler
Undefvec         B           undefvec            ; 0x04 Undefined Instruction
swivec           B           swivec              ; 0x08 Software Interrupt
pabtvec          B           pabtvec             ; 0x0C Prefetch Abort
dabtvec          B           dabtvec             ; 0x10 Data Abort
rsvdvec          B           rsvdvec             ; 0x14 reserved
irqvec           B   irqvec    ; 0x18 IRQ
fiqvec     B   fiqvec        ; 0x1c FIQ
InitReset
MSR CPSR_c,#Mode_USR   ;使能FIQ,IRQ中断
LDR SP,=USR_Stack
IMPORT      main
b        main
END

  3> C语言代码

#i nclude "AT91SAM7S64.h"
#i nclude "Board.h"
unsigned int Key_Val;
unsigned int key;
int main(void)
{
*AT91C_PMC_SCER = 0x1;     //使能系统时钟寄存器的处理器时钟
*AT91C_PMC_PCER = 1 91C_ID_PIOA; //使能PIOA外围时钟
*AT91C_PIOA_PER = SW_MASK;   //使能KEY引脚的I/O口功能
*AT91C_AIC_IDCR = 1 91C_ID_PIOA; //禁止PIO外围中断功能
*AT91C_PIOA_ODR = SW_MASK;  //使能4个KEY管脚的输入功能
AT91C_BASE_AIC -> AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED;//中断模式(优先级和触发模式)
*AT91C_AIC_ICCR = 1 91C_ID_PIOA; //中断清除
*AT91C_PIOA_IDR = 0xffffffff;    //禁止所有PIO口的中断功能
*AT91C_PIOA_IER = SW3_MASK;   //使能PIO的SW3脚中断功能
*AT91C_AIC_IECR = 1 91C_ID_PIOA; //使能PIO外围中断功能
while (1);
}
四.出现的问题与解决方法
1> CPU进不了中断,即跳不到 IRQ中断向量入口地址。
原因是打开了Memory窗口,观察中断相关的寄存器。AXD软件为了在Memory窗口中刷新这些寄存器值,在程序运行过程中会访问CPU中相应寄存器值。当中断源触发后,在跳到IRQ的中断入口之前,IRQ的中断向量寄存器AIC_IVR就因为上述原因被读过,这时CPU就认为已经完成对IRQ中断的处理,因此就不再跳转到IRQ中断入口。
2> 刚一执行“ MSR CPSR_c,#Mode_USR”语句使能 IRQ中断, CPU就立即产生 IRQ中断。
原因当上一次产生IRQ中断后,没有读PIO的中断状态寄存器,将其清零。因为中断状态寄存器置1时表示自从上一次读取此寄存器,至少检测到了一次电平变化。所以当没有读该寄存器时,该状态位会一直保持着。又因为在重新装载程序进行调试时,没有复位目标CPU,所以当使能IRQ中断后,由于PIO中断状态寄存器为1的原因而产生中断。
五.总结
个人认为ARM的中断与51的中断,在本质上并没有多大的区别,出现上述的问题是由于它们在仿真、调试时的差异造成。在用普通的51仿真器进行仿真、调试时,如果我们不进行如单步、全速等执行程序运行,内部的各种寄存器、状态寄存器等是不会改变的,此时目标的CPU处于停止一样。而用ARM仿真器进行仿真、调试时,当你不进行如单步、全速等执行程序运行,内部的各种寄存器、状态寄存器还可能会改变,目标的CPU还会处处响应外部,这种情况在调试内部定时器时会更加明显。
注意:
      仔细观察可发现,原作者写的启动代码有点小问题,格式也不是很对,这是我调整后的,经供参考~~(Editor:Mr.Dragon)
 

    AREA START,CODE,READONLY
    CODE32
    
Mode_USR    EQU    0x10 ;CPSR中各种处理器模式对应的控制位    
USR_Stack EQU    0x00204000 ;定义RAM的最高地址,无重映射    
    
    ENTRY

                    B                     InitReset                     ; 0x00 Reset handler    
undefvec                    
                    B                     undefvec                        ; 0x04 Undefined Instruction
swivec                        
                    B                     swivec                            ; 0x08 Software Interrupt
pabtvec                        
                    B                     pabtvec                         ; 0x0C Prefetch Abort
dabtvec                        
                    B                     dabtvec                         ; 0x10 Data Abort
rsvdvec                        
                    B                     rsvdvec                         ; 0x14 reserved
irqvec                        
                    B             irqvec                            ; 0x18 IRQ    
fiqvec                    
                    B                     fiqvec                            ; 0x1c FIQ    
InitReset
    MSR CPSR_c,#Mode_USR     ;使能FIQ,IRQ中断    
    LDR SP,=USR_Stack    
    IMPORT     main    
    b                main    
    END