This function is called by the kernel to place the CPU in the idle state when there are no threads ready to run.
我们以前的做法也不是一旦系统进入IDLE就去调频调压的,而是要等一段时间足够长后才去调整
可以参考一下Intel平台的IPM代码,或者是Samsung平台的DVS代码
The kernel calls OEMIdle whenever there are no threads ready to run. The kernel provides an extern DWORD dwReschedTime value that indicates when the next known event is to occur. Such asynchronous events as user-generated interrupt from a keyboard or mouse can occur before then and need to be handled.
You can find code samples of OEMIdle in %_WINCEROOT%\Platform\Common\Src\Common\Timer\Idle\Idle.c.
When the kernel calls the OEMIdle function, the OEM device is requested to go into a sleep, or idle, state. This consists of saving the current state, placing the memory into a refresh state if necessary, stopping the clock, and suspending execution.
In order to conserve power while continually awakening the target device, OEMIdle should sleep for as long as possible. This is usually until the sooner of two events: dwReschedTime, or the maximum delay supported by the hardware timer.
When an interrupt occurs, scheduled or otherwise, the device ends its idle state, the previous state is restored, and the scheduler is invoked. If no new threads are ready to run, the kernel will again call OEMIdle.
When the system returns from idle, OEMIdle must update the CurMSec variable with the real number of milliseconds that have elapsed. The sample OAL also keeps partial millisecond counts, dwPartialCurMSec, in case another interrupt occurs, which will cause the system to stop idling before the system timer fires.
The following code example shows how to implement OEMIdle with these variables.
void OEMIdle(DWORD idleParam)
{
UINT32 baseMSec;
UINT32 idleTimeMSec;
INT32 idleSysTicks;
INT32 usedCounts;
INT32 idleCounts;
ULARGE_INTEGER idle;
// Get current system timer counter
baseMSec = CurMSec;
// Compute the remaining idle time
idleTimeMSec = dwReschedTime - baseMSec;
// Idle time has expired - we need to return
if ((INT32)idleTimeMSec <= 0) return;
// Limit the maximum idle time to what is supported.
// Counter size is the limiting parameter. When kernel
// profiler or interrupt latency timing is active it is set
// to one system tick.
if (idleTimeMSec > g_oalTimer.maxIdleMSec) {
idleTimeMSec = g_oalTimer.maxIdleMSec;
}
// We can wait only full systick
idleSysTicks = idleTimeMSec/g_oalTimer.msecPerSysTick;
// This is idle time in hi-res ticks
idleCounts = idleSysTicks * g_oalTimer.countsPerSysTick;
// Find how many hi-res ticks was already used
usedCounts = OALTimerCountsSinceSysTick();
// Prolong beat period to idle time -- don't do it idle time isn't
// longer than one system tick. Even if OALTimerExtendSysTick function
// should accept this value it can cause problems if kernel profiler
// or interrupt latency timing is active.
if (idleSysTicks > 1) {
OALTimerExtendSysTick(idleCounts, g_oalTimer.countsMargin, 0);
}
// Move SoC/CPU to idle mode
OALCPUIdle();
// Return system tick period back to original. Don't call when idle
// time was one system tick. See comment above.
if (idleSysTicks > 1) {
// Return system tick period back to original
idleSysTicks = OALTimerReduceSysTick(
g_oalTimer.countsPerSysTick, g_oalTimer.countsMargin
);
// Do we need offset counters?
if (idleSysTicks > 0) {
// Fix system tick counters
CurMSec += idleSysTicks * g_oalTimer.msecPerSysTick;
g_oalTimer.curCounts += idleSysTicks * g_oalTimer.countsPerSysTick;
}
// Get where we are inside tick
idleCounts = OALTimerCountsSinceSysTick();
}
引用 1 楼 hzdysymbol 的回复:
This function is called by the kernel to place the CPU in the idle state when there are no threads ready to run.
我们以前的做法也不是一旦系统进入IDLE就去调频调压的,而是要等一段时间足够长后才去调整
可以参考一下Intel平台的IPM代码,或者是Samsung平台的DVS代码