S3C2440中断控制器痛点详解
- 格式:docx
- 大小:384.09 KB
- 文档页数:5
MDK下S3C2440裸机中断,断断续续将耗费了我将近了一个月的时间,在贵师大图书馆里几乎翻遍了有关图书,有关这方面的介绍寥寥而过,想必出书的人也未必弄得清楚。
网上的资料也五花八门,有些说MDK自带的2440的启动代码有误(确实跟2410的启动代码不同,但经过这段时间的验证,启动代码绝对没有任何问题);有些说必须内存映射到正确的地址,才可以进入相应异常(从NORFLASH启动绝对可以进入IRQ中断);大部分在书写中断服务程序时,__irq关键字都放在函数名的前面(ADS编译器__irq关键之放置在函数名前面,但MDK必须将__irq关键字放在函数最末端);有些说必须修改2440启动代码才能进入中断(没有对启动代码做任何修改,实现了IRQ中断)……在这些一大堆乱七八糟的资料中,我差点都放弃了ARM的学习。
为了实现IRQ中断而很吃力地学习了ARM汇编,试着修改2440的启动代码;学习了内存管理,试着映射异常向量的地址;如今回过头去看,能挺过来挺欣慰的。
为实现简单IRQ中断其实很简单的,真是踏破铁鞋无觅处,得来全不费功夫。
以下是关键的几点程序说明,希望对后面学习的朋友,有些帮助。
void irq_init() //irq初始化,这个函数其实比较简单,适当看看2440PDF就应该能设定寄存器了{GPFCON = 0xaaaa;SRCPND = 0x17;INTMSK &= ~(0x17);INTPND = 0x17;EINTPEND =(1<<4);__asm{nop}EINTMASK &=~(1<<4);__asm{nop}EXTINT0 = 0x0;}//这是个很关键的函数,但其实也简单中断服务函数照着这个形式写就应该没能进入IRQ中断了。
void IRQ_Handler(void) __irq //irq中断函数{int j=0;__asm{nop};__asm{nop};j= INTOFFSET;SRCPND = SRCPND | 0x17;INTPND = INTPND | 0x17;switch(j){case 0:irq_ent0();//为中断0break;case 1:irq_ent1();//外中断1break;case 2:irq_ent2();//外中断2break;case 4:irq_ent4();//外中断4irq_init();break;}}以上两个函数式实现IQR中断的关键函数,能弄清楚上面的两个函数,IRQ中断应该就没什么大问题了。
S3C2440中断分析中断源未决寄存器(SRCPND)和中断未决寄存器(INTPND)以及外部中断未决寄存器(EINTPEND)分析2013年04月13日飞梦缘整理中断源未决寄存器SRCPND寄存器由32位构成,每一位与一个中断请求信号相关联。
当某个中断源请求中断服务时,SRCPND寄存器中相应位被置为1,即首先在源未决寄存器中做登记,因此该寄存器记录了哪个中断源的请求在等待处理。
注意SRCPND寄存器的每一位由中断源自动设置,而不管中断屏蔽寄存器中对应的位是否被屏蔽,此外,SRCPND寄存器也不受中断控制器的优先级逻辑影响。
当多个中断源提出中断请求后,SRCPND寄存器中相应位均被置为1,然后裁决逻辑基于优先级寄存器来进行处理,选中优先级最高的中断请求,对中断未决寄存器中相应的位设置为1。
注意:INTPND寄存器中只有一位可以被设置为1,如果该中断被屏蔽,SRCPND寄存器中相对应的位被设置为1,但不会导致INTPND寄存器中相应位也被设置为1,SRCPND寄存器是可读可写的,在某个特定中断源的中断服务程序中,SRCPND寄存器的相应位必须被清除,从而保证能收到同一中断源的下一次中断请求,如果从中断服务程序返回时没有清除相应的未决位,中断控制器会误以为该中断源产生了另一个中断请求,换句话说,如果SRCPND寄存器的某位始终设置为1,则被认为始终有一个与该位相对应的中断源,即一个有效的中断请求等待处理,何时进行清除相应的未决位取决于用户需求,如果想在中断服务程序中,再收到相同的中断源提出的另一个有效的中断请求,则应该首先清除相应的未决位,用户可以通过写数据“1”到SRCPND寄存器来清除相应的未决位,数据位为“1”表示该位置的未决位将被清除,而0表示该位置的未决位保持不变。
———————————————————————————————————————————————————前几天把外部中断基本搞好了,但对几个中断寄存器的具体含义和区别不是很了解。
按键与LED灯,四个中断控制四个灯LED引脚连接按键引脚连接://===================================================================== =// 开发板:GT2440// 工程名称:KEY_EINT// 功能描述:外部中断0 2 11 19 控制四个LED小灯//===================================================================== =/******************************************************************************4 个用户按键四个输入引脚:EINT0 -----( GPF0 )----INPUT---K1EINT2 -----( GPF2 )----INPUT---K2EINT11 -----( GPG3 )----INPUT---K3EINT19 -----( GPG11 )----INPUT---K4******************************************************************************/ #include "def.h"#include "2440addr.h"#include "2440lib.h"#include "string.h"#include "uart.h"#define LED1ON 0xFDE //LED1点亮值为0x7DE(低电平点亮)#define LED2ON 0xFBE#define LED3ON 0xF7E#define LED4ON 0xEFE#define LEDOFF 0xFFF //LED熄灭值为0xFFFvoid __irq EintHandler0(void);void __irq EintHandler2(void);void __irq EintHandler8_23(void);void Main(void){memcpy((unsigned char *)0x0,(unsigned char *)0x30000000,0x1000);SetSysFclk(FCLK_400M); //设置系统时钟400MChangeClockDivider(2, 1); //设置分频1:4:8CalcBusClk(); //计算总线频Uart_Select(0);Uart_Init(0,115200);Uart_Printf("KEY EINT TEST\n");Uart_Printf("Use Eint 0,2,11,19 falling edge\n");rGPBCON = (rGPBCON | 0xFFFFFFF) & 0xFFFd57FC; //GPB5--GPB8设置为output rGPBUP = rGPBUP & 0xFE1F; //使能GPB5 6 7 8上拉电阻rGPBDAT = 0x7FE; //GPB5 6 7 8位初始化为1/***********************************************************//GPF0 GPF2设置为EINT[0],EINT[2] 10 = EINT[2] 10 = EINT[0]//设置GPGCON的3,11为中断功能,分别对应EINT[11] EINT[19]*************************************************************/rGPFCON = (rGPFCON|0xFFFF)&0xFFFFFFEE;rGPGCON = (rGPGCON|0xFFFFFFFF)&0xFFBFFFBF;/*************************************************************** START:外部中断控制寄存器3位一个设置触发沿, 设置外部中断0 ,2下降沿触发外部中断控制寄存器3位设置一个触发沿, 设置外部中断11下降沿触发外部中断控制寄存器3位设置一个触发沿, 设置外部中断19下降沿触发01x = 下降沿触发*****************************************************************/ rEXTINT0 &= ~(7<<0 | 7<<8 );rEXTINT0 |= (2<<0 | 2<<8) ;rEXTINT1 &= ~(7<<12 );rEXTINT1 |= (2<<12) ;rEXTINT2 &= ~(7<<12 );rEXTINT2 |= (2<<12) ;/*************************************************************** END*****************************************************************//********************************************************//外部中断0~3保留为0 不用使能EINTPEND和EINTMASK rEINTPEND |= (1<<0|1<<2); //clear eint 4 rEINTMASK &= ~(1<<0|1<<2); //enable eint************************************************************//********************************************************//外部中断11,19需要对EINTPEND(外部中断挂起寄存器)清零并对EINTMASK(外部中断屏蔽寄存器)清零使能EINTPEND写1清零使能中断,EINTMASK清零使能中断************************************************************/ rEINTPEND |= (1<<11|1<<19);rEINTMASK &= ~(1<<11|1<<19);/***********************************************************清源挂起(SRCPND)寄存器和中断挂起(INTPND)寄存器,可以直接操作寄存器这两个函数在2440addr.h中定义*************************************************************/ ClearPending(BIT_EINT0);ClearPending(BIT_EINT2);ClearPending(BIT_EINT8_23);/***********************************************************pISR_EINT0,2中断的入口地址,定义在2440addr.inc中2440addr.inc文件内定义了用于汇编的s3c2440寄存器变量和地址*************************************************************/ pISR_EINT0 =(unsigned)EintHandler0;pISR_EINT2 =(unsigned)EintHandler2;pISR_EINT8_23 =(unsigned)EintHandler8_23;/*********************************************************** 使能或禁止中断,这是个宏定义,其原型为rINTMSK &= ~(bit)这里的操作就是取消了屏蔽,中断就开始了*************************************************************/ EnableIrq(BIT_EINT0);EnableIrq(BIT_EINT2);EnableIrq(BIT_EINT8_23);while(1);}//外部中断0,服务函数void __irq EintHandler0(void){if(rINTPND==BIT_EINT0){ClearPending(BIT_EINT0);Uart_Printf("KEY To LED1 ON \n");rGPBDAT = LED1ON;Delay(500);rGPBDAT = LEDOFF;}}//外部中断2,服务函数void __irq EintHandler2(void){if(rINTPND==BIT_EINT2){ClearPending(BIT_EINT2);Uart_Printf("KEY To LED2 ON \n");rGPBDAT = LED2ON;Delay(500);rGPBDAT = LEDOFF;}}//外部中断11,19服务函数void __irq EintHandler8_23(void){if(rINTPND==BIT_EINT8_23){ClearPending(BIT_EINT8_23);if(rEINTPEND&(1<<11)){Uart_Printf("KEY To LED3 ON \n");rGPBDAT = LED3ON;Delay(500);rGPBDAT = LEDOFF;rEINTPEND |= 1<< 11;//写1清零该位}if(rEINTPEND&(1<<19)){Uart_Printf("KEY To LED4 ON \n");rGPBDAT = LED4ON;Delay(500);rGPBDAT = LEDOFF;rEINTPEND |= 1<< 19;//写1清零该位}}}。
一 ARM9(S3C2440)的中断系统——理论知识转载自:骨Zi里德骄傲概述S3C2440A 中的中断控制器接受来自60 个中断源的请求。
提供这些中断源的是内部外设,如DMA 控制器、UART、IIC 等等。
在这些中断源中,UARTn、AC97 和EINTn 中断对于中断控制器而言是“或”关系。
当从内部外设和外部中断请求引脚收到多个中断请求时,中断控制器在仲裁步骤后请求ARM920T 内核的FIQ或IRQ。
仲裁步骤由硬件优先级逻辑决定并且写入结果到帮助用户通告是各种中断源中的哪个中断发生了的中断挂起寄存器中中断控制器操作程序状态寄存器(PSR)的F 位和I 位如果ARM920T CPU 中的PSR 的F 位被置位为1,CPU 不会接受来自中断控制器的快中断请求(FIQ)。
同样的如果PSR 的I 位被置位为1,CPU 不会接受来自中断控制器的中断请求(IRQ)。
因此,中断控制器可以通过清除PSR 的F 位和I 位为0 并且设置INTMSK 的相应位为0 来接收中断。
中断模式ARM920T 有两种中断模式的类型:FIQ 或IRQ。
所有中断源在中断请求时决定使用哪种类型。
中断挂起寄存器S3C2440A 有两个中断挂起寄存器:源挂起寄存器(SRCPND)和中断挂起寄存器(INTPND)。
这些挂起寄存器表明一个中断请求是否为挂起。
当中断源请求中断服务,SRCPND 寄存器的相应位被置位为1,并且同时在仲裁步骤后INTPND 寄存器仅有1 位自动置位为1。
如果屏蔽了中断,则SRCPND 寄存器的相应位被置位为1。
这并不会引起INTPND 寄存器的位的改变。
当INTPND 寄存器的挂起位为置位,每当I 标志或F 标志被清除为0 中断服务程序将开始。
SRCPND 和INTPND 寄存器可以被读取和写入,因此服务程序必须首先通过写1 到SRCPND寄存器的相应位来清除挂起状态并且通过相同方法来清除INTPND 寄存器中挂起状态。
ARM S3C2440中断分析1.什么是中断所谓中断,是指CPU在正常运行程序时,由于内部/外部事件或由程序预先安排的事件,引起CPU中断正在运行的程序,而转到为内部/外部事件或为预先安排的事件服务的中断程序中去,服务完毕,再返回去执行刚才被中断的程序。
2.什么是中断优先级中断优先级是指,中断源被响应和处理的优先等级。
设置优先级的目的是为了在有多个中断源同时发出中断请求时,CPU能够按照预定的顺序(如:按事件的轻重缓急处理)进行响应并处理。
3.什么是中断嵌套中断嵌套是指当CPU正在处理某个中断源即正在执行中断服务程序时,会出现优先级更高的中断源申请中断,为了使更急的中断源及时得到服务,需要暂时中断(挂起)当前正在执行的级别较低的中断服务程序,去处理更高级别的中断源,待执行完毕后再返回来执行低优先级的中断服务程序。
但中断级别低的中断源不能中断级别高的中断服务,这就是中断嵌套,并且称这种中断嵌套方式为完全嵌套方式。
4.什么是中断向量中断向量是中断服务程序的入口地址,中断向量一般是固定的,我们需要把我们写好的中断服务程序(ISR)的入口地址写道中断向量表中,这样在发生中断时,CPU就会自动跳转到中断向量表中找到它要执行的中断服务程序了。
5.什么是硬中断,什么是软中断硬中断是由外部事件引起的因此具有随机性和突发性;软中断是执行中断指令产生的,无面外部施加中断请求信号,因此中断的发生不是随机的而是由程序安排好的。
S3C2440/S3C2410中断体系结构:6.ARM体系 CPU的7种工作模式:·用户模式(usr): ARM处理器正常的程序执行状态·快速中断模式(fiq): 用于高速数据传输或通道处理·中断模式(irq):用于通用的中断处理·管理模式(svc):操作系统使用的保护模式·数据访问终止模式(abt): 当数据或指令预取时进入该模式,可用于虚拟存储及存储保护·系统模式(sys):运行具有特权操作系统任务·未定义指令中止模式(und): 当为定义的指令执行时进入该模式,可用于支持硬件协处理的软件仿真可以通过软件来进行模式切换,或者发生各类中断,异常时CPU自动进入相应的模式。
S3C2440A 中的中断控制器可以从60 个中断源接收中断请求。
这些中断源由内部的外围器件提供的,例如DMA 控制器、UART 、IIC 等。
在这些中断源中,AC97 和外部中断 UARTn 、EINTn 对于中断控制器来说是或逻辑。
当接收来自内部外设和外部中断请求引脚的多个中断请求时,在仲裁过程后中断控制器请求ARM920T 的FIR 或IRQ 中断。
1.0 程序状态寄存器(PSR )的F 位和L 位如果PSR的F 位置1 ,CPU 不能接收FIR请求,PSR的 L 位置1,CPU 不能接收IRQ请求。
如果要接受中断,则相应位清零并且INTMSK的相应位也清零。
1.1 中断模式ARM920T 有两个类型的中断模式:FIR 和IRQ 。
所有的中断源决定了哪种模式的中断请求。
1.2 中断挂起寄存器两个中断挂起寄存器SRCPND (源挂起寄存器)和INTPND(中断挂起寄存器),当中断源发起中断请求时,SRCPND 寄存器相应位被置位,当允许中断请求时,INTPND 相应位会被置位,否则INTPND 相应位不会被置位。
对寄存器清0 时,分别向他们相应位写入 1.1.3中断屏蔽寄存器:相应位置1时,中断被屏蔽,如果为0则正常服务中断。
当某位为 1 时,中断请求时,SRCPND 里相应位会被置1,但不会置INTPND 的相应位。
1.4中断源:60 个中断源(具体参见S3C2440手册)1.5. 中断次级源:15 个子中断源(具体参见S3C2440手册)1.6中断优先级生成模块和中断优先级2.0 中断特殊功能寄存器:2.1源挂起寄存器(SRCPND )寄存器由32 位数据组成,每位代表相应的一个中断,当中断发生的时候,无论是否屏蔽了这个中断,SRCPND 相应位都会自动置 1 ,表明此中断发生中断请求,如果此中断没有被屏蔽,则程序响应中断,注意:在进入中断服务程序中时要清除SRCPND 相应位。
2.2中断挂起寄存器(INTPND )寄存器由32 位数据组成,每位代表相应的中断,当INTPND 寄存器在优先级逻辑后被定位了,那么它每次只有一位能被设置为 1 ,并且产生IRQ 到CPU 。
中断详解
1、S3C2440官方手册最权威:
手册是最芯片IP开发者最直接的描述,最准确;但对英文阅读能力要求高、因详细而繁杂;适合参考和深入研究;
另外参考网上相关短文较容易入门,并短文是有套路的:基本是围绕几个较优秀的文章(优秀短文要多研读几遍理解透作者的每个心思)。
2、支持60个中断源:
S3C2440中断控制器总共支持60个中断源(内部外设和外部管脚):详细数下表中Descriptions中的中断源个数正好60;
子中断源分解如下:
注:INT_LCD也有两个中断但没有包含在子中断源寄存器中
3、一种中断源分类方法:
1、独立的外部中断源(EINT0-EINT3):4个;
2、合并的外部中断源(EINT4-EINT23):20个,合并后对应EINT4_7和EINT8_23;
注意:对应的相关寄存器在IO模块中,手册中的做法有点特殊;
3、带子中断的内部中断源:15个中断源,体现为6个bit(INT_WDT_AC97/ INT_CAM/ INT_ADC/ INT_UART2/ INT_UART1/ INT_UART0);
4、不带子中断的内部中断源:21个;
注意:INT_LCD实际对应两个中断源但是没有作为带子中断的内部中断源(如下图手册中有提到,TMD隐蔽!);
综上理解中断过程可以总结为:
4、中断优先级解析:
优秀的SOC对外设中断的处理都比较用心,基本能照顾到用户的各种场景,和LPC2292以及作者工作期间参与开发的一款SOC相比,作者经历到的三款SOC对中断的处理各有千秋(原谅不细说,因为没有必要);
可以总结为易用和特性的平衡,如果极特殊的场景下的实时性得不到满足,那就换个SOC 呗!没有必要使用一款SOC打遍天下,也不可能,而且厂家也没有强迫你呀!
言归正传:
S3C2440A支持60种中断,多个硬件可能同时产生中断请求,由于CPU只能处理一个中断,中断控制器怎么选择出一个最佳的中断,交给ARM内核进行处理呢?中断控制器采用优先级仲裁比较的方式进行选择,找出优先级最高的中断源。
中断控制器将60种中断源分成7组,如下图所示,它类似体育赛事里的比赛方式,所有参赛选手在小组赛PK,选择出小组赛最优秀选手,然后进入决赛阶段和其它小组最优先选择再PK,最后优胜者就是总冠军。
其中ARBITER0~ARBITER5为“小组赛”阶段,中断源信号在各自小组里进行优先级仲裁,选择出最高优先级中断信号,每小组选出的中断信号送到ARBITER6,也就是决赛阶段,选择出最高优先级中断信号,交给ARM内核。
中断信号在7个分组里PK时的优先级是可编程的,通过PRIORITY寄存器进行优先级设置。
如下表(只列出PRIORITY寄存器部分位):
表3-6 中断优先级控制寄存器(PRIORITY)
如果不是极特殊场景要求,我们就让这套机制留着三星自己的开发人员慢慢研究吧!
我们使用默认模式即可!
5、中断服务函数的入口:
重点说下920T内核外中断控制器对各种中断的入口函数处理,如果读者对X86保护模式程序员模型熟悉的话,2440的机制和其有异曲同工之妙!
支持定义的总入口,根据不同中断的编号偏移取得对应的中断服务函数入口。
分享下作者中断函数管理机制:
irq_handler irq_table[IRQ_HANDLE_SIZE];
即使用一个全局变量保存32个向量,根据INTOFFSET寄存器的中断号计算偏移取得入口地址;
这种机制比官网提供的各个中断有固定地址的机制有较大的灵活性,另外要注意Cache一致性的问题(如果遇到bug就是一个隐蔽性很强的bug):注册了中断服务函数就要flushcache。
6、中断模式:
FIQ模式业内认为是鸡肋,就像thumb模式这个大鸡肋一样!
总之一句话:不管、不问、任他去!不要用arm的错误惩罚自己!。