⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 C
📖 第 1 页 / 共 2 页
字号:
    // Limit the maximum idle time to what is supported.
    if (idleSysTicks > g_timer.maxIdleMSec) idleSysTicks = g_timer.maxIdleMSec;

    // Find where we are and if interrupt is pending
    cnt = INREG32(&pTimerRegs->TCR);
    if (OALIntrIsIrqPending(IRQ_TIMER32K)) {
        // Full period was used, leave OEMIdle...
        usedCounts = TIMER_PERIOD;
        idleSysTicks = 1;
    } else {
        // We already used 
        usedCounts = TIMER_PERIOD - cnt;
        // If there is pending timer update or we are neer to interrupt
        // then sleep only until 32K interrupt
        if (g_timer.updatePeriod || cnt < TIMER_MARGIN) idleSysTicks = 1;
    }

    // Prolong timer period to idle time when it is longer than 1ms
    if (idleSysTicks > 1) {

        // Clear deep sleep flag
        deepSleep = FALSE;

        // Idle time in hi-res ticks
        idleCounts = idleSysTicks << 5;
        // New timer period without timer setup compensation
        set = idleCounts - usedCounts - 1;
        // Wait for timer value change...
        do {
            while (cnt == INREG32(&pTimerRegs->TCR));
            // We have check for interrupt one more time...
            cnt = INREG32(&pTimerRegs->TCR);
        } while (cnt == TIMER_PERIOD - 1);            

        // If there is pending interrupt now use short idle...
        if (OALIntrIsIrqPending(IRQ_TIMER32K)) {

            usedCounts = TIMER_PERIOD;
            idleSysTicks = 1;

        } else {

            // Compensate for timer update delays
            set -= SET_COMPENSATION;
            usedCounts += SET_COMPENSATION;

            // We need to find if OMAP730 will go to deep sleep mode.
            if (
                g_timer.deepSleep && 
                set >= g_timer.deepSleepTreshold &&
                (INREG16(&pULPDRegs->STATUS_REQ) ^ 0x0006) == 0 &&
                INREG16(&pULPDRegs->STATUS_REQ2) == 0 &&
                INREG16(&pULPDRegs->SOFT_REQ) == 0
            ) {
                // Enable deep sleep
                SETREG16(&pULPDRegs->POWER_CTRL, POWER_CTRL_DEEP_SLEEP_EN);
                // Reduce idle length
                set -= g_timer.deepSleepSetup;
                // Set deep sleep flag
                deepSleep = TRUE;
            } else {
                // Disable deep sleep
                CLRREG16(&pULPDRegs->POWER_CTRL, POWER_CTRL_DEEP_SLEEP_EN);
            }                

            // Set new value
            OUTREG32(&pTimerRegs->TVR, set);
            SETREG32(&pTimerRegs->CR, CR_TRB);
            // Wait while it is set
            while ((INREG32(&pTimerRegs->CR) & CR_TRB) != 0);
            // Wait until one tick (any timer set in this time is ignored)
            while (INREG32(&g_timer.pTimerRegs->TCR) != (set - 2));
        }

    } else {

        idleCounts = TIMER_PERIOD;

    }

#if 1
    // Show that we are going sleep
    OALLED(LED_IDX_IDLE, 1);

    // Display clock requests
    OALLED(LED_IDX_CLKREQ1, INREG16(&pULPDRegs->STATUS_REQ));
    OALLED(LED_IDX_CLKREQ2, INREG16(&pULPDRegs->STATUS_REQ2));
    OALLED(LED_IDX_SOFTREQ, INREG16(&pULPDRegs->SOFT_REQ));
    OALLED(LED_IDX_DBBSTAT, INREG16(&pULPDRegs->PCC_DBB_STATUS));
    OALLED(LED_IDX_ITSTAT,  INREG16(&pULPDRegs->PCC_IT_STATUS));
    OALLED(LED_IDX_IDLECT1, INREG16(&pCLKMRegs->IDLECT1));
    OALLED(LED_IDX_IDLECT2, INREG16(&pCLKMRegs->IDLECT2));
    OALLED(LED_IDX_IDLECT3, INREG16(&pCLKMRegs->IDLECT3));
    OALLED(LED_IDX_SOFT_DIS_REQ, INREG16(&pULPDRegs->SOFT_DISABLE_REQ));
