1、第五章 中断中断是指计算机在执行程序的过程中,当出现异常情况或特殊请求时,计算机停止现行程序的运行,转向对这些异常情况或特殊请求的处理,处理结束后再返回现行程序的间断处,继续执行原程序。中断是单片机或ARM实时地处理内部或外部事件的一种机制。换言之,中断可以作为ARM外围设备与CPU之间的一种联系或通信方式。S3C2410A中有56个中断源,这些中断源分别为:表 5.1中断源具体描述INT_ADCADC EOC中断和Touch中断,INT_ADC/INT_TCINT_RTCRTC报警中断INT_SPI1SPI1中断INT_UART0通用异步收发器0的ERR(错误)中断、RXD和TXD中断INT
2、_UART1通用异步收发器1的ERR(错误)中断、RXD和TXD中断INT_UART2通用异步收发器2的ERR(错误)中断、RXD和TXD中断INT_USBHUSB主机中断INT_USBDUSB设备中断INT_SPI0SPI0中断INT_SDISDI中断INT_DMADMA03中断INT_LCDLCD中断INT_IICI2C中断INT_TIMER定时器04中断INT_WDT看门狗定时器中断INT_TICKRTC实时时钟节拍中断nBATT_FLT电池错误中断EINT外部中断023假如UART0的接收缓存收到了来自外部的数据,那么设备UART0要通知CPU已经收到数据,请示CPU进行下一步工作。那
3、么UART0要通过什么方式告知CPU收到数据了呢?设想一下,UART是通用异步收发器的英文缩写,一般在ARM芯片与外部进行数据传输的时候并不是一直不断地进行数据交换,而是断断续续地进行数据通信,那么CPU不可能一直监视着UART设备。在UART设备不进行数据收发时,CPU可以去进行别的程序处理。一旦UART设备需要和外部进行数据传输的时候,比如收到了来自外部设备的一帧数据,此时CPU还在进行着别的程序处理,那么UART设备就要告知CPU收到数据了,需要对数据进行处理,UART会通过中断的方式通知CPU,打断CPU正在进行的工作,让CPU对UART收到的数据进行处理。此时CPU收到UART的中断
4、通知,那么他会停下正在处理的工作,保存当前的数据,转向UART的数据处理程序(UART中断服务程序)对UART收到的数据进行处理,处理完毕后如果没有其他设备的中断请求,CPU会跳转回UART中断之前的程序,调出中断时保存的数据继续运行中断之前的程序。S3C2410A是以ARM920T为内核的ARM,ARM920T内核有两种中断模式:FIQ和IRQ。IRQ全称为Interrupt Request,即是“中断请求”的意思。FIQ全称为Fast Interrupt Request,即是“快速中断请求”的意思。FIQ模式是特权模式中的一种,同时也属于异常模式一类。用于高速数据传输或通道处理,在触发快速
5、中断请求(FIQ)时进入。一般情况下,我们只用到IRQ而很少用到FIQ。5.1 S3C2410A中和中断相关的寄存器1. SOURCE PENDIND REGISTER(SRCPND)这个寄存器名称为中断源挂起寄存器。该寄存器是32位寄存器,每一位都代表着相应的中断源是否发出中断请求。当其中某一位值为“1”时,表明其相应的中断源发出了中断请求,否则这个中断源没有发出中断请求。比如,SRCPND10=1,则说明定时器0请求中断。2. SUB SOURCE PENDING REGISTER(SUBSRCPND)这个寄存器与SRCPND寄存器功能相同,只不过这个寄存器有效bit为11位。这个寄存器中
6、主要是更细地列出了UART中具体的中断类型。3. INTERRUPT PENDING REGISTER(INTPND)这个寄存器名称为中断挂起寄存器。该寄存器为32位寄存器,每一位都代表着相应的中断源是否发出中断请求。当其中某一位值为“1”时,表明其相应的中断源发出了中断请求,否则这个中断源没有发出中断请求。这个寄存器的每一位功能描述和寄存器SRCPND是相同的。4. INTERRUPT MASK REGISTER(INTMSK)这个寄存器名称为中断屏蔽寄存器。该寄存器为32位寄存器,每一位都代表着相应的中断源是否可用。当其中某一位值为“1”时,表明其相应的中断源被屏蔽掉了,反之相应中断源是可
7、用的。下面对上述三个寄存器进行说明。S3C2410A中有两个中断挂起寄存器分别为SRCPND和INTPND。这些寄存器指明了一个中断是否要被进行处理。当中断源请求中断服务时,SRCPND的相应bit位会被置位,同时INTPND中仅有与SRCPND相对应的一位数值在判决程序执行后被置位。如果中断被INTMSK寄存器所屏蔽,那么当有中断请求时,SRCPND的相应bit位会置位,而INTPND中与SRCPND相对应的bit位不会发生变化。SRCPND和INTPND都是可读写的,在中断服务程序中为了清除相应的中断请求,需要向SRCPND的相应bit位和INTPND的相应bit位写“1”,这样就清除了中
8、断服务请求。(注:此处是向SRCPND和INTPND中写“1”进行清除操作,而不是写“0”)另外,在中断服务程序中,我们可以读寄存器INTPND,看看其中哪一位被置位了(这个寄存器中的值同时只能有1bit被置位),就可以知道是哪个设备向CPU请求了中断。5. INTERRUPT SUB MASK REGISTER(INTSUBMSK)这个寄存器功能与INTMSK相同,这个寄存器主要用来屏蔽UART的具体中断类型。6. INTERRUPT MODE REGISTER(INTMOD)这个寄存器名称为中断模式寄存器。其相应bit为“1”时,按FIQ模式处理,否则按IRQ模式处理。注意,同时只能有一个
9、中断源按照FIQ模式处理,即INTMOD寄存器中只能有一个bit为“1”。7. INTERRUPT OFFSET REGISTER (INTOFFSET)这个寄存器名称为中断偏移量寄存器。这个寄存器说明了IRQ模式下,哪个中断请求正在INTPND寄存器当中。在清零SRCPND和INTPND之后,这个寄存器自动清零。8. PRIORITY REGISTER (PRIORITY)此寄存器为中断优先级寄存器。在此处需要讲述S3C2410A的中断优先级逻辑。图5.1.1为S3C2410A的中断优先级产生模块。32个中断请求的优先级逻辑由7级判决器组成,其中有6个fisrt-level判决器和1个sec
10、ond-level判决器。每个中断判决器基于1个bit模式控制(ARB_MODE)和2个bit选择控制信号(ARB_SEL)来处理中断请求。如图5.1.1所示,从05六个判决器中生成REQ0REQ6六个中断请求,再由判决器6生成最终的中断请求。优先级规则为:如果ARB_SEL为00,那么优先级顺序由高到低为REQ0、REQ1、REQ2、REQ3、REQ4、REQ5。如果ARB_SEL为01,那么优先级顺序由高到低为REQ0、REQ2、REQ3、REQ4、REQ1、REQ5。如果ARB_SEL为10,那么优先级顺序由高到低为REQ0、REQ3、REQ4、REQ1、REQ2、REQ5。如果ARB_
11、SEL为11,那么优先级顺序由高到低为REQ0、REQ4、REQ1、REQ2、REQ3、REQ5。注:判决器中REQ0永远是优先级最高的,REQ5永远是优先级最低的,改变ARB_SEL的值可以重新排列REQ1REQ5的优先级次序。如果ARB_MODE被设置为“0”,那么ARB_SEL的值就不会自动改变,则判决器会工作在固定优先级的模式(我们可以手动改变优先级)。如果ARB_MODE被设置为“1”,那么ARB_SEL就处于滚动模式。例如:如果REQ1输出请求,ARB_SEL就会自动变为“01”,然后REQ1就会被放到最低优先级REQ5的前面一级。ARB_SEL的变化规律为: 如果REQ0和REQ
12、5输出请求,则ARB_SEL保持不变; 如果REQ1输出请求,则ARB_SEL变为01; 如果REQ2输出请求,则ARB_SEL变为10; 如果REQ3输出请求,则ARB_SEL变为11; 如果REQ4输出请求,则ARB_SEL变为00;图5.15.2 程序分析此程序用定时器中断来控制两个LED闪烁。定时器的内容下一章再具体讲述。1. 中断初始化程序void Isr_Init(void) pISR_UNDEF = (unsigned)HaltUndef;/调试信息定义 pISR_SWI = (unsigned)HaltSwi; /调试信息定义 pISR_PABORT = (unsigned)H
13、altPabort; /调试信息定义 pISR_DABORT = (unsigned)HaltDabort; /调试信息定义 rINTMOD = 0x0; rINTMSK = BIT_ALLMSK; rINTSUBMSK = BIT_SUB_ALLMSK;在程序中,调试信息定义不用去理睬,实际程序中没有这些调试信息程序一样能够正常工作。有关中断的寄存器定义全部都在文件2410ADDR.H中,读者可以自行查阅。rINTMOD = 0x0;将INTMOD寄存器的所有值都设置为“0”,即全部中断都是IRQ中断。rINTMSK = BIT_ALLMSK;将INTMSK寄存器的所有值都设置为“1”,即屏
14、蔽所有中断。BIT_ALLMSK 在文件2410ADDR.S中有定义,BIT_ALLMSK= 0xffffffff。rINTSUBMSK = BIT_SUB_ALLMSK;将INTSUBMSK寄存器的所有值都设置为“1”,即屏蔽所有子中断。BIT_SUB_ALLMSK在2410ADDR.H中进行了定义,#define BIT_SUB_ALLMSK (0x7ff),即BIT_SUB_ALLMSK=0x7ff。2. 定时器中断初始化void Timer1INT_Init(void) if (rINTPND & BIT_TIMER1)/判断是否有定时器1的中断请求 rSRCPND |= BIT_TI
15、MER1; pISR_TIMER1 = (int)Timer1_ISR; rINTMSK &= (BIT_TIMER1); /开中断; BIT_TIMER1在文件2410ADDR.S中有定义,BIT_TIMER1= 0x111,rINTPND & BIT_TIMER1就是判断寄存器INTPND11是否为“1”,也就是说程序要判断定时器1是否发出中断请求。如果有中断请求,那么rSRCPND |= BIT_TIMER1;即SRCPND11=1。pISR_TIMER1在文件2410ADDR.S中有定义,它是定时器1中断服务函数的入口,Timer1_ISR是中断服务函数,pISR_TIMER1 = (
16、int)Timer1_ISR;就是将中断服务函数的地址赋给定时器1中断服务函数的入口。rINTMSK &= (BIT_TIMER1);即INTPND11=0,开启定时器1中断。3. 中断服务函数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;/清
17、除中断挂起条件void _irq Timer1_ISR( void )为中断服务函数的固定写法,Timer1_ISR为中断函数名,这个函数名可以根据不同的中断加以修改。一旦定时器1中断,那么程序就会自动跳转到这里执行中断处理函数,执行完毕后返回程序中断前的位置继续执行后面的程序。在这个程序中if else结构里的程序就是让两个LED闪烁。在中断服务程序中需要特别注意的是最后两句程序,rSRCPND |= BIT_TIMER1;是清除源挂起寄存器中定时器1的中断请求;rINTPND |= BIT_TIMER1;是清除中断挂起寄存器中定时器1的中断请求。只有执行了这两句后,定时器1中断条件才被清除,否则CPU会一直认为定时器1有可用的中断请求。以上三个函数就是中断处理所必须的基本函数。