在 Prima EVB 板上,最好是用 GPIO0_8 作为练习对象,原因有二:一是它本身是个按钮,便于触发;二是是按钮的三个按键中有两个是有中断的,如果再用,会产生冲突。
经验心得 1:不必一定要把 IO 口设置成输入状态,才能 ENABLE IO 口中断,故 PIO_OUTPUT_DISABLE 加与不加效果一样;
2:ENABLE IO 口中断,此时 IO 口默认为输入状态。
3:InterruptDone(SYSINTR_CHARGEDONE); 的作用是恢复原来状态,以便下次按键继续触发
以下是将 Prima EVB 板 GPIO0_8 设置成中断源的具体步骤:
一:OAL 配置
1.在 c:\wince600\platform\tt4x0bd\src\inc\Oemintr.h 中添加
//2011-10-25 FD add for
#define IRQ_CHARGEDONE (IRQ_TD1120 - 2)
#define SYSINTR_CHARGEDONE (SYSINTR_TD1120 - 2)
2.在 c:\wince600\platform\tt4x0bd\src\oal\oallib\Intr.c 中
1)#define GPIO_GROUTP_CHARGEDONE_INT GPIO_GROUP(0) //2011-10-25 FD add for GPIO Interrupt
#define GPIO_INDEX_CHARGEDONE_INTGPIO_INDEX(8)
2)在函数 BSPIntrInit() 中添加
OALIntrStaticTranslate(SYSINTR_CHARGEDONE,IRQ_CHARGEDONE);
3)在函数 BSPIntrEnableIrq中添加
case IRQ_CHARGEDONE://2010-10-25 FD add for GPIO Interrupt
if(!OALGpioIntrIsRegisterd(GPIO_NUM(GPIO_GROUTP_CHARGEDONE_INT, GPIO_INDEX_CHARGEDONE_INT)))
{
RETAILMSG(1,(TEXT("^^==========61=========^^^^IRQ_JACK enable 2\r\n")));
OALGpioRegisterIntr(GPIO_NUM(GPIO_GROUTP_CHARGEDONE_INT,GPIO_INDEX_CHARGEDONE_INT),
GPIO_INTTYPE_FALLING_EDGE,SYSINTR_CHARGEDONE, IRQ_CHARGEDONE);//目的在与注册系统 ID 和中断服务 ID
GPIO_PAD_EN_SET(GPIO_GROUTP_CHARGEDONE_INT,1 << GPIO_INDEX_CHARGEDONE_INT);//1<<GPIO_INDEX_CHARGEDONE_INT is the sameto PIO_MASK(Index)
//PIO_OUTPUT_DISABLE(GPIO,GPIO_GROUTP_CHARGEDONE_INT, GPIO_INDEX_CHARGEDONE_INT);//It has no function
PIO_INT_ENABLE(GPIO,GPIO_GROUTP_CHARGEDONE_INT, GPIO_INDEX_CHARGEDONE_INT);
}
break;
4)在函数 BSPIntrDoneIrq 中添加
case IRQ_CHARGEDONE://2011-10-25 FD add for Interrupt
PIO_INT_ENABLE(GPIO,GPIO_GROUTP_CHARGEDONE_INT, GPIO_INDEX_CHARGEDONE_INT);
break;
目的是 ENABLE IO 口的中断
5)在函数 BSPIntrDisableIrq 中添加
case IRQ_CHARGEDONE: //2011-10-25 FD add for GPIO Interrupt
PIO_INT_DISABLE(GPIO,GPIO_GROUTP_CHARGEDONE_INT, GPIO_INDEX_CHARGEDONE_INT);
break;
目的是 DISABLE IO 口的中断
二:中断服务程序
Note:该程序可置于任意在 Platform.reg 和 Platform.bib 添加了信息的驱动中,在这里我添加在自己添加的 GPIO 命名的流驱动中
1.创建事件
1)全局变量 HANDLE m_hGpioEvent; //2011-10-25 FD add
2)在函数 GIO_Init中添加
m_hGpioEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!m_hGpioEvent)
{
RETAILMSG(1,(TEXT("\r\nCreateEvent ERROR!!--\r\n")));
return FALSE;
}
else RETAILMSG(1,(TEXT("\r\nCreateEvent OK!!--\r\n")));
2.初始化中断
1)系统中断ID:SYSINTR_CHARGEDONE 与事件关联
BOOL bSuccess;
bSuccess = InterruptInitialize(SYSINTR_CHARGEDONE, m_hGpioEvent, NULL, 0);
此时会调用OAL 中UINT32 BSPIntrEnableIrq(UINT32irq) ,进行中断的注册
2)由于存在 SYSINTR_CHARGEDONE,因此需要添加头文件oemintr.h,还要在 GPIO 的Source 文件中添加该头文件路径
$(_TARGETPLATROOT)\SRC\INC;$(INCLUDES)
3.创建线程
1)全局变量 HANDLE m_hGpioThread; //2011-10-25 FD add
2)在 GIO_Init 中添加
m_hGpioThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)GpioThread,
NULL,
0,
NULL);
if (!m_hGpioThread)
{
RETAILMSG(1,(TEXT("\r\nCreateThread ERROR!!--\r\n")));
return FALSE;
}
else RETAILMSG(1,(TEXT("\r\nCreateThread Successfully!!--\r\n")));
4.中断线程函数
void GpioThread()
{
while(TRUE)
{
InterruptDone(SYSINTR_CHARGEDONE);
WaitForSingleObject(m_hGpioEvent,INFINITE);//等待中断事件发生,即向下执行
RETAILMSG(1,(TEXT("m_hGpioThread: WaitForSingleObject -m_hGpioEvent!\r\n")));
}
}