📄 timer.c
字号:
// Limit the maximum idle time to what is supported.
if (idleSysTicks > g_timer.maxIdleMSec) idleSysTicks = g_timer.maxIdleMSec;
// Find where we are and if interrupt is pending
cnt = INREG32(&pTimerRegs->TCR);
if (OALIntrIsIrqPending(IRQ_TIMER32K)) {
// Full period was used, leave OEMIdle...
usedCounts = TIMER_PERIOD;
idleSysTicks = 1;
} else {
// We already used
usedCounts = TIMER_PERIOD - cnt;
// If there is pending timer update or we are neer to interrupt
// then sleep only until 32K interrupt
if (g_timer.updatePeriod || cnt < TIMER_MARGIN) idleSysTicks = 1;
}
// Prolong timer period to idle time when it is longer than 1ms
if (idleSysTicks > 1) {
// Clear deep sleep flag
deepSleep = FALSE;
// Idle time in hi-res ticks
idleCounts = idleSysTicks << 5;
// New timer period without timer setup compensation
set = idleCounts - usedCounts - 1;
// Wait for timer value change...
do {
while (cnt == INREG32(&pTimerRegs->TCR));
// We have check for interrupt one more time...
cnt = INREG32(&pTimerRegs->TCR);
} while (cnt == TIMER_PERIOD - 1);
// If there is pending interrupt now use short idle...
if (OALIntrIsIrqPending(IRQ_TIMER32K)) {
usedCounts = TIMER_PERIOD;
idleSysTicks = 1;
} else {
// Compensate for timer update delays
set -= SET_COMPENSATION;
usedCounts += SET_COMPENSATION;
// We need to find if OMAP730 will go to deep sleep mode.
if (
g_timer.deepSleep &&
set >= g_timer.deepSleepTreshold &&
(INREG16(&pULPDRegs->STATUS_REQ) ^ 0x0006) == 0 &&
INREG16(&pULPDRegs->STATUS_REQ2) == 0 &&
INREG16(&pULPDRegs->SOFT_REQ) == 0
) {
// Enable deep sleep
SETREG16(&pULPDRegs->POWER_CTRL, POWER_CTRL_DEEP_SLEEP_EN);
// Reduce idle length
set -= g_timer.deepSleepSetup;
// Set deep sleep flag
deepSleep = TRUE;
} else {
// Disable deep sleep
CLRREG16(&pULPDRegs->POWER_CTRL, POWER_CTRL_DEEP_SLEEP_EN);
}
// Set new value
OUTREG32(&pTimerRegs->TVR, set);
SETREG32(&pTimerRegs->CR, CR_TRB);
// Wait while it is set
while ((INREG32(&pTimerRegs->CR) & CR_TRB) != 0);
// Wait until one tick (any timer set in this time is ignored)
while (INREG32(&g_timer.pTimerRegs->TCR) != (set - 2));
}
} else {
idleCounts = TIMER_PERIOD;
}
#if 1
// Show that we are going sleep
OALLED(LED_IDX_IDLE, 1);
// Display clock requests
OALLED(LED_IDX_CLKREQ1, INREG16(&pULPDRegs->STATUS_REQ));
OALLED(LED_IDX_CLKREQ2, INREG16(&pULPDRegs->STATUS_REQ2));
OALLED(LED_IDX_SOFTREQ, INREG16(&pULPDRegs->SOFT_REQ));
OALLED(LED_IDX_DBBSTAT, INREG16(&pULPDRegs->PCC_DBB_STATUS));
OALLED(LED_IDX_ITSTAT, INREG16(&pULPDRegs->PCC_IT_STATUS));
OALLED(LED_IDX_IDLECT1, INREG16(&pCLKMRegs->IDLECT1));
OALLED(LED_IDX_IDLECT2, INREG16(&pCLKMRegs->IDLECT2));
OALLED(LED_IDX_IDLECT3, INREG16(&pCLKMRegs->IDLECT3));
OALLED(LED_IDX_SOFT_DIS_REQ, INREG16(&pULPDRegs->SOFT_DISABLE_REQ));
#endif
// Without following 16 microsecond stall command device hangs
// on retail image without LED debug output. It happens on retail
// tiny kernel image (however with shell&KITL), so it seems to be
// related to sleep itself. MultiICE JTAG isn't able to connect
// to hang device and it doesn't look as hang in timer related
// code (verified by LEDs output added to all timer while
// wait loops).
OALStall(16);
// Move SoC/CPU to idle mode - interrupt are disabled
OALCPUIdle();
#if 1
// Display awake mode
OALLED(LED_IDX_SLEEPSTAT, INREG16(&pULPDRegs->SLEEP_STATUS));
// Hide sleep signal
OALLED(LED_IDX_IDLE, 0);
#endif
// Get current counter value
cnt = INREG32(&pTimerRegs->TCR);
// Was 32K timer modified?
if (idleSysTicks > 1) {
// If we should fall deep sleep but there was only big sleep
// correct idleSysTick value (we wait shorter...)
if (deepSleep) {
set += g_timer.deepSleepSetup >> 5;
if ((INREG16(&pULPDRegs->SLEEP_STATUS) & BIG_SLEEP) != 0) {
idleSysTicks -= g_timer.deepSleepSetup >> 5;
}
}
if (!OALIntrIsIrqPending(IRQ_TIMER32K) && cnt > TIMER_MARGIN) {
// Wait for timer value change...
while (cnt == INREG32(&pTimerRegs->TCR));
// We have recheck pending IRQ
cnt = INREG32(&pTimerRegs->TCR);
if (!OALIntrIsIrqPending(IRQ_TIMER32K)) {
// Update timer period back
counts = usedCounts + set - cnt + 1;
idleSysTicks = counts >> 5;
counts -= idleSysTicks << 5;
set = TIMER_PERIOD - counts - 1;
if (set == 0) set += TIMER_PERIOD - 1;
// Set new value
OUTREG32(&pTimerRegs->TVR, set);
SETREG32(&pTimerRegs->CR, CR_TRB);
// Wait while it is set
while ((INREG32(&pTimerRegs->CR) & CR_TRB) != 0);
// Wait until one tick (any timer set in this time is ignored)
while (INREG32(&pTimerRegs->TCR) != set);
while (INREG32(&pTimerRegs->TCR) >= set);
} else {
// Interrupt handler will add final one tick to clock
idleSysTicks--;
}
} else {
// Interrupt handler will add final one tick to clock
idleSysTicks--;
}
// There must be period update
g_timer.updatePeriod = TRUE;
// Fix system tick counters & idle counter
idleCounts = idleSysTicks << 5;
g_timer.curCounts += idleCounts;
CurMSec = (UINT32)((g_timer.curCounts * 1000) >> 15);
} else if (!OALIntrIsIrqPending(IRQ_TIMER32K)) {
// Fix idle count to get better idle time
idleCounts -= cnt;
}
// Get real idle value. If result is negative we didn't idle at all.
idleCounts -= usedCounts;
if (idleCounts < 0) idleCounts = 0;
// Update idle counters
idle.LowPart = curridlelow;
idle.HighPart = curridlehigh;
idle.QuadPart += idleCounts * 1000;
curridlelow = idle.LowPart;
curridlehigh = idle.HighPart;
}
//------------------------------------------------------------------------------
//
// Function: SC_GetTickCount
//
// This returns the number of milliseconds that have elapsed since Windows
// CE was started. If the system timer period is 1ms the function simply
// returns the value of CurMSec. If the system timer period is greater then
// 1 ms, the HiRes offset is added to the value of CurMSec.
//
UINT32 SC_GetTickCount()
{
return CurMSec;
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalSetDeepSleepMode
//
// This function is called from internal bus driver to enable/disable
// deep sleep mode.
//
BOOL OALIoCtlHalSetDeepSleepMode(
UINT32 code, VOID *pInBuffer, UINT32 inSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize
) {
BOOL rc = FALSE;
// Check buffer size
if (pInBuffer == NULL || inSize < sizeof(BOOL)) {
NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
OALMSG(OAL_WARN, (L"WARN: OALIoCtlHalSetDeepSleepMode: "
L"Buffer too small\r\n"
));
goto cleanUp;
}
// Set new value
g_timer.deepSleep = *(BOOL*)pInBuffer;
// Done
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -