📄 timer.c
字号:
if (period == 0) {
// Period is zero, let interrupt occurs asap
rc = 0;
g_timer.compare = edge;
OALTimerSetCount(g_timer.compare);
} else if ((INT32)(g_timer.compare - edge) > 0) {
// We are more than margin before actual compare, update period
offset = count - g_timer.base;
// Avoid divide/multiply for most cases
if ((INT32)(offset - period) <= 0) {
rc = 0;
} else {
rc = offset/period;
g_timer.base += rc * period;
}
// New compare value is base plus period
g_timer.compare = g_timer.base + period;
// Are we more than margin before new compare?
if ((INT32)(g_timer.compare - edge) > 0) {
// Yes, then use calculated value
OALTimerSetCompare(g_timer.compare);
} else {
// No, shift real compare value
OALTimerSetCompare(edge);
}
} else {
// No, stay with original period
rc = (g_timer.compare - g_timer.base)/period - 1;
}
return rc;
*/
}
//------------------------------------------------------------------------------
//
// Function: OEMIdle
//
// 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;
volatile S3C2413_IOPORT_REG *s2413IOP = (S3C2413_IOPORT_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_IOPORT, FALSE);
while (s2413IOP->GSTATUS4 == 0x2bed); // for avoiding collision with sleep mode
s2413IOP->GSTATUS4 = 0x1d1e;
// 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();
// RETAILMSG(1,(TEXT("(%x, %x)"), idleCounts, usedCounts));
if (idleCounts == usedCounts)
{
//RETAILMSG(1,(TEXT("(%x, %x)"), idleCounts, usedCounts));
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
idleSysTicks = OALTimerUpdate(g_oalTimer.countsPerSysTick, g_oalTimer.countsMargin);
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 += idleSysTicks * g_oalTimer.actualMSecPerSysTick;
idleCounts = idleSysTicks * g_oalTimer.actualCountsPerSysTick;
g_oalTimer.curCounts += idleCounts;
idleCounts += OALTimerCountsSinceSysTick();
}
} else {
if (CurMSec == baseMSec) {
// Update actual idle counts, if there wasn't timer interrupt
idleCounts = OALTimerCountsSinceSysTick();
// RETAILMSG(1,(TEXT("(%x)"), idleCounts));
}
}
// 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;
s2413IOP->GSTATUS4 = 0;
#ifdef DVS_EN
dwCurrentidle = (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.
//
// LED status on/off for IDLE action.
#define IDLELED_ACTIVATE TRUE
extern void Nop(void);
extern void MMU_WaitForInterrupt();
VOID OALCPUIdle()
{
S3C2413_IOPORT_REG *s2413IOPORT = (S3C2413_IOPORT_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_IOPORT, FALSE);
S3C2413_CLKPWR_REG *s2413CLKPWR = (S3C2413_CLKPWR_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_CLOCK_POWER, FALSE);
S3C2413_INTR_REG *s2413INTR= (S3C2413_INTR_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_INTR, FALSE);
int i=0;
#ifdef DVS_EN
S3C2413_LCD_REG *pLCD = (S3C2413_LCD_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_LCD, FALSE);
#if(DVS_METHOD == 1)
{
if ( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
if ( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
if ( s2413INTR->SRCPND & (1 << IRQ_LCD )) s2413INTR->SRCPND = 1 << IRQ_LCD;
if ( s2413INTR->INTPND & (1 << IRQ_LCD )) s2413INTR->INTPND = 1 << IRQ_LCD;
s2413INTR->INTMSK &= ~(1 << IRQ_LCD); // enable LCD interrupt
if ( CurrStateIdle == TRUE )
s2413INTR->INTMSK |= (1 << IRQ_LCD); // disable LCD interrupt
IDLEflag = TRUE;
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
#endif
s2413CLKPWR->PWRCFG &=~(3<<6); // clear bit for bit remained after sleep
s2413CLKPWR->PWRCFG |=(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
MMU_WaitForInterrupt();
s2413CLKPWR->PWRCFG &= ~(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
OALTimerIntrHandler();
//IDLEflag = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
#endif
if ( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
if ( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
if ( s2413INTR->SRCPND & (1 << IRQ_LCD) ) s2413INTR->SRCPND = ( 1 << IRQ_LCD );
if ( s2413INTR->INTPND & (1 << IRQ_LCD) ) s2413INTR->INTPND = ( 1 << IRQ_LCD );
s2413INTR->INTMSK &= ~(1 << IRQ_LCD); // enable LCD interrupt
if ( CurrStateIdle == FALSE )
s2413INTR->INTMSK |= (1 << IRQ_LCD); // disable LCD interrupt
}
#elif (DVS_METHOD == 2)
{
//RETAILMSG(1, (TEXT("-2-")));
#if 1
DVS_ON();
g_oalIoCtlClockSpeed = S3C2413_HCLK;
ChangeVoltage(MIDVOLTAGE);
//g_oalLastSysIntr = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
#endif
s2413CLKPWR->PWRCFG &=~(3<<6); // clear bit for bit remained after sleep
s2413CLKPWR->PWRCFG |=(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
MMU_WaitForInterrupt();
s2413CLKPWR->PWRCFG &= ~(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
#endif
ChangeVoltage(HIGHVOLTAGE);
for(i=0;i<VOLTAGEDELAY;i++)
{
INREG32(&s2413IOPORT->GPFDAT); // for loop operation, just read.
}
DVS_OFF();
if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
OALTimerIntrHandler();
s2413IOPORT->GPFDAT |= (1 << 5);
g_oalIoCtlClockSpeed = S3C2413_FCLK;
#endif
}
#elif (DVS_METHOD == 3)
if ( CurrentState == Active ) // Active -> Idle
{
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
#endif
// DVS_ON();
// g_oalIoCtlClockSpeed = S3C2413_HCLK;
// ChangeVoltage(MIDVOLTAGE);
IDLEflag = TRUE;
s2413CLKPWR->PWRCFG &=~(3<<6); // clear bit for bit remained after sleep
s2413CLKPWR->PWRCFG |=(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
MMU_WaitForInterrupt();
s2413CLKPWR->PWRCFG &= ~(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
OALTimerIntrHandler();
//IDLEflag = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
#endif
}
else if ( CurrentState == SlowActive ) // Slow Active -> Deep Idle
{
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
#endif
if( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
if( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
if( s2413INTR->SRCPND & (1 << IRQ_LCD) ) s2413INTR->SRCPND = ( 1 << IRQ_LCD );
if( s2413INTR->INTPND & (1 << IRQ_LCD) ) s2413INTR->INTPND = ( 1 << IRQ_LCD );
s2413INTR->INTMSK &= ~(1 << IRQ_LCD); // enable LCD interrupt
if ( CurrStateIdle == TRUE ) s2413INTR->INTMSK |= (1 << IRQ_LCD); // disable LCD interrupt
IDLEflag = TRUE;
// RETAILMSG(1, (TEXT("-D-")));
s2413CLKPWR->PWRCFG &=~(3<<6); // clear bit for bit remained after sleep
s2413CLKPWR->PWRCFG |=(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
MMU_WaitForInterrupt();
s2413CLKPWR->PWRCFG &= ~(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
OALTimerIntrHandler();
//IDLEflag = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
#endif
if( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
if( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
if( s2413INTR->SRCPND & (1 << IRQ_LCD) ) s2413INTR->SRCPND = ( 1 << IRQ_LCD );
if( s2413INTR->INTPND & (1 << IRQ_LCD) ) s2413INTR->INTPND = ( 1 << IRQ_LCD );
s2413INTR->INTMSK &= ~(1 << IRQ_LCD); // enable LCD interrupt
if ( CurrStateIdle == FALSE ) s2413INTR->INTMSK |= (1 << IRQ_LCD); // disable LCD interrupt
}
else
{
}
#endif //DVS_METHOD
#else
//g_oalLastSysIntr = FALSE;
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
#endif
s2413CLKPWR->PWRCFG &=~(3<<6); // clear bit for bit remained after sleep
s2413CLKPWR->PWRCFG |=(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
MMU_WaitForInterrupt();
s2413CLKPWR->PWRCFG &= ~(1<<6); //STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode
if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
OALTimerIntrHandler();
#if IDLELED_ACTIVATE==TRUE
s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
#endif
#endif //DVS_EN
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -