您的位置 首页 产品

S3C2440外部中止详解

要想正确地执行2440的外部中断,一般需要完成两个部分内容:中断初始化和中断处理函数。在具体执行中断之前,要初始化好要用的中断…

要想正确地履行2440的外部中止,一般需求完结两个部分内容:中止初始化和中止处理函数。

在详细履行中止之前,要初始化好要用的中止。2440的外部中止引脚EINT与通用IO引脚F和G复用,要想运用中止功用,就要把相应的引脚装备成中止形式,如咱们想把端口F0设置成外部中止,而其他引脚功用不变,则GPFCON=(GPFCON & ~0x3) | 0x2。装备完引脚后,还需求装备详细的中止功用。咱们要翻开某一中止的屏蔽,这样才干呼应该中止,相对应的寄存器为INTMSK;还要设置外部中止的触发方法,如低电平、高电平、上升沿、下降沿等,相对应的寄存器为EXTINTn。别的由于EINT4到EINT7共用一个中止向量,EINT8到EINT23也共用一个中止向量,而INTMSK只担任总的中止向量的屏蔽,要详细翻开某一详细的中止屏蔽,还需求设置EINTMASK。上面介绍的是最基本的初始化,当然还有一些其他的装备,如当需求用到快速中止时,要运用INTMOD,当需求装备中止优先级时,要运用PRIORITY等。
中止处理函数担任履行详细的中止指令,除此以外还需求把SRCPND和INTPND中的相应的位清零(通过置1来清零),由于当中止产生时,2440会主动把这两个寄存器中相对应的方位1,以表明某一中止产生,假如不在中止处理函数内把它们清零,体系会一向履行该中止函数。别的仍是由于前面介绍过的,有一些中止是共用一个中止向量的,而一个中止向量只能有一个中止履行函数,因而详细是哪个外部中止,还需求EINTPEND来判别,并相同还要通过置1的方法把相应的位清零。一般来说,运用__irq这个关键词来界说中止处理函数,这样体系会为咱们主动保存一些必要的变量,并能够在中止处理函数履行完后正确地回来。还需求留意的是,中止处理函数不能有回来值,也不能传递任何参数。
为了把这个中止处理函数与在2440发动文件中界说的中止向量表相对应上,需求先界说中止进口地址变量,该中止进口地址有必要与中止向量表中的地址共同,然后把该中止处理函数的首地址传递给该变量,即中止进口地址。
下面便是一个外部中止的实例。开发板上一共有四个按键,别离连到了EINT0,EINT1,EINT2和EINT4,咱们让这四个按键别离操控连接在B5~B8引脚上的四个LED:按一下键则LED亮,再按一下则灭:
#define _ISR_STARTADDRESS 0x33ffff00
#define U32 unsigned int
#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_EINT1 (*(unsigned *)(_ISR_STARTADDRESS+0x24))
#define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x28))
#define pISR_EINT4_7 (*(unsigned *)(_ISR_STARTADDRESS+0x30))
#define rSRCPND (*(volatile unsigned *)0x4a000000) //Interrupt request status
#define rINTMSK (*(volatile unsigned *)0x4a000008) //Interrupt mask control
#define rINTPND (*(volatile unsigned *)0x4a000010) //Interrupt request status
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define rGPFCON (*(volatile unsigned *)0x56000050) //Port F control
#define rEXTINT0 (*(volatile unsigned *)0x56000088) //External interrupt control register 0
#define rEINTMASK (*(volatile unsigned *)0x560000a4) //External interrupt mask
#define rEINTPEND (*(volatile unsigned *)0x560000a8) //External interrupt pending
static void __irq Key1_ISR(void) //EINT1
{
int led;
rSRCPND = rSRCPND | (0x1<<1);
rINTPND = rINTPND | (0x1<<1);
led = rGPBDAT & (0x1<<5);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<5);
else
rGPBDAT = rGPBDAT & ~(0x1<<5);
}
static void __irq Key2_ISR(void) //EINT4
{
int led;
rSRCPND = rSRCPND | (0x1<<4);
rINTPND = rINTPND | (0x1<<4);
if(rEINTPEND&(1<<4))
{
rEINTPEND = rEINTPEND | (0x1<<4);
led = rGPBDAT & (0x1<<6);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<6);
else
rGPBDAT = rGPBDAT & ~(0x1<<6);
}
}
static void __irq Key3_ISR(void) //EINT2
{
int led;
rSRCPND = rSRCPND | (0x1<<2);
rINTPND = rINTPND | (0x1<<2);
led = rGPBDAT & (0x1<<7);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<7);
else
rGPBDAT = rGPBDAT & ~(0x1<<7);
}
void __irq Key4_ISR(void) //EINT0
{
int led;
rSRCPND = rSRCPND | 0x1;
rINTPND = rINTPND | 0x1;
led = rGPBDAT & (0x1<<8);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<8);
else
rGPBDAT = rGPBDAT & ~(0x1<<8);
}
void Main(void)
{
int light;
rGPBCON = 0x015550;
rGPBUP = 0x7ff;
rGPFCON = 0xaaaa;
rSRCPND = 0x17;
rINTMSK = ~0x17;
rINTPND =0x17;
rEINTPEND = (1<<4);
rEINTMASK = ~(1<<4);
rEXTINT0 = 0x20222;
light = 0x0;
rGPBDAT = ~light;
pISR_EINT0 = (U32)Key4_ISR;
pISR_EINT1 = (U32)Key1_ISR;
pISR_EINT2 = (U32)Key3_ISR;
pISR_EINT4_7 = (U32)Key2_ISR;
while(1)
;
}
/******************************************************************************************************************************************************************************************************/

