2440test中按鍵的分析
4個(gè)按鍵,分別是
EINT11 / GPG3
EINT13 / GPG5
EINT14 / GPG6
EINT15 / GPG7
外部上拉電阻。
EINT 8-23 共用一個(gè)IRQ向量。
初始化步驟
1,設(shè)置IO的功能,00 輸入 01輸出 02 第二功能 P292
設(shè)置的方法是
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,設(shè)置 EXTINT 系列寄存器,設(shè)定中斷觸發(fā)的類型 P301
其中這次用到的 EINT11 13-15是分布在 EXTINT1 中
觸發(fā)類型
000 低電平 001 高電平 01x 下降弦 10x 上升弦 11x 邊緣觸發(fā)
rEXTINT1 &= ~(7<<12 | 7<<20 | 7<<24 | 7<<28);
rEXTINT1 |= (2<<12 | 2<<20 | 2<<24 | 2<<28);
3,設(shè)置 EINTPEND,P306
如果發(fā)生中斷,該寄存器對(duì)應(yīng)的位置一,沒(méi)有中斷則為0
清零的辦法比較特殊,對(duì)對(duì)應(yīng)位置一的話表示清零。
所以這里要這樣做:
rEINTPEND |= (1<<11)|(1<<13)|(1<<14)|(1<<15);
4,設(shè)置 EINTMASK 寄存器,P305
0表示允許對(duì)應(yīng)位中斷,1表示禁止對(duì)應(yīng)位中斷,默認(rèn)是禁止的
rEINTMASK &= ~((1<<11)|(1<<13)|(1<<14)|(1<<15));
5,先清一下IRQ中斷
作為初始化,需要先清一下,注意,剛才 EINTPEND 是清次中斷,
EXTINT 8-23 都遞屬于 IRQ的中斷號(hào) 5,所以這里清的是主IRQ中斷
ClearPending(BIT_EINT8_23);
其中 ClearPending(); 是一個(gè)內(nèi)聯(lián)函數(shù),原型在 2440addr.h
由于在頭文件里面不適宜放函數(shù)的實(shí)現(xiàn),所以這次移植將函數(shù)體放到
2440lib.c 里面,而 2440addr.h 保留函數(shù)的定義
__inline void ClearPending(int bit)
{
register i;
rSRCPND = bit;
rINTPND = bit;
i = rINTPND;
}
函數(shù)很簡(jiǎn)單,跟前面一樣,在 INTPND對(duì)應(yīng)位置1就能清除該位的中斷
標(biāo)志了。SRCPND可以有多位置1表示多個(gè)發(fā)生中斷,INTPND 表示經(jīng)過(guò)
優(yōu)先級(jí)裁決之后,所以同一時(shí)間只能有1位是置一的。
參考 datasheet P391
#define BIT_EINT8_23(0x1<<5)
初始化的時(shí)候有必要將這兩個(gè)東西都清一下
6,設(shè)置 IRQ Handleer執(zhí)行中斷任務(wù)
#define pISR_EINT8_23(*(unsigned *)(_ISR_STARTADDRESS+0x34))
pISR_EINT8_23 = (U32)Key_ISR;
這部分的原理在中斷移植的時(shí)候已經(jīng)分析過(guò)了。這里可以簡(jiǎn)單的理解為
當(dāng)外部中斷8-23發(fā)生的時(shí)候,執(zhí)行中斷服務(wù)程序 Key_ISR 。
注意這個(gè)函數(shù)的原型,中斷服務(wù)程序,所以不能有參數(shù),也不能返回。
void Key_ISR(void)
7,允許中斷
EnableIrq(BIT_EINT8_23);
這個(gè)宏也在剛才的 2440addr.h 里面,原型是:
#defineEnableIrq(bit)rINTMSK &= ~(bit)
很簡(jiǎn)單,就是設(shè)置 INTMSK 對(duì)應(yīng)的位而已。
8,分析按鍵中斷處理函數(shù) Key_ISR
首先
EnterCritical(&r); 看名字也大概猜出是什么東西了,玩過(guò)uCOS應(yīng)該很
熟悉,進(jìn)入臨界區(qū),臨界區(qū)這里的意思是不允許其他中斷,也就是說(shuō)在
處理的過(guò)程中禁止其他的IRQ中斷,也就是說(shuō)IRQ中斷不能嵌套,這樣做
的話就方便很多了。
.globalEnterCritical
EnterCritical:
mrsr1, cpsr
strr1, [r0]
orrr1, r1, #NOINT
msrcpsr_cxsf, r1
MOV_PC_LR
在 2440slib.s 中定義匯編函數(shù),其實(shí)功能非常簡(jiǎn)單,先讀出 cpsr,保存
到R0中,因?yàn)檫@里是根據(jù)ATPCS的匯編和C的參數(shù)傳遞規(guī)則,R0中應(yīng)該放的
是參數(shù) &r,也就是說(shuō),r寄存器的地址,然后將 I 位置一(1表示禁止,
0表示開(kāi)啟),最后返回。
那么相對(duì)應(yīng)的 ExitCritical 函數(shù)也就沒(méi)啥懸念了。
.globalExitCritical
ExitCritical:
ldrr1, [r0]
msrcpsr_cxsf, r1
MOV_PC_LR
將 r 寄存器的數(shù)值讀出來(lái),恢復(fù)到 cpsr中
至于 cpsr_cxsf 是什么東西,百度一下就知道了。
if(rINTPND==BIT_EINT8_23)
首先判斷當(dāng)前的 IRQ 中斷是否 EINT 8-23,是的話再根絕 EINTPEND 分析
是哪個(gè)外部中斷源。
ClearPending(BIT_EINT8_23); 每次中斷都要清一下的,以便能接受下一次
中斷,
if(rEINTPEND&(1<<11))
這里就很簡(jiǎn)單了,判斷 EINTPEND 對(duì)應(yīng)的位是否為1則能判斷出是否該路
rEINTPEND |= 1<< 11;
同樣了,知道是哪個(gè)中斷還得清一下標(biāo)志位。
評(píng)論