如何实现2440软件重启/software reset(作者:wogoyixikexie@gliet)

     上周,把4.2下的BSP 的串口驱动(包括16C552的并口转换成串口的驱动)移植到5.0BSP下,经过一番周折,已经把所有异常排除了,但是用到外部中断2(EINT2)的注册表加载的时候导致系统重启。后来发现这个EINT2是系统默认做软件重启/software reset的中断的。找了一小时,把一些中断相关的东西改变一些了,但是还是照样加载重启。刚才无意中想到了一个函数OEMInterruptHandler,这个可以对中断做一些处理的,我想玄机就在这里了,果然是。下面来看看这个函数。

第一处:

C:\WINCE500\PLATFORM\SMDK2440A\Src\Common\Intr\intr.c(251)://  Function:  OEMInterruptHandler

 

//------------------------------------------------------------------------------
//
//  Function:  OEMInterruptHandler
//
ULONG OEMInterruptHandler(ULONG ra)
{
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 irq, irq2, mask;

    // Get pending interrupt(s)
    irq = INREG32(&g_pIntrRegs->INTOFFSET);

 g_oalLastSysIntr = TRUE;    //c ksk 20060404

    // System timer interrupt?
    if (irq == IRQ_TIMER4) {

        // Clear the interrupt
        OUTREG32(&g_pIntrRegs->SRCPND, 1 << IRQ_TIMER4);
        OUTREG32(&g_pIntrRegs->INTPND, 1 << IRQ_TIMER4);

        // Rest is on timer interrupt handler
        sysIntr = OALTimerIntrHandler();
 }   
    // Profiling timer interrupt?
    else if (irq == IRQ_TIMER2)
    {
        // Mask and Clear the interrupt.
        mask = 1 << irq;
        SETREG32(&g_pIntrRegs->INTMSK, mask);
        OUTREG32(&g_pIntrRegs->SRCPND, mask);
        OUTREG32(&g_pIntrRegs->INTPND, mask);

        // The rest is up to the profiling interrupt handler (if profiling
        // is enabled).
        //
        if (g_pProfilerISR)
        {
            sysIntr = g_pProfilerISR(ra);
        }
    }
    else if (irq == IRQ_EINT2)  // Softreset
    {
  RETAILMSG(1, (TEXT("OEMInterruptHandler: irq = %d \r\n"), irq));
  OALIoCtlHalReboot(IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL);
        sysIntr = SYSINTR_NOP;
    }
    else
    {

#ifdef OAL_ILTIMING
        if (g_oalILT.active) {
            g_oalILT.isrTime1 = OALTimerCountsSinceSysTick();
            g_oalILT.savedPC = 0;
            g_oalILT.interrupts++;
        }       
#endif
   
        if (irq == IRQ_EINT4_7 || irq == IRQ_EINT8_23) { // 4 or 5

            // Find external interrupt number
            mask = INREG32(&g_pPortRegs->EINTPEND);
            mask &= ~INREG32(&g_pPortRegs->EINTMASK);
            mask = (mask ^ (mask - 1)) >> 5;
            irq2 = IRQ_EINT4;
            while (mask != 0) {
                mask >>= 1;
                irq2++;
            }

            // Mask and clear interrupt
            mask = 1 << (irq2 - IRQ_EINT4 + 4);
            SETREG32(&g_pPortRegs->EINTMASK, mask);
            OUTREG32(&g_pPortRegs->EINTPEND, mask);

            // Clear primary interrupt
            mask = 1 << irq;
            OUTREG32(&g_pIntrRegs->SRCPND, mask);
            OUTREG32(&g_pIntrRegs->INTPND, mask);

            // From now we care about this irq
            irq = irq2;

        } 
      else if(irq == IRQ_CAM)
        {
         if(INREG32(&g_pIntrRegs->SUBSRCPND) & (1<<IRQ_SUB_CAM_C))
         {
           SETREG32(&g_pIntrRegs->INTSUBMSK, (1<<IRQ_SUB_CAM_C));
           SETREG32(&g_pIntrRegs->INTMSK, (1<<IRQ_CAM));
           OUTREG32(&g_pIntrRegs->SUBSRCPND, (1<<IRQ_SUB_CAM_C));
           OUTREG32(&g_pIntrRegs->SRCPND, (1<<IRQ_CAM));
           OUTREG32(&g_pIntrRegs->INTPND,(1<<IRQ_CAM));
           //RETAILMSG(1,(TEXT("IRQ_CAM Codec\r\n")));
         }
         
         else if(INREG32(&g_pIntrRegs->SUBSRCPND) & (1<<IRQ_SUB_CAM_P))
          {
           SETREG32(&g_pIntrRegs->INTSUBMSK, (1<<IRQ_SUB_CAM_P));
           SETREG32(&g_pIntrRegs->INTMSK, (1<<IRQ_CAM));
           OUTREG32(&g_pIntrRegs->SUBSRCPND, (1<<IRQ_SUB_CAM_P));
           OUTREG32(&g_pIntrRegs->SRCPND, (1<<IRQ_CAM));
           OUTREG32(&g_pIntrRegs->INTPND,(1<<IRQ_CAM));
           //RETAILMSG(1,(TEXT("PreView\r\n")));
         }
         
         else
         {
          SETREG32(&g_pIntrRegs->INTSUBMSK, (1<<IRQ_SUB_CAM_C)|(1<<IRQ_SUB_CAM_P));
          SETREG32(&g_pIntrRegs->INTMSK, (1<<IRQ_CAM));
          SETREG32(&g_pIntrRegs->SUBSRCPND, (1<<IRQ_SUB_CAM_C)|(1<<IRQ_SUB_CAM_P));         
          OUTREG32(&g_pIntrRegs->SRCPND, (1<<IRQ_CAM));
          OUTREG32(&g_pIntrRegs->INTPND,(1<<IRQ_CAM));
                 //RETAILMSG(1,(TEXT("nop\r\n")));          
          return SYSINTR_NOP;
         }
        }
         
 
 else {

            // Mask and clear interrupt
            mask = 1 << irq;
            SETREG32(&g_pIntrRegs->INTMSK, mask);
            OUTREG32(&g_pIntrRegs->SRCPND, mask);
            OUTREG32(&g_pIntrRegs->INTPND, mask);

        }

        // First find if IRQ is claimed by chain
        sysIntr = NKCallIntChain((UCHAR)irq);
        if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
            // IRQ wasn't claimed, use static mapping
            sysIntr = OALIntrTranslateIrq(irq);
        }
    }

 //g_oalLastSysIntr = sysIntr;
    return sysIntr;
}