1.中止分两大类:内部中止和外部中止。

2.外部中止。24个外部中止占用GPF0-GPF7(EINT0-EINT7),GPG0-GPG15(EINT8-EINT23)。用这些脚做中止输入,则有必要装备引脚为中止,而且不要上拉。详细参阅datesheet数据手册。

寄存器:EXTINT0-EXTINT2:三个寄存器设定EINT0-EINT23的触发方法。

EINTFLT0-EINTFLT3:操控滤波时钟和滤波宽度。

EINTPEND:这个是中止挂起寄存器,铲除时要写1,后边还有几个是写1铲除。当一个外部中止(EINT4-EINT23)产生后,那么相应的位会被置1。为什么没有EINT0-EINT3,呵呵,看看SRCPND就知道了,里边没有EINT4-EINT23的位子(SRCPND第[3]位为EINT4-7组,第[4]位为EINT8-23组),所以有了EINTPENDx用以细化弥补SRCPND。

EINTMASK:这个简略,是屏蔽中止用的,也便是说位为1时,此次中止无效。

3.内部中止。内部中止有8个寄存器,下面逐个来看。

寄存器:SUBSRCPND:当一个中止产生后,那么相应的位会被置1,表明一个中止产生了。

INTSUBMSK:与上一个是一伙的,中止屏蔽寄存器,详细屏蔽什么,自己看手册去吧。

INTMOD:中止的方法。一个中止可所以一般中止,也可所以快中止,在这里设置,但只能有一个快中止。

PRIORITY:优先级寄存器,不说了。

SRCPND:当一个中止产生后,那么相应的位会被置1,表明一个或一类中止产生了。

INTMSK:中止屏蔽寄存器。

INTPND:中止产生后,SRCPND中会有方位1,或许好几个(由于一起或许产生几个中止),这些中止会由优先级裁定器选出一个最急迫的,然后把INTPND中相应方位1,所以同一时间只要一位是1。也便是说前面的寄存器置1是表明产生了,只要INTPND置1,CPU才会处理。

INTOFFSET:用来表明INTPND中哪一方位1了,好让你查询,一般中止跳转时查询用。铲除INTPND、SRCPND时主动铲除。

4.各寄存器联系:

下面看图阐明:

5.中止过程。

a假如是不带子中止的内部中止:产生后SRCPND相应方位1,假如没有被INTMSK屏蔽,那么等候进一步处理。

b假如是带子中止的内部中止:产生后SUBSRCPND相应方位1,假如没有被INTSUBMSK屏蔽,那么SRCPND相应方位1,等候进一步处理,几个SUBSRCPND或许对应同一个SRCPND,对应表如下:

SRCPND SUBSRCPND
INT_UART0 INT_RXD0,INT_TXD0,INT_ERR0
INT_UART1 INT_RXD1,INT_TXD1,INT_ERR1
INT_UART2 INT_RXD2,INT_TXD2,INT_ERR2
INT_ADC INT_ADC_S, INT_TC
INT_CAM INT_CAM_C, INT_CAM_P
INT_WDT_AC97 INT_WDT, INT_AC97

c假如是外部中止:EINT0-EINT3产生后SRCPND相应方位1,假如没有被INTMSK屏蔽,那么等候进一步处理。EINT4-EINT23产生后EINTPEND相应方位1,假如没有被EINTMASK屏蔽,那么SRCPND相应位EINT4-7或EINT8-23置1,假如没有被INTMSK屏蔽,等候进一步处理。几个EINTPEND对应同一个SRCPND,对应表如下:

SRCPND EINTPEND

EINT0 EINT0

EINT1 EINT1

EINT2 EINT2

EINT3 EINT3

EINT4-7 EINT4 EINT5EINT6EINT7

EINT8-23 EINT8 EINT9EINT10EINT11……EINT23

三种中止都等候进一步处理了。接下来从SRCPND往下看,看INTMSK。假如中止被屏蔽了,就不用说了。假如没有被屏蔽,那么会进一步到INTMOD。假如是快中止,那么直接出来,进入FIQ(即CPU进入快中止形式处理)。假如是一般中止,那么SRCPND能够有多位为置1(FIQ只能有一个),这时就会通过PRIORITY选出一个优先级高的,然后把依据选出的中止把INTPND相应方位1(留意:只能选出一个),进入IRQ,让CPU处理。

6.中止的敞开。

a.假如是不带子中止的内部中止,只需设置INTMSK,让它不屏蔽中止就能够了。

b假如是带子中止的内部中止,需设置INTSUBMSK和INTMSK,让它们不屏蔽中止就能够了。

c假如是外部中止,关于EINT8-23需求设置EINTMASK和INTMSK。关于EINT0-EINT3只需设置INTMSK。

7.中止的铲除。

a.假如是不带子中止的内部中止,只需铲除SRCPND,留意铲除需方位1。

b假如是带子中止的内部中止,需铲除SRCPND和SUBSRCPND,留意先铲除SUBSRCPND,再铲除SRCPND。由于,假如你先铲除SRCPND的话,然后在铲除SUBSRCPND的过程中,SRCPND会认为又有中止产生,又会置1。也便是说一次中止会呼应两次。所以有必要先掐断源头。

c假如是外部中止,关于EINT8-23需求铲除EINTPEND和SRCPND(相同留意次序)。关于EINT0-EINT3只需铲除SRCPND。

本文详细分析了S3C2440的中止寄存器,对arm初学者有必定的协助。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/chanpin/254938.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部