在音频驱动(WM9705)的Hwctxt.cpp的initcodec函数中加入如下代码:
if (m_pGPIORegs == NULL)
{
PHYSICAL_ADDRESS ioPhysicalBase = {BULVERDE_BASE_REG_PA_GPIO,0};
m_pGPIORegs = (PBULVERDE_GPIO_REG)MmMapIoSpace(ioPhysicalBase, sizeof(BULVERDE_GPIO_REG),FALSE);
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
//create the headphone Event
gHeadPhoneIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//Interrupt initialize and connect SYSINTR with EVENT.
if (!(InterruptInitialize(SYSINTR_HEADPHONE_DETECT, gHeadPhoneIntrEvent, NULL, 0))) {
WAV_DBGMSG(TEXT("[Audio]Intialize the interrupt gHeadphoneIntrEvent error/r/n"));
}
//Create the Interrupt thread
gHeadPhoneIntrThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)HeadPhoneIntrThread,this, 0, NULL);
if (!gHeadPhoneIntrThread)
{
WAV_DBGMSG(TEXT("Create the Detect thread failure--/r/n"));
}
其中SYSINTR_HEADPHONE_DETECT定义在Bsp_cfg.h中,具体定义如下:
#define SYSINTR_HEADPHONE_DETECT (SYSINTR_FIRMWARE+19) //chose a unused intr
具体的中断处理函数如下:
int WINAPI HeadPhoneIntrThread(void)
{
while(1)
{
WaitForSingleObject(gHeadPhoneIntrEvent,INFINITE);
//if GPIO34 is high,means headphone is inserted
if (m_pGPIORegs->GPLR1 & XLLP_BIT_2)
{
HeadPhone_Detect=1;
//WAV_DBGMSG(TEXT("[Audio]in HeadphoneIntrThread Headphone in--/r/n"));
WMAudioMuteSignal( DeviceToRW, WM_AUDIO_HEADPHONE, FALSE );//open headphone output
WMAudioMuteSignal( DeviceToRW, WM_AUDIO_LINEOUT, TRUE );//mute the lineout output
}
else
{
HeadPhone_Detect=0;
//WAV_DBGMSG(TEXT("[Audio]in HeadphoneIntrThread Headphone out--/r/n"));
WMAudioMuteSignal( DeviceToRW, WM_AUDIO_HEADPHONE,TRUE );
WMAudioMuteSignal( DeviceToRW, WM_AUDIO_LINEOUT, FALSE );
}
InterruptDone(SYSINTR_HEADPHONE_DETECT);
}
}
但是SYSINTR_HEADPHONE_DETECT是如何和真正的中断联系起来的呢,具体的操作在intr.c里面.这个文件位于/project/platform/mainstoneii/src/kernel/oal.
OALIntrStaticTranslate(SYSINTR_HEADPHONE_DETECT, IRQ_HEADPHONE_DETECT);
这句将SYSINTR_HEADPHOONE_DETECT和真正的中断号联系起来.而IRQ_HEADPHONE_DETECT的定义也在这儿:#define IRQ_HEADPHONE_DETECT (IRQ_BULVERDE_MAX + 15)
注意,这里的IRQ_HEADPHONE_DETECT与#define IRQ_GPIO0_PCMCIA_S1_CSC (IRQ_BULVERDE_MAX + 15) 是一样的,因为PCMCIA在系统里面没有用,所以采用这个中断来给我们的HEADPHONE使用.所以别忘了把下面这句注释掉,否则你的系统会不知道这个中断给谁用了.
//OALIntrStaticTranslate(SYSINTR_PCCARD_CSC_S1, IRQ_GPIO0_PCMCIA_S1_CSC);
然后在BSPIntrEnableIrq函数中加入对headphone IRQ的处理:
if (irq == IRQ_HEADPHONE_DETECT)
{
// WAV_DBGMSG(TEXT("[Audio]Setting GPIO for Headphone in BSPIntrEnableIrq/r/n"));
g_pGPIORegs->GAFR1_L &= ~XLLP_GPIO_AF_BIT_FFRXD_MASK; //GPIO34 as GPIO
g_pGPIORegs->GPDR1 &= ~XLLP_BIT_2; //GPIO34 as HPS Input
//set the falling edge and rising edg to work
g_pGPIORegs->GFER1 |=XLLP_BIT_2;
g_pGPIORegs->GRER1 |=XLLP_BIT_2;
}
同样的在BSPIntrDisableIrq函数中也要加入处理headphone IRQ的代码:
else if (irq == IRQ_HEADPHONE_DETECT)
{
//clear the falling edge and rising to start the interrupt
g_pGPIORegs->GFER1 &=~XLLP_BIT_2;
g_pGPIORegs->GRER1 &=~XLLP_BIT_2;
}
在BSPIntrActiveIrq函数中,可以知道这个函数的用途是:This function is called from interrupt handler to give BSP chance to translate IRQ in case of secondary interrupt controller.可以看到实际处理我们HEADPHONE IRQ的函数是GPIOXX2InterruptHandler().在这个函数中处理Headphone IRQ的代码为:
else if (g_pGPIORegs->GEDR1 & XLLP_BIT_2)
{//set the GPIO Edge Status Register
g_pGPIORegs->GEDR1 |= XLLP_BIT_2;
//return IRQ to enbale the EVENT
return IRQ_HEADPHONE_DETECT;
}
此处返回中断号可以触发EVENT.这样的话在中断处理函数中 WaitForSingleObject(gHeadPhoneIntrEvent,INFINITE);就可以知道中断发生了,否则的话它会等在这儿.
这样在WINCE下的GPIO中断处理到检测就完成了.