#endif

    // Without following 16 microsecond stall command device hangs
    // on retail image without LED debug output. It happens on retail 
    // tiny kernel image (however with shell&KITL), so it seems to be
    // related to sleep itself. MultiICE JTAG isn't able to connect
    // to hang device and it doesn't look as hang in timer related
    // code (verified by LEDs output added to all timer while
    // wait loops).
    OALStall(16);

    // Move SoC/CPU to idle mode - interrupt are disabled
    OALCPUIdle();

#if 1
    // Display awake mode
    OALLED(LED_IDX_SLEEPSTAT, INREG16(&pULPDRegs->SLEEP_STATUS));

    // Hide sleep signal
    OALLED(LED_IDX_IDLE, 0);
#endif

    // Get current counter value
    cnt = INREG32(&pTimerRegs->TCR);

    // Was 32K timer modified?
    if (idleSysTicks > 1) {

        // If we should fall deep sleep but there was only big sleep
        // correct idleSysTick value (we wait shorter...)
        if (deepSleep) {
            set += g_timer.deepSleepSetup >> 5;
            if ((INREG16(&pULPDRegs->SLEEP_STATUS) & BIG_SLEEP) != 0) {
                idleSysTicks -= g_timer.deepSleepSetup >> 5;
            }                
        }                

        if (!OALIntrIsIrqPending(IRQ_TIMER32K) && cnt > TIMER_MARGIN) {

            // Wait for timer value change...
            while (cnt == INREG32(&pTimerRegs->TCR));

            // We have recheck pending IRQ
            cnt = INREG32(&pTimerRegs->TCR);
            if (!OALIntrIsIrqPending(IRQ_TIMER32K)) {

                // Update timer period back
                counts = usedCounts + set - cnt + 1;
                idleSysTicks = counts >> 5;
                counts -= idleSysTicks << 5;
                set = TIMER_PERIOD - counts - 1;
                if (set == 0) set += TIMER_PERIOD - 1;

                // Set new value
                OUTREG32(&pTimerRegs->TVR, set);
                SETREG32(&pTimerRegs->CR, CR_TRB);
                // Wait while it is set
                while ((INREG32(&pTimerRegs->CR) & CR_TRB) != 0);
                // Wait until one tick (any timer set in this time is ignored)
                while (INREG32(&pTimerRegs->TCR) != set);
                while (INREG32(&pTimerRegs->TCR) >= set);

            } else {
            
                // Interrupt handler will add final one tick to clock
                idleSysTicks--;

            }

        } else {

            // Interrupt handler will add final one tick to clock
            idleSysTicks--;
            
        }

        // There must be period update
        g_timer.updatePeriod = TRUE;

        // Fix system tick counters & idle counter
        idleCounts = idleSysTicks << 5;
        g_timer.curCounts += idleCounts;
        CurMSec = (UINT32)((g_timer.curCounts * 1000) >> 15);

    } else if (!OALIntrIsIrqPending(IRQ_TIMER32K)) {

        // Fix idle count to get better idle time
        idleCounts -= cnt;
    }

    // Get real idle value. If result is negative we didn't idle at all.
    idleCounts -= usedCounts;
    if (idleCounts < 0) idleCounts = 0;

    // Update idle counters
    idle.LowPart = curridlelow;
    idle.HighPart = curridlehigh;
    idle.QuadPart += idleCounts * 1000;
    curridlelow  = idle.LowPart;
    curridlehigh = idle.HighPart;
}

//------------------------------------------------------------------------------
//
//  Function: SC_GetTickCount
//
//  This returns the number of milliseconds that have elapsed since Windows
//  CE was started. If the system timer period is 1ms the function simply
//  returns the value of CurMSec. If the system timer period is greater then
//  1 ms, the HiRes offset is added to the value of CurMSec.
//
UINT32 SC_GetTickCount()
{
    return CurMSec;
}

//------------------------------------------------------------------------------
//
//  Function:  OALIoCtlHalSetDeepSleepMode
//
//  This function is called from internal bus driver to enable/disable
//  deep sleep mode.
//
BOOL OALIoCtlHalSetDeepSleepMode(
    UINT32 code, VOID *pInBuffer, UINT32 inSize, VOID *pOutBuffer,
    UINT32 outSize, UINT32 *pOutSize
) {
    BOOL rc = FALSE;

    // Check buffer size
    if (pInBuffer == NULL || inSize < sizeof(BOOL)) {
        NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
        OALMSG(OAL_WARN, (L"WARN: OALIoCtlHalSetDeepSleepMode: "
            L"Buffer too small\r\n"
        ));
        goto cleanUp;
    }

    // Set new value
    g_timer.deepSleep = *(BOOL*)pInBuffer;

    // Done
    rc = TRUE;
    
cleanUp:
    return rc;
}

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -