zoukankan      html  css  js  c++  java
  • 如何实现2440软件重启/software reset(作者:wogoyixikexie@gliet)

    如何实现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

  • 相关阅读:
    HDU 2100 LoveKey
    HDU 2111 Saving HDU
    HDU 2132 An easy problem
    PAT 甲级 1081 Rational Sum (数据不严谨 点名批评)
    LWIP内存管理
    LWIP带UCOS操作系统移植
    LWIP协议栈2-
    LWIP协议栈1
    掌握所有IO口的外部中断
    熟悉相关电路,控制I/O口,且配置相关参数,LED,光敏,74LS164数码管
  • 原文地址:https://www.cnblogs.com/gooogleman/p/1869734.html
Copyright © 2011-2022 走看看