1. 在smdkv210\src\oal\oallib\ksarm.h头文件里可以看到wince的中断定义。
设备中断的起始编号即wince预定义的设备中断ID的基值
SYSINTR_DEVICES EQU 8
一共支持64个设备中断
SYSINTR_MAX_DEVICES EQU 64
可用的设备中断ID的基值
SYSINTR_FIRMWARE EQU SYSINTR_DEVICES+16
中断总数
SYSINTR_MAXIMUM EQU SYSINTR_DEVICES+SYSINTR_MAX_DEVICES
那我们自己增加的外设的中断需要以SYSINTR_FIRMWARE为基值来定义,所有自定义的系统中断号都应该基于该值进行累加加1,这些自定义的系统中断号用于和IRQ一一对应。如下:
#define SYSINTR_SHUTPOWER_DETECT (SYSINTR_FIRMWARE+N)
SYSINTR_SHUTPOWER_DETECT为我定义的关机中的中断。
N为当前已定义的最大值(以保证此中断未使用过)。
2. 在datasheet上查要使用的中断号。
我用的是XEINT1/GPH01----->EINT1
3. 在s5pv210_sec_v1\oal\inc\intr_reg.h 中找到我们要用的虚拟中断号IRQ_EINT1。
4. 在smdkv210\src\oal\oallib\intr.c中的BSPIntrInit()函数中加入对GPH01的初始化。
//gph01 as eint1
v_pGPIOregs->GPH0.GP_CON &= ~(0xf<<4);
//gph01 as eint1
v_pGPIOregs->GPH0.GP_CON |= (0xf<<4);
//gph01 pull disable
v_pGPIOregs->GPH0.GP_PUD &=~(0x3<<2);
//gph01 low level triggered
v_pGPIOregs->EINTCON.EXT_INT0_CON &=~(0xF<<4);
//enable eint1
v_pGPIOregs->EINTMSK.EXT_INT0_MASK &=~(0x1<<1);
//Filter Enable for EXT_INT[1] ---DISBLE
v_pGPIOregs->EINTFLT.EXT_FLT0_CON._FLT_CON0 &=~(0x3<<14);
//EINT1 interrupt clear
v_pGPIOregs->EINTPND.EXT_INT0_PEND |=(0x1<<1);
然后调用OALIntrStaticTranslate(SYSINTR_SHUTPOWER_DETECT, IRQ_EINT1)来注册中断。
然后使能中断。
value = IRQ_EINT1;
OALIntrEnableIrqs(1, &value);
BSPIntrInit这个函数由s5pv210_sec_v1\oal\intr\intr.c的OALIntrInit()来调用,
OALIntrInit()最终由OEMInit()来调用。
看这个函数的注释。
// This is Windows CE OAL initialization function. It is called from kernel
// after basic initialization is made.
他由内核来调用的。
5. 修改OALIntrEnableIrqs函数,加入我们对此中断的使能。
if (PhysicalIRQ == PHYIRQ_EINT1)
{
g_pGPIOReg->EINTMSK.EXT_INT0_MASK &=~(0x1<<1); //enable eint1
OALMSG(1, (L"+OALIntrEnableIrqs(%d,)\r\n", PhysicalIRQ));
}
6. 修改OALIntrDisableIrqs函数,加入我们对此中断的关闭。
if (PhysicalIRQ == PHYIRQ_EINT1)
{
g_pGPIOReg->EINTMSK.EXT_INT0_MASK |=(0x1<<1); //enable eint1
g_pGPIOReg->EINTPND.EXT_INT0_PEND |=(0x1<<1); // Clear pending EINT1
OALMSG(1, (L"+OALIntrDisableIrqs(%d,)\r\n", PhysicalIRQ));
}
至此,对bsp修改完成,接下来写驱动。
1. 在驱动的初始化函数中创建一个事件对象
gShutpowerIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
此事件对象用于和中断绑定,来阻塞我们自己写的IST。
2. 然后将刚才创建的事件对象与中断绑定。
InterruptInitialize(SYSINTR_SHUTPOWER_DETECT,gShutpowerIntrEvent, NULL, 0)
3. 创建我们自己的IST
gShutpowerIntrThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ShutpowerIntrThread,this, 0, NULL);
4. 编写IST完成我们在中断到来时需要完成的关机动作。
IST的框架如下:
int WINAPI ShutpowerIntrThread(void) {
while(1) {
WaitForSingleObject(gShutpowerIntrEvent ,INFINITE);
关机代码
}
InterruptDone(SYSINTR_SHUTPOWER_DETECT);
}
至此一个简单的CE中断关机驱动完成。