wince中断之2

来源:互联网 发布:腾讯国内足球数据 编辑:程序博客网 时间:2024/05/22 00:07

作者:wuan584974722

转自:http://blog.csdn.net/wuan584974722/article/details/7972905


上片我的博文说到一个问题,今天现在将将其整理如下:

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 - jli@sychip.com.cn
             //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吧。