S3C2440的中断控制器
来源:互联网 发布:淘宝哪家化妆品是正品 编辑:程序博客网 时间:2024/06/10 07:10
S3C2440的中断控制器 S3C2440有60个中断源。这些中断源是由诸如DMA控制器、UART、IIC等片内外设提供的。 当从片内外设和外部中断请求引脚获得多个中断请求时,在仲裁程序完成之后,中断控制器向核ARM920T发出FIQ或IRQ请求。 这个仲裁程序取决于硬件优先逻辑并将仲裁结果写入中断请求寄存器(interrupt pending register,INTPND)。 中断控制器的操作 ARM提供FIQ和IRQ异常中断用于外部设备向CPU请求中断服务,一般情况下都采用IRQ中断.那么FIQ和IRQ与什么寄存器有关呢?包括PSR和INTMOD 程序状态寄存器(Program Status Register,PSR)的F位和I位,这两位是用来控制FIQ和IRQ的。 如果CPU ARM920T的PSR寄存器中F位置1,CPU就不接受来自中断控制器的快速中断请求(Fast Interrupt Request,FIQ)。类似的如果I位置1,CPU就不接受来自中断控制器的中断请求(Interrupt Resquest)。因此,我们可以通过将PSR的F位或者I位清零,同时将INTMSK相应的位清零使中断控制器可以接收到对应的中断请求 中断模式寄存器——INTMOD(INTERRUPT MODE) 中断模式寄存器有32位,每一位都对应一个中断源,INTMOD相应的位置1,ARM核就已FIQ模式响应中断;同样的,INTMOD相应的位置0,就已IRQ模式响应中断。 中断优先级 每一个仲裁机构依赖于一位的仲裁模式控制器(ARB_MODE)和两位的选择控制器信号(ARB_SEL)来对6路中断请求进行处理。具体参见S3C2440_datasheet。 中断控制器 SRCPND(SOURCE PENDING)——源中断指示寄存器 SRCPND寄存器32位中每一位对应着一个中断源,哪一位置1,则相应的中断源产生了中断请求并且等待中断服务。要注意,SRCPND寄存器每一位的置位与INTMSK寄存器中的屏蔽位是否置1无关,是由中断源自动置位的,但要清除该位,即将该位清零,是需要手动操作的。这就是说在响应中断之后,SRCPND寄存器相应的位必须被清除,也就是清零,这样才能正确的再次响应同一中断源的中断请求,如果没有这么做,那就会一直响应该中断,出现如图1所示情况,即这种不停响应中断的情况并不是用户所期望的。 这里要注意,如何清除指定位呢?方法是向指定位写1,没错是写1,这样相应的位就被清零了。 例如: rSRCPND |= 0xFFFFFFFF; 这条语句执行完之后,rSRCPND的值就是0 图1未清除制定位导致错误的中断响应 SRCPND地址 SRCPND每一位所代表的中断源 INTPND(INTERRUPT PENDING)——中断请求寄存器 中断请求寄存器每一位对应着相应的中断请求,经过优先级逻辑后,INTPND只能有一位被置1,并向CPU产生中断请求,在IRQ中断服务子程序中,读取该寄存器值来决定响应哪一个中断。 与SRCPND类似,在响应中断后,相应的位需要清零,也是向寄存器相应位写1,来清除指定位。 例如: rINTPND |= bit; 这里的bit就是相应的位,此条语句执行完之后,rINTPND值为0。如果响应中断后不清除相应的位,那么出现如图1同样的错误,即不断响应该中断。 同样我们要注意到,只有在IRQ模式下的中断发生,INTPND相应的位才置1,如果FIQ模式的中断发生了,不会对INTPND相应的位产生影响。 INTPND地址 INTPND每一位对应的中断源与SRCPND相同 INTMSK(INTERRUPT MASK)——中断屏蔽寄存器 在INTMSK寄存器中,32位一次对应着每个中断源,如果某一位被置1,CPU将不会响应该中断源的中断请求,即SRCPND被置1但INTPND不变。如果每一位都为0,那么所有中断请求都会被响应。 INTMSK地址 INTMSK每一位对应的中断源与SRCPND相同 INTOFFSET(INTERRUPT OFFSET)——中断偏移寄存器 中断偏移寄存器INTOFFSET中的值显示了INTPND寄存器中的哪一个IRQ被响应,这个位在清除SRCPND和INTPND后将自动被清除。 这里要注意,与INTPND寄存器相似,FIQ模式的中断并不影响INTOFFSET寄存器,INTOFFSET只对IRQ有效。 SUBSRCPND(SUB SOURCE PENDING)——次级中断指示寄存器 其用法与注意事项与SRCPND相同。用完清零,方法同样为写1,但要记住,先清除SUBSRCPND,再清除SRCPND,如果先清除SRCPND,CPU会以为有一次发生了中断。 SUBSRCPND地址 SUBSRCPND对应位 SUBSRCPND与SRCPND对应 INTSUBMSK(INTERRUPT SUB MASK)——次级中断屏蔽器 与INTMSK相似,哪一位置1,CPU不响应该中断请求。 INTSUBMSK地址 每一位对应地址与SUBSRCPND相同,只是除了保留位之外,其他位的初始值是1。 PRIORITY(PRIORITY REGISTER)——优先级寄存器 REQn所代表中断源如下图 EXTINTn(External Interrupt Filter Register n)——外部中断控制寄存器 外部中断控制寄存器可以控制外部中断信号的有效方式,外部中断信号有效方式可以设置为电平触发和边沿触犯,具体内容如下: EXTINT0 EXTINT1 EXTINT2 EINTPND(External Interrupt Pending Register)——外部中断判断寄存器 EINTPND用来判断外部的20个中断源(EINT[23:4]),清除该位的方法同样是向其相应位写1。其中3:0位是保留位。可以说这个寄存器是专门针对外部中断4-7,8-23来设计的。例如当外部中断8-23其中一个发生中断请求,在中断源没有被屏蔽的情况下,SRCPND和INTPND第5位(INT8_23)均被置1,当CPU响应中断进而寻找到底是哪一个外部中断发出请求时,就要在EINTPND中寻找了,而外部中断0、1、2、3就不需要这一过程,直接通过SRCPND或INTPND就能判断。 EINTMASK(External Interrupt Mask Resgister)——外部中断屏蔽寄存器 同样3:0位为保留位。 EINTFLTn(External Interrupt Filter Register n)——外部中断滤波寄存器n 为识别外部中断,EXTINTn引脚上的逻辑电平至少要保持40ns。 中断服务起始地址(_ISR_STARTADDRESS)定义在option.inc中: _ISR_STARTADDRESS EQU 0x33ffff00 中断服务向量表定义在2440addr.h中: #define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20)) #define pISR_EINT1 (*(unsigned *)(_ISR_STARTADDRESS+0x24)) #define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x28)) #define pISR_EINT3 (*(unsigned *)(_ISR_STARTADDRESS+0x2c)) #define pISR_EINT4_7 (*(unsigned *)(_ISR_STARTADDRESS+0x30)) #define pISR_EINT8_23 (*(unsigned *)(_ISR_STARTADDRESS+0x34)) #define pISR_CAM (*(unsigned *)(_ISR_STARTADDRESS+0x38)) #define pISR_BAT_FLT (*(unsigned *)(_ISR_STARTADDRESS+0x3c)) #define pISR_TICK (*(unsigned *)(_ISR_STARTADDRESS+0x40)) #define pISR_WDT_AC97 (*(unsigned *)(_ISR_STARTADDRESS+0x44)) #define pISR_TIMER0 (*(unsigned *)(_ISR_STARTADDRESS+0x48)) #define pISR_TIMER1 (*(unsigned *)(_ISR_STARTADDRESS+0x4c)) #define pISR_TIMER2 (*(unsigned *)(_ISR_STARTADDRESS+0x50)) #define pISR_TIMER3 (*(unsigned *)(_ISR_STARTADDRESS+0x54)) #define pISR_TIMER4 (*(unsigned *)(_ISR_STARTADDRESS+0x58)) #define pISR_UART2 (*(unsigned *)(_ISR_STARTADDRESS+0x5c)) #define pISR_LCD (*(unsigned *)(_ISR_STARTADDRESS+0x60)) #define pISR_DMA0 (*(unsigned *)(_ISR_STARTADDRESS+0x64)) #define pISR_DMA1 (*(unsigned *)(_ISR_STARTADDRESS+0x68)) #define pISR_DMA2 (*(unsigned *)(_ISR_STARTADDRESS+0x6c)) #define pISR_DMA3 (*(unsigned *)(_ISR_STARTADDRESS+0x70)) #define pISR_SDI (*(unsigned *)(_ISR_STARTADDRESS+0x74)) #define pISR_SPI0 (*(unsigned *)(_ISR_STARTADDRESS+0x78)) #define pISR_UART1 (*(unsigned *)(_ISR_STARTADDRESS+0x7c)) #define pISR_NFCON (*(unsigned *)(_ISR_STARTADDRESS+0x80)) #define pISR_USBD (*(unsigned *)(_ISR_STARTADDRESS+0x84)) #define pISR_USBH (*(unsigned *)(_ISR_STARTADDRESS+0x88)) #define pISR_IIC (*(unsigned *)(_ISR_STARTADDRESS+0x8c)) #define pISR_UART0 (*(unsigned *)(_ISR_STARTADDRESS+0x90)) #define pISR_SPI1 (*(unsigned *)(_ISR_STARTADDRESS+0x94)) #define pISR_RTC (*(unsigned *)(_ISR_STARTADDRESS+0x98)) #define pISR_ADC (*(unsigned *)(_ISR_STARTADDRESS+0x9c)) 举例来说: #include "def.h" #include "option.h" #include "2440addr.h" #include "2440lib.h" //外部中断0的中断服务程序,__irq是必须的,Eint0_ISR是中断服务函数名,可以随便取,看个人喜好,void加不加均可。 static void __irq Eint0_ISR(void) { ClearPending(BIT_EINT0); //这个函数用来清除SCRPND和INTPND相应位,在2440addr.h中有定义 Uart_Printf("EINT0 is occurred./n"); } static void __irq Eint2_ISR(void) { ClearPending(BIT_EINT2); Uart_Printf("EINT2 is occurred./n"); } //外部中断8-23中的某个产生了中断请求,判断是哪个,n从8到23,看你自己的程序中用到了哪个,这里只判断了两个,同样以你的程序为准。 static void __irq Eint11_8_23_ISR(void) { if(rEINTPEND & (1<<n)) { Uart_Printf("EINT11 is occurred./n"); rEINTPEND=(1<<11); //已响应该中断,清除此中断标志,写1, ClearPending(BIT_EINT8_23); } else if(rEINTPEND & (1<<n)) { Uart_Printf("EINT19 is occurred./n"); rEINTPEND=(1<<19); ClearPending(BIT_EINT8_23); } else { Uart_Printf("others ENTs are occurred/n"); rEINTPEND=0xffffff; ClearPending(BIT_EINT8_23); } } void xmain(void) { . . . . . //这里要写时钟初始化程序,初始化中断,串口,同样要将用到的GPF和GPG口的GPFCON和CPGCON寄存器相应位初始化 rEXTINT0 = (rEXTINT0 & ~(7<<8))|(2<<8); rEXTINT0 = (rEXTINT0 & ~(7<<0))|(2<<0); //EINT0、2下降沿触发,启用滤波器,注意是rEXTINT0先与7取反相与,再和2或。如果看不习惯的话话,可以这么写rEXTINT0 |= (1<<3)|(2<<0); rEXTINT1 = (rEXTINT1 & ~(7<<12))|(0x2<<12); //EINT11下降沿触发,启用滤波器 rEXTINT2 = (rEXTINT2 & ~(7<<12))|(0x2<<12); //EINT19下降沿触发,启用滤波器 pISR_EINT0=(U32)Eint0_ISR; pISR_EINT2=(U32)Eint2_ISR; pISR_EINT8_23=(U32)Eint11_8_23_ISR; //将EINT0、EINT2、EINT8_23中断服务程序起始地址定位到正确的位置,同时要将Eint0_ISR强制转化为无符号int型,U32在def.h中有定义#define U32 unsigned int rEINTPEND = 0xffffff; rSRCPND |= BIT_EINT0|BIT_EINT2|BIT_EINT8_23; //清除之前的判断标志 rINTPND |= BIT_EINT0|BIT_EINT2|BIT_EINT8_23; rEINTMASK=~( (1<<11)|(1<<19) ); //不屏蔽外部中断11与19,同时不改变其他中断屏蔽状态 rINTMSK=~(BIT_EINT0|BIT_EINT2|BIT_EINT8_23); while(1) { Uart_Printf("the main is running/n"); Delay(10000000); } } 要注意到,此程序段并不能直接运行,并不只因为那几个初始化语句没有给出,同时也因为你可能没有添加那几个必要的头文件和C文件。程序段中同样没有对中断优先级进行配置,使用的是默认中断优先级。在此仅提供一种写断服务程序的思路,供大家参考。
- S3C2440的中断控制器
- S3C2440的中断控制器
- s3c2440的中断控制器以及中断编程
- S3C2440中断控制器
- S3C2440中断控制器
- 中断控制器学习 <s3c2440>
- s3c2440中断控制器(九)
- S3C2440中断控制器一贴OK!!!
- S3C2440的SPI控制器
- S3C2440的SPI控制器
- S3c2440的存储控制器
- S3C2440的SPI控制器
- S3C2440的SPI控制器
- S3C2440的存储控制器
- S3C2440的I2S控制器
- S3C2440的中断寄存器
- S3C2440的中断寄存器
- S3C2440的中断机制
- Linux下高性能网络编程中的几个TCP/IP选项
- VC取目录(包括子目录)下所有文件名
- 网络编程; winSock;
- WM_CLOSE
- 评论:雨林木风Linux 意义和目的是什么?
- S3C2440的中断控制器
- 我的phpMyadmin乱码问题解决方案
- WM_PAINT
- 10 Papers Every Programmer Should Read (At Least Twice)
- DOM读XML文件
- S3C2440的中断控制器
- Buffer Overrun, Memory Corruptions, and Special Pool
- map insert使用
- Alienware 2010外星人电脑主题