//------------------------------------------------------------------------------

第二处:

C:\WINCE500\PLATFORM\SMDK2440A\Src\Common\Intr_dvs\intr.c(284)://  Function:  OEMInterruptHandler

//------------------------------------------------------------------------------
//
//  Function:  OEMInterruptHandler
//
ULONG OEMInterruptHandler(ULONG ra)
{
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 irq, irq2, mask;

#ifdef DVS_EN
#if (DVS_METHOD == 1 || DVS_METHOD == 3)
    unsigned int clkval_calc;
 unsigned int i;
#endif //(DVS_METHOD == 1 || DVS_METHOD == 3)
#endif //DVS_EN

 b_oalInterruptFlag = TRUE;

    // Get pending interrupt(s)
    irq = INREG32(&g_pIntrRegs->INTOFFSET);

#ifdef DVS_EN
#if (DVS_METHOD == 2)
#if ( USESWPWSAVING == 1)
 if ( bPowerSaving != TRUE )  // do not power up, if cpu load is low.
#endif //( USESWPWSAVING == 1)
 {
  int i;
  if ( GetCurrentVoltage() != V130 )
  {
   ChangeVoltage(HIGHVOLTAGE);
   for(i=0;i<VOLTAGEDELAY;i++)
   {
    INREG32(&g_pPortRegs->GPFDAT);  // for loop operation, just read.
   }
   DVS_OFF();
  }
 }

#elif (DVS_METHOD == 3)
 if ( CurrentState == Active )
 {
  if ( GetCurrentVoltage() != V130 )
  {
   ChangeVoltage(HIGHVOLTAGE);
   for(i=0;i<VOLTAGEDELAY;i++)
   {
    INREG32(&g_pPortRegs->GPFDAT);  // for loop operation, just read.
   }
   DVS_OFF();
  }
 }
#endif //(DVS_METHOD == 3)
#endif //DVS_EN
    // System timer interrupt?
    if (irq == IRQ_TIMER4) {

        // Clear the interrupt
        OUTREG32(&g_pIntrRegs->SRCPND, 1 << IRQ_TIMER4);
        OUTREG32(&g_pIntrRegs->INTPND, 1 << IRQ_TIMER4);

        // Rest is on timer interrupt handler
        sysIntr = OALTimerIntrHandler();
 }   
    // Profiling timer interrupt?
    else if (irq == IRQ_TIMER2)
    {
        // Mask and Clear the interrupt.
        mask = 1 << irq;
        SETREG32(&g_pIntrRegs->INTMSK, mask);
        OUTREG32(&g_pIntrRegs->SRCPND, mask);
        OUTREG32(&g_pIntrRegs->INTPND, mask);

        // The rest is up to the profiling interrupt handler (if profiling
        // is enabled).
        //
        if (g_pProfilerISR)
        {
            sysIntr = g_pProfilerISR(ra);
        }
    }
    else if (irq == IRQ_EINT2)  // Softreset
    {
//  RETAILMSG(1, (TEXT("g_pIntrRegs->INTMSK = 0x%x \r\n"), g_pIntrRegs->INTMSK));
//  RETAILMSG(1, (TEXT("OEMInterruptHandler: irq = %d \r\n"), irq));
#ifdef DVS_EN
#if (DVS_METHOD == 1 || DVS_METHOD == 3)
  ChangeVoltage(HIGHVOLTAGE);
  for(i=0;i<VOLTAGEDELAY;i++)
  {
   INREG32(&g_pPortRegs->GPFDAT); // for loop operation, just read.
  }
  DVS_OFF();
  //switch ( HCLKDIV )
  switch ( 4 )
  {
  case 4:
   CLKDIV124();
   break;
  case 6:
   CLKDIV136();
   break;
  case 8:
   CLKDIV148();
   break;
  }
#endif //(DVS_METHOD == 1 || DVS_METHOD == 3)
#endif //DVS_EN       
  OALIoCtlHalReboot(IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL);
        sysIntr = SYSINTR_NOP;
    }
#ifdef DVS_EN   
#if (DVS_METHOD == 1)
 else if(irq == IRQ_LCD)
 {
  VSYNCINTR = TRUE;
  if ( IDLEflag == FALSE )
  {

   // 4.1 Mask LCD VSYNC Interrupt
   OUTREG32(&g_pIntrRegs->INTMSK, INREG32(&g_pIntrRegs->INTMSK ) | (1 << IRQ_LCD ));
   if( INREG32(&g_pLCDRegs->LCDSRCPND) & 2) OUTREG32(&g_pLCDRegs->LCDSRCPND, 0x2);
   if( INREG32(&g_pLCDRegs->LCDINTPND) & 2) OUTREG32(&g_pLCDRegs->LCDINTPND, 0x2);   
   if( INREG32(&g_pIntrRegs->SRCPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->SRCPND, 0x1 << IRQ_LCD);
   if( INREG32(&g_pIntrRegs->INTPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->INTPND, 0x1 << IRQ_LCD);

   if (INREG32(&g_pLCDRegs->LCDCON5) & (0x3 << 15) ) // Check VSync Area.
   {
   }
   else
   {
    CurrStateIdle = FALSE;
    OUTREG32(&g_pLCDRegs->LCDCON1, INREG32(&g_pLCDRegs->LCDCON1) & ~(0x1)); //Disable LCD Output

    // 4.2 Return Voltage
    ChangeVoltage(HIGHVOLTAGE);

    // 4.3 Delay
    for(i=0;i<VOLTAGEDELAY;i++)
    {
     INREG32(&g_pPortRegs->GPFDAT); // for loop operation, just read.
    }

    // 4.4 DVS_ON = 0 (6:6:6->1:6:6)
    DVS_OFF();


    // 4.5 Return HCLK
    // (1:6:6) -> (1:6:12) -> (1:3:6)
    CLKDIV136();

    clkval_calc = (WORD)((float)(S3C2440A_HCLK)/(2.0*5000000)+0.5)-1;
    
    OUTREG32(&g_pLCDRegs->LCDCON1, (clkval_calc << 8)|(MVAL_USED << 7)|(3 << 5)|(12 << 1)|(1 << 0));
   }
  }
  else
  {

   // 2.1 Mask LCD VSYNC Interrupt
   OUTREG32(&g_pIntrRegs->INTMSK, INREG32(&g_pIntrRegs->INTMSK) | (1 << IRQ_LCD)); // disable LCD interrupt
   if( INREG32(&g_pLCDRegs->LCDSRCPND) & 2) OUTREG32(&g_pLCDRegs->LCDSRCPND, 0x2);
   if( INREG32(&g_pLCDRegs->LCDINTPND) & 2) OUTREG32(&g_pLCDRegs->LCDINTPND, 0x2);   
   if( INREG32(&g_pIntrRegs->SRCPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->SRCPND, 0x1 << IRQ_LCD);
   if( INREG32(&g_pIntrRegs->INTPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->INTPND, 0x1 << IRQ_LCD);

   if (INREG32(&g_pLCDRegs->LCDCON5) & (0x3 << 15) ) // Check VSync Area.
   {
   }
   else
   {
    CurrStateIdle = TRUE;
    OUTREG32(&g_pLCDRegs->LCDCON1, INREG32(&g_pLCDRegs->LCDCON1) & ~(0x1)); //Disable LCD Output

    // 2.2 Change HCLK Freq by half
    // (1:3:6) -> (1:6:12) -> (1:6:6)
    CLKDIV166();


    // 2.3 DVS_ON = 1 (6:6:6)
    DVS_ON();
    
    // 2.4 Drop Voltage
    ChangeVoltage(LOWVOLTAGE);

    clkval_calc = (WORD)((float)(S3C2440A_HCLK/2)/(2.0*5000000)+0.5)-1;

    OUTREG32(&g_pLCDRegs->LCDCON1, (clkval_calc << 8)|(MVAL_USED << 7)|(3 << 5)|(12 << 1)|(1 << 0));

   }
  }
  sysIntr = SYSINTR_NOP;
 }
#elif (DVS_METHOD == 3)
 else if( irq == IRQ_LCD )
 {
  VSYNCINTR = TRUE;
  if ( NextState == Active )
  {
   OUTREG32(&g_pIntrRegs->INTMSK, INREG32(&g_pIntrRegs->INTMSK) | (1 << IRQ_LCD)); // Disable LCD interrupt
   
   if( INREG32(&g_pLCDRegs->LCDSRCPND) & 2) OUTREG32(&g_pLCDRegs->LCDSRCPND, 0x2);
   if( INREG32(&g_pLCDRegs->LCDINTPND) & 2) OUTREG32(&g_pLCDRegs->LCDINTPND, 0x2);   
   if( INREG32(&g_pIntrRegs->SRCPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->SRCPND, 0x1 << IRQ_LCD);
   if( INREG32(&g_pIntrRegs->INTPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->INTPND, 0x1 << IRQ_LCD);


   CurrStateIdle = FALSE;
   OUTREG32(&g_pLCDRegs->LCDCON1, INREG32(&g_pLCDRegs->LCDCON1) & ~(0x1)); //Disable LCD Output

   ChangeVoltage(HIGHVOLTAGE);
   for(i=0;i<VOLTAGEDELAY;i++)
   {
    INREG32(&g_pPortRegs->GPFDAT); // for loop operation, just read.
   }
   DVS_OFF();

   CLKDIV136();
   clkval_calc = (WORD)((float)(S3C2440A_HCLK)/(2.0*5000000)+0.5)-1;
   
   OUTREG32(&g_pLCDRegs->LCDCON1, (clkval_calc << 8)|(MVAL_USED << 7)|(3 << 5)|(12 << 1)|(1 << 0));

   CurrentState = Active;
   NextState = 0;
  }
  else if ( NextState == SlowActive )
  {

   OUTREG32(&g_pIntrRegs->INTMSK, INREG32(&g_pIntrRegs->INTMSK) | (1 << IRQ_LCD)); // Disable LCD interrupt
   if( INREG32(&g_pLCDRegs->LCDSRCPND) & 2) OUTREG32(&g_pLCDRegs->LCDSRCPND, 0x2);
   if( INREG32(&g_pLCDRegs->LCDINTPND) & 2) OUTREG32(&g_pLCDRegs->LCDINTPND, 0x2);   
   if( INREG32(&g_pIntrRegs->SRCPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->SRCPND, 0x1 << IRQ_LCD);
   if( INREG32(&g_pIntrRegs->INTPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->INTPND, 0x1 << IRQ_LCD);


   CurrStateIdle = FALSE;
   OUTREG32(&g_pLCDRegs->LCDCON1, INREG32(&g_pLCDRegs->LCDCON1) & ~(0x1)); //Disable LCD Output

   CLKDIV136();
   clkval_calc = (WORD)((float)(S3C2440A_HCLK)/(2.0*5000000)+0.5)-1;
   
   OUTREG32(&g_pLCDRegs->LCDCON1, (clkval_calc << 8)|(MVAL_USED << 7)|(3 << 5)|(12 << 1)|(1 << 0));

   CurrentState = SlowActive;
   NextState = 0;
  }
  else if ( NextState == LazyActive )
  {

   // 2.1 Mask LCD VSYNC Interrupt
   OUTREG32(&g_pIntrRegs->INTMSK, INREG32(&g_pIntrRegs->INTMSK) | (1 << IRQ_LCD)); // Disable LCD interrupt
   if( INREG32(&g_pLCDRegs->LCDSRCPND) & 2) OUTREG32(&g_pLCDRegs->LCDSRCPND, 0x2);
   if( INREG32(&g_pLCDRegs->LCDINTPND) & 2) OUTREG32(&g_pLCDRegs->LCDINTPND, 0x2);   
   if( INREG32(&g_pIntrRegs->SRCPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->SRCPND, 0x1 << IRQ_LCD);
   if( INREG32(&g_pIntrRegs->INTPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->INTPND, 0x1 << IRQ_LCD);

   CurrStateIdle = TRUE;
   OUTREG32(&g_pLCDRegs->LCDCON1, INREG32(&g_pLCDRegs->LCDCON1) & ~(0x1)); //Disable LCD Output

   CLKDIV166();
   DVS_ON();
   ChangeVoltage(LOWVOLTAGE);

   clkval_calc = (WORD)((float)(S3C2440A_HCLK/2)/(2.0*5000000)+0.5)-1;

   OUTREG32(&g_pLCDRegs->LCDCON1, (clkval_calc << 8)|(MVAL_USED << 7)|(3 << 5)|(12 << 1)|(1 << 0));   

   CurrentState = LazyActive;
   NextState = 0;
  }
  else if ( NextState == DeepIdle )
  {

   // 2.1 Mask LCD VSYNC Interrupt
   OUTREG32(&g_pIntrRegs->INTMSK, INREG32(&g_pIntrRegs->INTMSK) | (1 << IRQ_LCD)); // Disable LCD interrupt
   if( INREG32(&g_pLCDRegs->LCDSRCPND) & 2) OUTREG32(&g_pLCDRegs->LCDSRCPND, 0x2);
   if( INREG32(&g_pLCDRegs->LCDINTPND) & 2) OUTREG32(&g_pLCDRegs->LCDINTPND, 0x2);   
   if( INREG32(&g_pIntrRegs->SRCPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->SRCPND, 0x1 << IRQ_LCD);
   if( INREG32(&g_pIntrRegs->INTPND) & ( 0x1 << IRQ_LCD)) OUTREG32(&g_pIntrRegs->INTPND, 0x1 << IRQ_LCD);

   CurrStateIdle = TRUE;
   OUTREG32(&g_pLCDRegs->LCDCON1, INREG32(&g_pLCDRegs->LCDCON1) & ~(0x1)); //Disable LCD Output

   CLKDIV166();
   DVS_ON();
   ChangeVoltage(LOWVOLTAGE);

   clkval_calc = (WORD)((float)(S3C2440A_HCLK/2)/(2.0*5000000)+0.5)-1;
   OUTREG32(&g_pLCDRegs->LCDCON1, (clkval_calc << 8)|(MVAL_USED << 7)|(3 << 5)|(12 << 1)|(1 << 0)); 

   NextState = 0;
  }
  sysIntr = SYSINTR_NOP;
 }
#endif //(DVS_METHOD == 3)

  
#endif  //DVS_EN   
   
    else
    {

#ifdef OAL_ILTIMING
        if (g_oalILT.active) {
            g_oalILT.isrTime1 = OALTimerCountsSinceSysTick();
            g_oalILT.savedPC = 0;
            g_oalILT.interrupts++;
        }       
#endif
   
        if (irq == IRQ_EINT4_7 || irq == IRQ_EINT8_23) { // 4 or 5

            // Find external interrupt number
            mask = INREG32(&g_pPortRegs->EINTPEND);
            mask &= ~INREG32(&g_pPortRegs->EINTMASK);
            mask = (mask ^ (mask - 1)) >> 5;
            irq2 = IRQ_EINT4;
            while (mask != 0) {
                mask >>= 1;
                irq2++;
            }

            // Mask and clear interrupt
            mask = 1 << (irq2 - IRQ_EINT4 + 4);
            SETREG32(&g_pPortRegs->EINTMASK, mask);
            OUTREG32(&g_pPortRegs->EINTPEND, mask);

            // Clear primary interrupt
            mask = 1 << irq;
            OUTREG32(&g_pIntrRegs->SRCPND, mask);
            OUTREG32(&g_pIntrRegs->INTPND, mask);

            // From now we care about this irq
            irq = irq2;

        }  else {

            // Mask and clear interrupt
            mask = 1 << irq;
            SETREG32(&g_pIntrRegs->INTMSK, mask);
            OUTREG32(&g_pIntrRegs->SRCPND, mask);
            OUTREG32(&g_pIntrRegs->INTPND, mask);

        }

        // First find if IRQ is claimed by chain
        sysIntr = NKCallIntChain((UCHAR)irq);
        if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
            // IRQ wasn't claimed, use static mapping
            sysIntr = OALIntrTranslateIrq(irq);
        }
    }

    return sysIntr;
}

//------------------------------------------------------------------------------

     很明显,这个OALIoCtlHalReboot(IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL);函数实现了软件复位。现在两个地方出现了这个函数,只要把这个去掉就可以了。哦,不行不能直接屏蔽的。还要做一些处理,因为在外部串口中还是需用到这个中断的。暂时不管先,先看看这个OALIoCtlHalReboot是怎么实现重启的吧。

     

     在C:\WINCE500\PLATFORM\SMDK2440A\Src\Inc\ioctl_tab.h(43):{ IOCTL_HAL_REBOOT,   0,  OALIoCtlHalReboot    }, 从这个可以看出在wince起来之后可以使用KernelIOControl函数来实现软件复位的。找到源码所在C:\WINCE500\PLATFORM\SMDK2440A\Src\Common\Ioctl\reboot.c(27):BOOL OALIoCtlHalReboot(UINT32 code, VOID *pInpBuffer,

 

//------------------------------------------------------------------------------
//  it only uses the watchdog timer to assert reset 看门狗复位?狗没有喂就会重新启动?貌似在单片机中实现过。哈哈,厉害。
//  Function: OALIoCtlHalReboot
//
//
BOOL OALIoCtlHalReboot(UINT32 code, VOID *pInpBuffer,
                       UINT32 inpSize, VOID *pOutBuffer,
                       UINT32 outSize, UINT32 *pOutSize)
{
    //
    // If the board design supports software-controllable hardware reset logic, it should be
    // used.  Because this routine is specific to the S3C2440A CPU, it only uses the watchdog
    // timer to assert reset.  One downside to this approach is that nRSTOUT isn't asserted
    // so any board-level logic isn't reset via this method.  This routine can be overidden in
    // the specific platform code to control board-level reset logic, should it exist.
    //

    volatile S3C2440A_WATCHDOG_REG *pWDRegs = (volatile S3C2440A_WATCHDOG_REG *)
                                              OALPAtoVA(S3C2440A_BASE_REG_PA_WATCHDOG, FALSE);

    OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalReboot\r\n"));

    // Setup the watchdog.
    //
    pWDRegs->WTDAT = 0;
    pWDRegs->WTCNT = 5;         // Load count with low value.
    pWDRegs->WTCON = 0x8021;    // Enable watchdog timer...

    // Wait for watchdog reset...
    //
    while(TRUE);

    // Should never get to this point...
    //
    OALMSG(OAL_IOCTL&&OAL_FUNC, (L"-OALIoCtlHalReboot\r\n"));

    return(TRUE);

}

//------------------------------------------------------------------------------

     关于中断的详细过程,请看这个帖子http://www.cnblogs.com/wogoyixikexie/archive/2009/02/04/1383849.html

你可能感兴趣的:(software)