ARM的中断原理
中断偏移寄存器,只是IRQ中断源 0x0
SUBSRCPND0x4A000018子中断源挂起寄存器,指示中断请求的状态0x0
0=该中断没有请求 1=该中断源发出中断请求
INTSUBMSK0x4A00 001C定义哪个中断源屏蔽 0=中断服务允许,1=中断服务屏 0x7FF
所有来自中断源的中断请求首先被登记到中断源挂起寄存器中。在中断模式寄存器,中断请求分成两类:FIQ和IRQ。多个IRQ中断的仲裁过程在优先级寄存器进行。
中断源挂起寄存器可以看作各种中断有无请求的状态标志寄存器。相应位置1,说明存在该中断请求;相应位为0,说明该中断请求产生。
中断模式寄存器主要用于配置该中断是IRQ型中断,还是FIQ型中断。
3.中断编程实例
介绍一个通过定时器1中断控制CPU板上的LED1和LED2实现轮流闪烁的实例,需要完成的主要工作如下:
(1)对定时器1初始化,并设定定时器的中断时间为1s,据代码参见Timer1_init()函数。
void Timer1_init(void){
rGPCON=rGPGCON&0xfff0ffff|0x00050000; //配置GPG口为输出口
rGPGDAT=rGPGDAT|0x300;
rTCFG0=255;
rTCFG1=0
rTCNTB1=48828; //在pclk=50MHz下,1s的记数值rTCNTB1=50000000/4/256=48828
rTCMPB1=0x00;
rTCON=(1
rTCON=(1
}
(2)为了使CPU响应中断,在中断服务子程序执行之前,必须打开ARM920T的CPSR中的I位,以及相应的中断屏蔽寄存器中的位。打开相应的中断屏蔽寄存器的位,是在Timer1INT_Init()函数中实现,具体代码如下。
void Timer1INT_Init(void){
//定时器接口使能
if((rINTPND&BIT_TIMER1)){
rSRCPND|=BIT_TIMER1;
}
pISR_TIMER1=(int)Timer1_ISR;
//写入定时器1中断服务子程序的入口地址
rINTMSK&=~(BIT_TIMER1);
//开中断
}
(3)等待定时器中断,通过一个死循环如“while(1);”实现等待过程。
(4)根据设置的定时时间,产生定时器中断。中断发生后,首先进行现场保护,然后转入中断的入口代码处执行。该部分代码通常使用汇编语言编写。在执行中断服务程序之前,要确保HandleIRQ地址处保存中断分发程序IsrIRQ的入口地址,代码如下:
ldrr0,=HandleIRQ
ldrr1,=IsrIRQ
strr1,[r0]
接下来将执行IsrIRQ中断分发程序,具体代码如下。
IsrIRQ
subsp,sp,#4 ;为保存PC预留堆栈空间
stmfdsp!,{r8-r9}
ldrr9,=INTOFFSET
ldrr9,[r9] ;加载INTOFFSET寄存器值到r9
ldrr8,=HandleEINT0;加载中断向量表的基地址到r8
addr8,r8,r9,lsl#2;获得中断向量
ldrr8,[r8] ;加载中断服务程序的入口地址到r8
strr8,[sp,#8] ;保存sp,将其作为新的pc值
ldmfd sp!,{r8-r9,pc};跳转到新的pc处执行,即跳转到中断服务子程序执行
(5)执行中断服务子程序,该子程序实现将LED1和LED2灯熄灭或点亮。从现象中看到LED1和LED2灯闪烁一次,就说明定时器发生了一次中断。具体实现见函数Timer1_ISR().
int flag;
void_ _irq Timer1_ISR(void){
if(flag==0){
rGPGDAT=rGPGDAT&0xeff|0x200;
flag=1;
}else{
rGPGDAT=rGPGDAT&0xdff|0x100;
flag=0;
}
rSRCPND|=BIT_TIMER1;
rINTPND|=BIT_TIMER1;
}
(6)从中断中返回,恢复现场,跳转到被中断的主程序继续执行,等待下一次中断的到来。
ARM中断原 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
