timer.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 704 行 · 第 1/2 页
C
704 行
// performance counter, the return value is FALSE.
//
// If this function is implemented by the OEM, the pointer pQueryPerformanceFrequency
// should be initialized as follows:
//
// BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpPerformanceFrequency)=OEMQueryPerformanceFrequency;
//
//------------------------------------------------------------------------------
BOOL
OEMQueryPerformanceFrequency(
LARGE_INTEGER *lpliPerformanceFreq
)
{
lpliPerformanceFreq->HighPart = 0;
lpliPerformanceFreq->LowPart = PerfCountFreq( );
return TRUE;
}
//------------------------------------------------------------------------------
// set pointers to OEM functions
//------------------------------------------------------------------------------
BOOL (*pQueryPerformanceCounter)(LARGE_INTEGER *lpliPerformanceCount)=OEMQueryPerformanceCounter;
BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpliPerformanceFreq)=OEMQueryPerformanceFrequency;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
CPUSetSysTimerCount(
DWORD dwCountdownMSec
)
{
// Using fixed tick, so do nothing
return;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
CPUClearSysTimerIRQ(
void
)
{
// Using fixed tick, so do nothing
return FALSE;
}
// In general the PIT (8254) does not support immediate reprogramming of the counter
// (the 8254 waits until the current countdown cycle is finished before reloading the
// counter with the new value) so the counter is fixed at SYSTEM_TICK_MS. If this
// OAL is being adapted to a system with a reprogrammable countdown timer or a
// free running counter with compare registers, see the ODO platform for examples.
#define IDLE_MAX_MS SYSTEM_TICK_MS
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DWORD
CPUGetSysTimerCountMax(
DWORD dwIdleMSecRequested
)
{
if (dwIdleMSecRequested > IDLE_MAX_MS) {
//
// Our timer isn't capable of idling more than IDLE_MAX_MS milliseconds.
// We'll have to break the sleep time into reasonable chunks.
//
return IDLE_MAX_MS;
}
return dwIdleMSecRequested;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
CPUEnterIdle(
DWORD dwIdleParam
)
{
_asm {
sti
hlt
}
}
//------------------------------------------------------------------------------
//
// 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.
//
//------------------------------------------------------------------------------
#if (CE_MAJOR_VER == 0x0003)
// Cedar
DWORD
CPUGetSysTimerCountElapsed(
DWORD dwTimerCountdownMSec,
volatile DWORD *pCurMSec,
volatile DWORD *pDiffMSec,
DWORD *pPartialCurMSec,
DWORD *pPartialDiffMSec,
volatile ULARGE_INTEGER *pCurTicks
)
{
// Using fixed tick, so do nothing and return 0 time passed
return 0;
}
void
OEMIdle(
DWORD dwIdleParam
)
{
DWORD dwIdleMSec;
DWORD dwDiffMSecPrev = *pDiffMSec;
static DWORD dwPartialCurMSec = 0; // Keep CPU-specific sub-millisecond leftover.
// Use for 64-bit math
ULARGE_INTEGER currIdle = {
curridlelow,
curridlehigh
};
if (ticksleft) {
// if ticksleft, potentially there are threads on the sleep queue waiting to run, so don't idle
return;
}
if (bProfileTimerRunning) {
// system timer is running at CPU specific profiling value - just call CPUEnterIdle and return
CPUEnterIdle(dwIdleParam);
return;
}
if (dwSleepMin == 0 || fIntrTime) {
//
// No minimum sleep time specified. Wakeup on the normal schedule tick.
//
CPUEnterIdle(dwIdleParam);
// Update global idle time and return
currIdle.QuadPart += SYSTEM_TICK_MS;
curridlelow = currIdle.LowPart;
curridlehigh = currIdle.HighPart;
return;
}
if (dwDiffMSecPrev >= dwSleepMin) {
//
// According to the globals, our sleep time has already passed!
//
return;
}
//
// How many milliseconds until we should wake up again?
//
dwIdleMSec = dwSleepMin - dwDiffMSecPrev;
//
// The system timer may not be capable of arbitrary timeouts. Get the
// CPU-specific highest possible timeout available.
//
dwIdleMSec = CPUGetSysTimerCountMax(dwIdleMSec);
//
// Since OEMIdle( ) is being called in the middle of a normal reschedule
// period, CurMSec, dwPartialCurMSec, dwPartialDiffMSec and CurTicks need to be updated accordingly.
//
CPUGetSysTimerCountElapsed(SYSTEM_TICK_MS, pCurMSec, pDiffMSec, &dwPartialCurMSec, &dwPartialDiffMSec, pCurTicks);
dwDiffMSecPrev = *pDiffMSec;
//
// Set the timer to wake up much later than usual, if needed.
//
CPUSetSysTimerCount(dwIdleMSec);
CPUClearSysTimerIRQ( );
//
// Enable wakeup on any interrupt, then go to sleep.
//
CPUEnterIdle(dwIdleParam);
INTERRUPTS_OFF( );
//
// We're awake! The wake-up ISR has already run.
//
if (dwDiffMSecPrev != *pDiffMSec) {
//
// We completed the full period we asked to sleep. Update the counters.
//
*pCurMSec += (dwIdleMSec - SYSTEM_TICK_MS); // Subtract SYSTEM_TICK_MS, because ISR also incremented.
*pDiffMSec += (dwIdleMSec - SYSTEM_TICK_MS);
CurTicks.QuadPart += (dwIdleMSec - SYSTEM_TICK_MS) * TIMER_COUNT;
currIdle.QuadPart += dwIdleMSec;
} else {
//
// Some other interrupt woke us up before the full idle period was
// complete. Determine how much time has elapsed.
//
currIdle.QuadPart += CPUGetSysTimerCountElapsed(dwIdleMSec, pCurMSec, pDiffMSec, &dwPartialCurMSec, &dwPartialDiffMSec, pCurTicks);
}
CPUSetSysTimerCount(SYSTEM_TICK_MS);
CPUClearSysTimerIRQ( );
// Update global idle time
curridlelow = currIdle.LowPart;
curridlehigh = currIdle.HighPart;
return;
}
#else
// DougFir or later
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DWORD CPUGetSysTimerCountElapsed (
DWORD dwTimerCountdownMSec,
volatile DWORD *pCurMSec,
DWORD *pPartialCurMSec,
volatile ULARGE_INTEGER *pCurTicks
)
{
// Using fixed tick, so do nothing and return 0 time passed
return 0;
}
void
OEMIdle(
DWORD dwIdleParam
)
{
DWORD dwIdleMSec;
DWORD dwPrevMSec = CurMSec;
// Use for 64-bit math
ULARGE_INTEGER currIdle = {
curridlelow,
curridlehigh
};
if ((int) (dwIdleMSec = dwReschedTime - dwPrevMSec) <= 0) {
// already time to wakeup
return;
}
// just idle till tick if profiling or running iltiming
if (bProfileTimerRunning || fIntrTime) {
// idle till end of 'tick'
CPUEnterIdle(dwIdleParam);
// Update global idle time and return
currIdle.QuadPart += SYSTEM_TICK_MS;
curridlelow = currIdle.LowPart;
curridlehigh = currIdle.HighPart;
return;
}
//
// Since OEMIdle( ) is being called in the middle of a normal reschedule
// period, CurMSec, dwPartialCurMSec, and CurTicks need
// to be updated accordingly.
// Once we reach this point, we must re-program the timer (if we ever did)
// because dwPartialCurMSec will be modified in the next function call.
//
CPUGetSysTimerCountElapsed(SYSTEM_TICK_MS, &CurMSec, &dwPartialCurMSec, pCurTicks);
if ((int) (dwIdleMSec -= CurMSec - dwPrevMSec) > 0) {
dwPrevMSec = CurMSec;
//
// The system timer may not be capable of arbitrary timeouts. Get the
// CPU-specific highest possible timeout available.
//
dwIdleMSec = CPUGetSysTimerCountMax(dwIdleMSec);
//
// Set the timer to wake up much later than usual, if needed.
//
CPUSetSysTimerCount(dwIdleMSec);
CPUClearSysTimerIRQ( );
//
// Enable wakeup on any interrupt, then go to sleep.
//
CPUEnterIdle(dwIdleParam);
INTERRUPTS_OFF( );
//
// 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 - SYSTEM_TICK_MS); // Subtract resched period, because ISR also incremented.
CurTicks.QuadPart += (dwIdleMSec - SYSTEM_TICK_MS) * TIMER_COUNT;
currIdle.QuadPart += dwIdleMSec;
} else {
//
// Some other interrupt woke us up before the full idle period was
// complete. Determine how much time has elapsed.
//
currIdle.QuadPart += CPUGetSysTimerCountElapsed(dwIdleMSec, &CurMSec, &dwPartialCurMSec, pCurTicks);
}
}
// Re-arm counters
CPUSetSysTimerCount(SYSTEM_TICK_MS);
CPUClearSysTimerIRQ( );
// Update global idle time
curridlelow = currIdle.LowPart;
curridlehigh = currIdle.HighPart;
return;
}
#endif // CE_MAJOR_VER == 0x0003
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// SC_GetTickCount must take into account the partials to reflect where we really
// are in time AND IT SHOULD NOT MODIFY ANY OF THE GLOBALS.
//
DWORD SC_GetTickCount(void)
{
#if (CE_MAJOR_VER == 0x0003)
return CurMSec;
#else
DWORD dwInc = 0, dwPartial = dwPartialCurMSec;
ULARGE_INTEGER cdummy = {0, 0};
CPUGetSysTimerCountElapsed(SYSTEM_TICK_MS, &dwInc, &dwPartial, &cdummy);
return CurMSec + dwInc;
#endif
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?