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

📄 pwrmg.c

📁 针对Intel Xscale PXA255的WinCE boot loader源代码包!极具参考价值!
💻 C
字号:
/* Copyright ?2000-2001 Intel Corp.  */
/*++

Module Name:  OEMIdle.c

Abstract:  
 Intel XScale Microarchitecture OEM Idle routine
 for Platform Build 3.0 based systems
Notes:

--*/

#include <windows.h>
#include <bldver.h>
#include <nkintr.h>
#include "xsc1.h"
#include "XSC1bd.h"
#include "timerxsc1.h"
#include "pmu.h"


#include "drv_glob.h"



extern CPUEnterIdle();




extern  void usWaitHal(unsigned usVal);



DWORD curridlehigh, curridlelow; // 64-bit idle time in ms
DWORD CurMSec;  
BOOL bProfileTimerRunning;

DWORD DiffMSec;
DWORD dwPartialDiffMSec;
DWORD ticksleft, dwSleepMin;
static DWORD dwPartialCurMSec = 0;  // Keep sub-millisecond leftover.
volatile ULARGE_INTEGER CurTicks = { 0, 0 };

extern void  CheckIdaIdleExit(void);

//
//  This routine is called by the kernel when there are no threads ready to
//  run. The CPU should be put into a reduced power mode and halted. It is 
//  important to be able to resume execution quickly upon receiving an interrupt.
//
//  Note: It is assumed that interrupts are off when OEMIdle is called. 
//
void OEMIdle (DWORD dwIdleParam) 
{

    DWORD dwIdleMSec, dwIdleTick, dwTicksElapsed;
    DWORD dwPrevMSec = CurMSec;
    DWORD dwDiffMSecPrev = DiffMSec;

    DWORD dwCount, dwTemp;

    ULARGE_INTEGER currIdle = 
    {
        curridlelow,
        curridlehigh
    };

    volatile OST_REGS *v_pOSTReg = (volatile OST_REGS *)OST_BASE_U_VIRTUAL;
#ifdef PLAT_LUBBOCK
    volatile BLR_REGS *v_pBLReg = (volatile BLR_REGS *) FPGA_REGS_BASE_U_VIRTUAL;
    volatile GPIO_REGS  *v_pGPIOReg = (volatile GPIO_REGS *)GPIO_BASE_U_VIRTUAL;
#endif

	//RETAILMSG(0,(TEXT("+OEMIdle\r\n")));
    //
    // Check to see if scheduler needs to run before 
    // entering "idle"
    //

    //
    // if ticksleft, there are threads on the sleep queue waiting to run
    // Sleep timer expiring (dwSleepMin) and sleep queue needs to be checked
    //
    if ((ticksleft) || ((dwSleepMin) && (DiffMSec >= dwSleepMin))) 
    {
        //
        // Already time to wake up - return to scheduler
        //
        return;
    }

    if (bPMURunning)
    {
        //
        // If PMU is currently sampling, we can't enter idle mode,
        // else the PMU counters will be turned off
        //
        return;
    }




    if (bProfileTimerRunning) {
        // system timer is running at CPU specific profiling value - just call CPUEnterIdle and return
        CPUEnterIdle();
        CheckIdaIdleExit();   // IDAE bit testing.
        return;
    }

    //
    // If no minimum sleep time specified 
	// or interrupt latency timing (fIntrTime - not currently supported),
    //
    if (dwSleepMin == 0)
    {
        // idle till end of tick
        CPUEnterIdle();
        CheckIdaIdleExit();   // IDAE bit testing.


        // Update global idle time and return
        currIdle.QuadPart  += RESCHED_PERIOD;
        curridlelow = currIdle.LowPart;
        curridlehigh = currIdle.HighPart;

        return;
    }


    //
    // Calculate the idle period
    // Time since scheduler was run (DiffMSec) from time until next
    // thread is ready to run (dwSleepMin)
    //
    dwIdleMSec = dwSleepMin - dwDiffMSecPrev;

    //
    // Since OEMIdle( ) is being called in the middle of a normal reschedule
    // period, CurMSec, dwPartialCurMSec, dwPartialDiffMSec and CurTicks need
    // to be updated accordingly.
    //

    //
    //
    // Calculate ticks that have elapsed since last timer firing
    //
    dwCount = PerfCountSinceTick();
	dwTemp = dwCount;

    //
    // Adjust dwPartialDiffMSec and DiffMSec 
    // and dwPartialCurMSec and CurMSec

	//
	// Add any partial MSec from last time
    //
    dwCount += dwPartialCurMSec;
	dwTemp += dwPartialDiffMSec;

    //
    // Calculate new Partial Msec, DiffMsec
    //
    dwPartialCurMSec = dwCount % OEM_TICKS_1MS;
    dwPartialDiffMSec = dwTemp % OEM_TICKS_1MS;

    //
    // Convert to MS and add to CurMsec, DiffMsec 
    //
    dwCount /= OEM_TICKS_1MS;
    CurMSec += dwCount;

	dwTemp /= OEM_TICKS_1MS;
	DiffMSec += dwTemp;

    dwDiffMSecPrev = DiffMSec;

    //
    // Adjust idle with any Msecs that have elapsed 
    // (due to dwPartialCurMSec tracking) and...
    //
    // Only idle if there is more than a Msec to do so
    //
    if ((int) (dwIdleMSec -= CurMSec - dwPrevMSec) > 0)
    {
        //
        // Adjust PreviousMsec to Current 
        //
        dwPrevMSec = CurMSec;

        //
        // Check idle time to timer's max timeout value
        //
        if (dwIdleMSec > MAX_IDLE_TIME)
        {
            dwIdleMSec = MAX_IDLE_TIME;
        }
    
        dwIdleTick = dwIdleMSec * OEM_TICKS_1MS;

        //
        // Settimer to length of time for idlemode
        //   
        v_pOSTReg->osmr0 = v_pOSTReg->oscr + dwIdleTick; 

        //Clear and enable the M0 interrupt
        TIMER_M0_INT_CLR(v_pOSTReg->ossr);      
        TIMER_M0_INT_EN(v_pOSTReg->oier);


        //
        // Set CPU to Idle to be awakened on any interrupt
        //
        CPUEnterIdle();

        CheckIdaIdleExit();   // IDAE bit testing.
        INTERRUPTS_OFF();


        //      
        //  We've been interrupted from our idle time:
        //     * Update counters and idle time
        //     * Re-arm (&clear) system timer interval and return
        //


        //
        // We're awake! 
        // The wake-up ISR (or any other ISR) has already run.
        //
        if (dwPrevMSec != CurMSec) 
        {
            //
            // We completed the full period we asked to sleep.  Update the counters.
            //
            CurMSec  += (dwIdleMSec - RESCHED_PERIOD); // Subtract resched period, because ISR also incremented.
            DiffMSec  += (dwIdleMSec - RESCHED_PERIOD);
			
            CurTicks.QuadPart += (dwIdleMSec - RESCHED_PERIOD) * OEM_TICKS_1MS;
            currIdle.QuadPart += dwIdleMSec;
        } else 
        {
            //
            // Some other interrupt woke us up before the 
            // full idle period was complete.  
			//

			//
			// Determine how much time has elapsed and update time variables.
            //
			// Note: If oscr went past the match point, the math still works since
			// it accounts for the dwIdleTick time plus the time past the match.
			// 
			dwTicksElapsed = dwIdleTick - ((DWORD)v_pOSTReg->osmr0 - (DWORD)v_pOSTReg->oscr);

            currIdle.QuadPart += dwTicksElapsed;

            //
            // Calculate new Partial Msec
            //
			dwCount = dwPartialCurMSec;
            dwCount += dwTicksElapsed;
			dwPartialCurMSec = dwCount % OEM_TICKS_1MS;

            dwTemp = dwPartialDiffMSec;
            dwTemp += dwTicksElapsed;
			dwPartialDiffMSec = dwTemp % OEM_TICKS_1MS;


            //
            // Convert to MS and add to CurMsec
            //
			dwCount /= OEM_TICKS_1MS;
            CurMSec += dwCount;

			dwTemp /= OEM_TICKS_1MS;
            DiffMSec += dwTemp;

        }

		//
		// Update global idle time variables
		//
		curridlelow = currIdle.LowPart;
		curridlehigh = currIdle.HighPart;

        //
        // Restore timer increment to normal value
        //
	    v_pOSTReg->osmr0 = v_pOSTReg->oscr + RESCHED_INCREMENT;

        //
        // Clear any interrupt on Match 0
        //
        TIMER_M0_INT_CLR(v_pOSTReg->ossr); 
        TIMER_M0_INT_EN(v_pOSTReg->oier);

		//
		// Caller will turn interrupts back on
		//

    }    
    
    return;

}

void OEMPowerOff (void)
{
    
    RETAILMSG(0,(TEXT("+OEMPowerOff\r\n")));
    

    
    RETAILMSG(0,(TEXT("-OEMPowerOn\r\n")));
} 


  

⌨️ 快捷键说明

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