上片我的博文说到一个问题,今天现在将将其整理如下:
1:wince下面的中断有两种:一种是静态的,另一种是动态的。他们的作用是维护两个数组g_oalsysIntr2iqr[]和g_oaliqr2sysIntr[].
2.我们的中断发生的时候,产生的中断必须在这个两个数组里面能找到相应的IQR和SYSINTR,所以不管是动态申请还是静态分配都是将这两个数组维护好。向里面填充对应的物理中断号和逻辑中断号。
3.cpu的执行流程:
# 1.发生中断后,CPU跳转到异常向量表处并执行IRQHandler,然后调用OEMInterruptHandler。
# 2.OEMInterruptHandler会根据IRQ返回对应的SYSINTR号,但前提是驱动中先通过KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,...)或其他方式建立IRQ与SYSINTR的映射,否则会返回SYSINTR_NOP
OEMInterruptHandler在d:\WINCE500\PRIVATE\WINCEOS\COREOS\NK\KERNEL\ARM\armtrap.s被调用了
4.OEMInterruptHandler源码网上抄的。
ULONG OEMInterruptHandler(ULONG ra)
{
UINT32 irq = OAL_INTR_IRQ_UNDEFINED;
UINT32 sysIntr = SYSINTR_NOP;
if (!g_pICReg) {
return(SYSINTR_NOP);
}
// Two steps for now, maybe condense later.
irq = XllpReadINTCReg(XLLP_INTC_ICHP);
irq = (irq >> 16) & 0x3F;
OALProfIRQEvent(irq);
//add by hgeng 2009-05-26
RETAILMSG(1, (TEXT("OEMInterruptHandler@@Intr\intr.c: irq = %d \r\n"), irq));
if (irq == 0)
{
return(SYSINTR_NOP);
}
// System timer interrupt?
else if(irq == IRQ_OSMRXX_4)
{
P_XLLP_OST_T pOSTRegs = (P_XLLP_OST_T)OALPAtoVA(MONAHANS_BASE_REG_PA_OST, FALSE);
if (pOSTRegs->ossr & XLLP_OSSR_M4)
{
sysIntr = OALTimerIntrHandler();
}
else if(pOSTRegs->ossr & XLLP_OSSR_M8)
{
UINT32 utiliz;
sysIntr = IPM_WindowDone(&utiliz);
}
}
else if (irq == IRQ_OSMR0)
{
XllpINTCEnableSource(irq,XLLP_FALSE);
sysIntr = SYSINTR_NOP;
}
// Profiling timer interrupt?
else if (irq == IRQ_OSMR2)
{
// Mask the interrupt
(void) XllpINTCEnableSource(irq,XLLP_FALSE);
// The rest is up to the profiling interrupt handler (if profiling
// is enabled).
//
if (g_pProfilerISR) {
sysIntr = g_pProfilerISR(ra);
}
}
else if (irq == IRQ_OSMR3)
{
XllpINTCEnableSource(irq,XLLP_FALSE);
sysIntr = SYSINTR_NOP;
}
#ifdef ENABLE_RCOMP
else if (irq == XLLP_INTC_S_DMEM)
{
// check if the RCOMP interrupt by read DMCISR[RCI] bit.
// if so,
// 1, clear the DMCISR[RCI]
// 2, read the MDCNFG for DMCISR, use the PCODE and NCODE of it to calculate.
// 3, write the PAD_XX with the new value.
XLLP_UINT32_T regIsr;
P_XLLP_DMEM_REGISTER_T pReg = (P_XLLP_DMEM_REGISTER_T) OALPAtoVA(MONAHANS_BASE_REG_PA_DMEMC, FALSE);
XllpINTCEnableSource(irq,XLLP_FALSE);
regIsr = pReg->dmcisr;
if (pReg->dmcisr & XLLP_DMCISR_RCI )
{
OALMSG(OAL_INTR, (L"OALIntrInit: irq number %x\r\n", irq));
pReg->dmcisr &= XLLP_DMCISR_RCI; //all the bits are write-clear bit or read-only bit.
OALMSG(OAL_INTR, (L"OALIntrInit: to update Rcomp()\r\n"));
XllpMemcRcompUpdate( pReg );
}
XllpINTCEnableSource(irq,XLLP_TRUE);
sysIntr = SYSINTR_NOP;
}
#endif
// Board-level interrupts
else
{
UINT32 origIrq = irq; // save the original so we can tell if it's BSP specific irq
//OALMSG(1, (L"OAL:OEMInterruptHandler: Irq %d\r\n", irq));
if ((irq == IRQ_GPIO0)||(irq == IRQ_GPIO1))
{
// Mask the interrupt
(void) XllpINTCEnableSource(irq,XLLP_FALSE);
#ifdef OAL_BSP_CALLBACKS
// Give BSP chance to translate IRQ -- if there is subordinate
// interrupt controller in BSP it give chance to decode its status
// and change IRQ
irq = BSPIntrActiveIrq(irq);
#endif
} else if(irq == IRQ_GPIOXX_2) {
UINT32 gedr, ggroup, i;
#ifdef BSP_DEBUG_LJ // For Debug - [email protected]
//OALMSG(1, (L"OAL:OEMInterruptHandler: GPIO Irq %d\r\n", irq));
#endif // LJDEBUG
if ((g_pGPIO->gedr0)&0xfffffffc) { // don't care GPIO0 and GPIO1
gedr = g_pGPIO->gedr0;
ggroup = 0;
} else if (g_pGPIO->gedr1) {
gedr = g_pGPIO->gedr1;
ggroup = 1;
} else if (g_pGPIO->gedr2) {
gedr = g_pGPIO->gedr2;
ggroup = 2;
} else if (g_pGPIO->gedr3) {
gedr = g_pGPIO->gedr3;
ggroup = 3;
} else {
//TO-DO: actually, should ASSERT here.
//TEMPORARY FIX: ignore this interrupt to avoid dead loop here
return(SYSINTR_NOP);
}
// Find out which bit causes the IRQ.
i = 0;
while(!(gedr&0x1)) {
gedr = gedr>>1;
i++;
}
i = i + ggroup*32;
//OALMSG(1, (L"OAL:OEMInterruptHandler: i = %d\r\n", i));
// Get current level on that GPIO
//XllpGpioGetLevel (g_pGPIO, i, &(g_GPIOPrevLevel[i]));
// Clear edge detect status first.
// Don't disable edge detect here.
// Otherwise, we may lose GPIO edge interrupt.
// In future, GPIO level interrupt is preferred.
//if (GPIO_RISE&g_GPIOEdgeDetect[i])
// XllpGpioSetRisingEdgeDetectEnable(g_pGPIO, i, XLLP_OFF);
//if (GPIO_FALL&g_GPIOEdgeDetect[i])
// XllpGpioSetFallingEdgeDetectEnable(g_pGPIO, i, XLLP_OFF);
XllpGpioClearEdgeDetectStatus (g_pGPIO, i);
// Compose the IRQ number.
irq = IRQ_GPIO_SHARE_BASE - 2 + i;
#ifdef OAL_BSP_CALLBACKS
// Give BSP chance to translate IRQ -- if there is subordinate
// interrupt controller in BSP it give chance to decode its status
// and change IRQ
irq = BSPIntrActiveIrq(irq);
#endif
} else
{
// Mask the interrupt
(void) XllpINTCEnableSource(irq,XLLP_FALSE);
}
// First find if IRQ is claimed by chain
sysIntr = (UINT16)NKCallIntChain((UCHAR)irq);
//fix the Intallable ISR error according to the MS documents.
//If the installable ISR returns SYSINTR_NOP,
//the BSP interrupt handler code will re-enable the interrupt and
//return SYSINTR_NOP.
if (sysIntr == SYSINTR_NOP)
{
//SETREG32(&g_pICReg->icmr, (1 << irq));
(void) XllpINTCEnableSource(irq,XLLP_TRUE);
return SYSINTR_NOP;
}
if (sysIntr == (UINT16)SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr))
{
// IRQ wasn't claimed, use static mapping
sysIntr = OALIntrTranslateIrq(irq);
#ifdef BSP_DEBUG_LJ
OALMSG(1, (L"-OALIntrTranslateIrq--hgeng\r\n"));
OALMSG(1, (L"+OALIntrTranslateIrq(%d)\r\n", irq));
OALMSG(1, (L"-OEMTranslateIrq(sysIntr = %d)\r\n", sysIntr));
#endif
}
// unmask interrupts in case it's NOP or invalid
if (SYSINTR_NOP == sysIntr) {
if (origIrq != irq) {
#ifdef OAL_BSP_CALLBACKS
// BSP specific irq
BSPIntrEnableIrq (irq);
#endif
if (origIrq == IRQ_GPIOXX_2) {
if (GPIO_RISE&g_GPIOEdgeDetect[IRQ_TO_GPIO_NUM(irq)])
XllpGpioSetRisingEdgeDetectEnable(g_pGPIO, IRQ_TO_GPIO_NUM(irq), XLLP_ON);
if (GPIO_FALL&g_GPIOEdgeDetect[IRQ_TO_GPIO_NUM(irq)])
XllpGpioSetFallingEdgeDetectEnable(g_pGPIO, IRQ_TO_GPIO_NUM(irq), XLLP_ON);
}
} else
{
// Unmask the interrupt
(void) XllpINTCEnableSource(irq,XLLP_TRUE);
}
}
}
return (sysIntr);
}
wince的中断算是搞清楚了,但是像什么可安装的中断,估计就是加个dll吧。