这里分析了4个按键,还有 ENIT8 和 EINT19没有,不过原理一样的。
4个按键,分别是
EINT11 / GPG3
EINT13 / GPG5
EINT14 / GPG6
EINT15 / GPG7
外部上拉电阻。
EINT 8-23 共用一个IRQ向量。
初始化步骤
1,设置IO的功能,00 输入 01输出 02 第二功能 P292
设置的方法是
rGPGCON &= ~(3<<3*2 | 3<<5*2 | 3<<6*2 | 3<<7*2);
rGPGCON |= (2<<3*2 | 2<<5*2 | 2<<6*2 | 2<<7*2);
2,设置 EXTINT 系列寄存器,设定中断触发的类型 P301
其中这次用到的 EINT11 13-15是分布在 EXTINT1 中
触发类型
000 低电平 001 高电平 01x 下降弦 10x 上升弦 11x 边缘触发
rEXTINT1 &= ~(7<<12 | 7<<20 | 7<<24 | 7<<28);
rEXTINT1 |= (2<<12 | 2<<20 | 2<<24 | 2<<28);
3,设置 EINTPEND,P306
如果发生中断,该寄存器对应的位置一,没有中断则为0
清零的办法比较特殊,对对应位置一的话表示清零。
所以这里要这样做:
rEINTPEND |= (1<<11)|(1<<13)|(1<<14)|(1<<15);
4,设置 EINTMASK 寄存器,P305
0表示允许对应位中断,1表示禁止对应位中断,默认是禁止的
rEINTMASK &= ~((1<<11)|(1<<13)|(1<<14)|(1<<15));
5,先清一下IRQ中断
作为初始化,需要先清一下,注意,刚才 EINTPEND 是清次中断,
EXTINT 8-23 都递属于 IRQ的中断号 5,所以这里清的是主IRQ中断
ClearPending(BIT_EINT8_23);
其中 ClearPending(); 是一个内联函数,原型在 2440addr.h
由于在头文件里面不适宜放函数的实现,所以这次移植将函数体放到
2440lib.c 里面,而 2440addr.h 保留函数的定义
__inline void ClearPending(int bit)
{
register i;
rSRCPND = bit;
rINTPND = bit;
i = rINTPND;
}
函数很简单,跟前面一样,在 INTPND对应位置1就能清除该位的中断
标志了。SRCPND可以有多位置1表示多个发生中断,INTPND 表示经过
优先级裁决之后,所以同一时间只能有1位是置一的。
参考 datasheet P391
#define BIT_EINT8_23 (0x1<<5)
初始化的时候有必要将这两个东西都清一下
6,设置 IRQ Handleer执行中断任务
#define pISR_EINT8_23 (*(unsigned *)(_ISR_STARTADDRESS+0x34))
pISR_EINT8_23 = (U32)Key_ISR;
这部分的原理在中断移植的时候已经分析过了。这里可以简单的理解为
当外部中断8-23发生的时候,执行中断服务程序 Key_ISR 。
注意这个函数的原型,中断服务程序,所以不能有参数,也不能返回。
void Key_ISR(void)
7,允许中断
EnableIrq(BIT_EINT8_23);
这个宏也在刚才的 2440addr.h 里面,原型是:
#define EnableIrq(bit) rINTMSK &= ~(bit)
很简单,就是设置 INTMSK 对应的位而已。
8,分析按键中断处理函数 Key_ISR
首先
EnterCritical(&r); 看名字也大概猜出是什么东西了,玩过uCOS应该很
熟悉,进入临界区,临界区这里的意思是不允许其他中断,也就是说在
处理的过程中禁止其他的IRQ中断,也就是说IRQ中断不能嵌套,这样做
的话就方便很多了。
.global EnterCritical
EnterCritical:
mrs r1, cpsr
str r1, [r0]
orr r1, r1, #NOINT
msr cpsr_cxsf, r1
MOV_PC_LR
在 2440slib.s 中定义汇编函数,其实功能非常简单,先读出 cpsr,保存
到R0中,因为这里是根据ATPCS的汇编和C的参数传递规则,R0中应该放的
是参数 &r,也就是说,r寄存器的地址,然后将 I 位置一(1表示禁止,
0表示开启),最后返回。
那么相对应的 ExitCritical 函数也就没啥悬念了。
.global ExitCritical
ExitCritical:
ldr r1, [r0]
msr cpsr_cxsf, r1
MOV_PC_LR
将 r 寄存器的数值读出来,恢复到 cpsr中
至于 cpsr_cxsf 是什么东西,百度一下就知道了。
if(rINTPND==BIT_EINT8_23)
首先判断当前的 IRQ 中断是否 EINT 8-23,是的话再根绝 EINTPEND 分析
是哪个外部中断源。
ClearPending(BIT_EINT8_23); 每次中断都要清一下的,以便能接受下一次
中断,
if(rEINTPEND&(1<<11))
这里就很简单了,判断 EINTPEND 对应的位是否为1则能判断出是否该路
rEINTPEND |= 1<< 11;
同样了,知道是哪个中断还得清一下标志位。
Etual
2009-5-7
阅读(1404) | 评论(1) | 转发(0) |