📄 timer_vartick.c
字号:
//
// This function is called by the kernel when there are no threads ready to
// run. The CPU should be put into a reduced power mode if possible and halted.
// It is important to be able to resume execution quickly upon receiving an
// interrupt.
//
// Interrupts are disabled when OEMIdle is called and when it returns.
//
// Note that system timer must be running when CPU/SoC is moved to reduced
// power mode.
//
void OEMIdle(DWORD idleParam)
{
UINT32 baseMSec, idleMSec, idleSysTicks;
INT32 usedCounts, idleCounts;
ULARGE_INTEGER idle;
// Get current system timer counter
baseMSec = CurMSec;
// Compute the remaining idle time
idleMSec = dwReschedTime - baseMSec;
// RETAILMSG(1,(TEXT("(%d)"), idleMSec));
// Idle time has expired - we need to return
if ((INT32)idleMSec <= 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 (idleMSec > g_oalTimer.maxPeriodMSec) {
idleMSec = g_oalTimer.maxPeriodMSec;
}
// We can wait only full systick
idleSysTicks = idleMSec/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();
if (usedCounts == g_oalTimer.countsPerSysTick)
{
return;
}
// 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) {
// Extend timer period
OALTimerUpdate(idleCounts-usedCounts, g_oalTimer.countsMargin);
// Update value for timer interrupt which wakeup from idle
g_oalTimer.actualMSecPerSysTick = idleMSec;
g_oalTimer.actualCountsPerSysTick = idleCounts;
}
g_idleMSec = idleMSec;
// 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) {
// If there wasn't timer interrupt we have to update CurMSec&curCounts
if (CurMSec == baseMSec) {
// Return system tick period back to original
idleCounts = OALTimerUpdate(g_oalTimer.countsPerSysTick, g_oalTimer.countsMargin)+usedCounts;
g_idleMSec = g_oalTimer.msecPerSysTick;
// RETAILMSG(1,(TEXT("(%x)"), idleSysTicks));
// Restore original values
g_oalTimer.actualMSecPerSysTick = g_oalTimer.msecPerSysTick;
g_oalTimer.actualCountsPerSysTick = g_oalTimer.countsPerSysTick;
// Fix system tick counters & idle counter
CurMSec += idleCounts/g_oalTimer.countsPerMSec;
//idleCounts = idleSysTicks * g_oalTimer.actualCountsPerSysTick;
g_oalTimer.curCounts += idleCounts;
idleCounts += OALTimerCountsSinceSysTick();
usedCounts = 0;
}
} else {
if (CurMSec == baseMSec) {
// Update actual idle counts, if there wasn't timer interrupt
idleCounts = OALTimerCountsSinceSysTick();
usedCounts = 0;
}
}
// Get real idle value. If result is negative we didn't idle at all.
idleCounts -= usedCounts;
if (idleCounts < 0) idleCounts = 0;
// RETAILMSG(1,(TEXT("(%x, %x)"), idleCounts, (CurMSec - baseMSec)*g_oalTimer.countsPerSysTick));
// Update idle counters
idle.LowPart = curridlelow;
idle.HighPart = curridlehigh;
idle.QuadPart += idleCounts;
curridlelow = idle.LowPart;
curridlehigh = idle.HighPart;
#ifdef DVS_EN
dwCurrentidle = (DWORD)(idle.QuadPart/idleconv);
#endif
}
//------------------------------------------------------------------------------
//
// Function: OALCPUIdle
//
// This Idle function implements a busy idle. It is intend to be used only
// in development (when CPU doesn't support idle mode it is better to stub
// OEMIdle function instead use this busy loop). The busy wait is cleared by
// an interrupt from interrupt handler setting the g_oalLastSysIntr.
//
//
extern void Nop(void);
//extern void MMU_WaitForInterrupt();
VOID OALCPUIdle()
{
volatile S3C2443_CLKPWR_REG *s2443CLKPWR = (S3C2443_CLKPWR_REG *)OALPAtoVA(S3C2443_BASE_REG_PA_CLOCK_POWER, FALSE);
volatile S3C2443_INTR_REG *s2443INT = (S3C2443_INTR_REG *)OALPAtoVA(S3C2443_BASE_REG_PA_INTR, FALSE);
volatile S3C2443_IOPORT_REG *s2443IOPORT = (S3C2443_IOPORT_REG *)OALPAtoVA(S3C2443_BASE_REG_PA_IOPORT, FALSE);
#ifdef DVS_EN
volatile S3C2443_LCD_REG *s2443LCD = (S3C2443_LCD_REG *)OALPAtoVA(S3C2443_BASE_REG_PA_LCD, FALSE);
#if(DVS_METHOD == 1)
{
if ( CurrStateIdle == TRUE )
{
s2443INT->INTSUBMSK |= (1 << IRQ_SUB_LCD3); // masking LCD3 sub interrupt
s2443INT->INTMSK |= (1 << IRQ_LCD); // maksing LCD interrupt
s2443LCD->VIDINTCON &= ~(0x1); // disable LCD interrupt
}
else
{
s2443INT->INTSUBMSK &= ~(1 << IRQ_SUB_LCD3); // unmasking LCD3 sub interrupt
s2443INT->INTMSK &= ~(1 << IRQ_LCD); // unmasking LCD interrupt
s2443LCD->VIDINTCON |= (0x1); // enable LCD interrupt
}
if ( s2443INT->SUBSRCPND & (1 << IRQ_SUB_LCD3) ) s2443INT->SUBSRCPND = (1 << IRQ_SUB_LCD3);
if ( s2443INT->SRCPND & (1 << IRQ_LCD)) s2443INT->SRCPND = (1 << IRQ_LCD);
if ( s2443INT->INTPND & (1 << IRQ_LCD)) s2443INT->INTPND = (1 << IRQ_LCD);
b_oalInterruptFlag = FALSE;
IDLEflag = TRUE;
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT |= ( 1<< 5); // GPF5 output data, turn LED on
#endif
s2443CLKPWR->PWRMODE |= (1 << 17);
// MMU_WaitForInterrupt();
INTERRUPTS_ON();
while (!b_oalInterruptFlag) {}
INTERRUPTS_OFF();
s2443CLKPWR->PWRMODE &= ~(1 << 17);
IDLEflag = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT &= ~(1 << 5); // GPF5 output data, turn LED off
#endif
if ( CurrStateIdle == FALSE ){
s2443INT->INTSUBMSK |= (1 << IRQ_SUB_LCD3); // masking LCD3 sub interrupt
s2443INT->INTMSK |= (1 << IRQ_LCD); // maksing LCD interrupt
s2443LCD->VIDINTCON &= ~(0x1); // disable LCD interrupt
}
else
{
s2443INT->INTSUBMSK &= ~(1 << IRQ_SUB_LCD3); // unmasking LCD3 sub interrupt
s2443INT->INTMSK &= ~(1 << IRQ_LCD); // unmasking LCD interrupt
s2443LCD->VIDINTCON |= (0x1); // enable LCD interrupt
}
if ( s2443INT->SUBSRCPND & (1 << IRQ_SUB_LCD3) )
{
s2443INT->SUBSRCPND = (1 << IRQ_SUB_LCD3);
}
if ( s2443INT->SRCPND & (1 << IRQ_LCD))
{
s2443INT->SRCPND = (1 << IRQ_LCD);
}
if ( s2443INT->INTPND & (1 << IRQ_LCD))
{
s2443INT->INTPND = (1 << IRQ_LCD);
}
}
#elif (DVS_METHOD == 2)
/**
* DVS_ON : Sync FCLK to HCLK
* Change voltage to lower
* set system mode to idle
* Wait for interrupt
* Change voltage to high
* Wait for recovering voltage to high
* DVS_OFF : restore FCLK
*/
// RETAILMSG(1, (TEXT("I")));
DVS_ON(); // FCLK to 133?
g_oalIoCtlClockSpeed = S3C2443_HCLK;
ChangeVoltage(LOWVOLTAGE);
//g_oalLastSysIntr = FALSE;
b_oalInterruptFlag = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT |= ( 1<< 5); // GPF5 output data, turn LED on
#endif
s2443CLKPWR->PWRMODE |= (1 << 17);
// MMU_WaitForInterrupt();
INTERRUPTS_ON();
while (!b_oalInterruptFlag) {}
INTERRUPTS_OFF();
s2443CLKPWR->PWRMODE &= ~(1 << 17);
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT &= ~(1 << 5); // GPF5 output data, turn LED off
#endif
ChangeVoltage(HIGHVOLTAGE);
{
// Voltage Difference : 0.55V needs 100usec --> in 133MHZ, 13300 cycles
volatile int i;
for(i=0;i<VOLTAGEDELAY*2;i++)
{
INREG32(&s2443IOPORT->GPFDAT); // for loop operation, just read.
}
}
DVS_OFF();
g_oalIoCtlClockSpeed = S3C2443_FCLK;
// RETAILMSG(1, (TEXT("O")));
#elif (DVS_METHOD == 3)
if ( CurrentState == Active ) // Active -> Idle
{
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT &= ~(1 << 5); // GPF5 output data, turn LED off
#endif
DVS_ON();
g_oalIoCtlClockSpeed = S3C2443_HCLK;
ChangeVoltage(MIDVOLTAGE);
b_oalInterruptFlag = FALSE;
IDLEflag = TRUE;
// RETAILMSG(1, (TEXT("-I-")));
s2443CLKPWR->PWRMODE |= (1 << 17);
// MMU_WaitForInterrupt();
INTERRUPTS_ON();
while (!b_oalInterruptFlag) {}
INTERRUPTS_OFF();
s2443CLKPWR->PWRMODE &= ~(1 << 17);
IDLEflag = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT |= ( 1<< 5); // GPF5 output data, turn LED on
#endif
}
else if ( CurrentState == SlowActive ) // Slow Active -> Deep Idle
{
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT &= ~(1 << 5); // GPF5 output data, turn LED off
#endif
if ( CurrStateIdle == TRUE )
{
s2443INT->INTSUBMSK |= (1 << IRQ_SUB_LCD3); // masking LCD3 sub interrupt
s2443INT->INTMSK |= (1 << IRQ_LCD); // maksing LCD interrupt
s2443LCD->VIDINTCON &= ~(0x1); // disable LCD interrupt
}
else
{
s2443INT->INTSUBMSK &= ~(1 << IRQ_SUB_LCD3); // unmasking LCD3 sub interrupt
s2443INT->INTMSK &= ~(1 << IRQ_LCD); // unmasking LCD interrupt
s2443LCD->VIDINTCON |= (0x1); // enable LCD interrupt
}
if ( s2443INT->SUBSRCPND & (1 << IRQ_SUB_LCD3) ) s2443INT->SUBSRCPND = (1<<IRQ_SUB_LCD3);
if ( s2443INT->SRCPND & (1 << IRQ_LCD)) s2443INT->SRCPND = (1 << IRQ_LCD);
if ( s2443INT->INTPND & (1 << IRQ_LCD)) s2443INT->INTPND = (1 << IRQ_LCD);
b_oalInterruptFlag = FALSE;
IDLEflag = TRUE;
// RETAILMSG(1, (TEXT("-D-")));
s2443CLKPWR->PWRMODE |= (1 << 17);
// MMU_WaitForInterrupt();
INTERRUPTS_ON();
while (!b_oalInterruptFlag) {}
INTERRUPTS_OFF();
s2443CLKPWR->PWRMODE &= ~(1 << 17);
IDLEflag = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2443IOPORT->GPFDAT |= ( 1<< 5); // GPF5 output data, turn LED on
#endif
if ( s2443INT->SUBSRCPND & (1 << IRQ_SUB_LCD3) ) s2443INT->SUBSRCPND = (1<<IRQ_SUB_LCD3);
if ( s2443INT->SRCPND & (1 << IRQ_LCD)) s2443INT->SRCPND = (1 << IRQ_LCD);
if ( s2443INT->INTPND & (1 << IRQ_LCD)) s2443INT->INTPND = (1 << IRQ_LCD);
if ( CurrStateIdle == FALSE ){
s2443INT->INTSUBMSK |= (1 << IRQ_SUB_LCD3); // masking LCD3 sub interrupt
s2443INT->INTMSK |= (1 << IRQ_LCD); // maksing LCD interrupt
s2443LCD->VIDINTCON &= ~(0x1); // disable LCD interrupt
}
else
{
s2443INT->INTSUBMSK &= ~(1 << IRQ_SUB_LCD3); // unmasking LCD3 sub interrupt
s2443INT->INTMSK &= ~(1 << IRQ_LCD); // unmasking LCD interrupt
s2443LCD->VIDINTCON |= (0x1); // enable LCD interrupt
}
}
#endif //DVS_METHOD
#else
// Clear last SYSINTR global value
//g_oalLastSysIntr = SYSINTR_NOP;
b_oalInterruptFlag = FALSE;
s2443IOPORT->GPFDAT |= ( 1<< 5); // GPF5 output data, turn LED on
s2443CLKPWR->PWRMODE |= (1 << 17);
//MMU_WaitForInterrupt();
INTERRUPTS_ON();
while (!b_oalInterruptFlag) {}
INTERRUPTS_OFF();
s2443CLKPWR->PWRMODE &= ~(1 << 17);
s2443IOPORT->GPFDAT &= ~(1 << 5); // GPF5 output data, turn LED off
#endif //DVS_EN
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -