ktimer.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 298 行
C
298 行
//------------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
//
// Module Name:
//
// ktimer.c
//
// Abstract:
//
// SH3 kernel timer functions.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <bldver.h>
#include "sh4.h"
#include "timer.h"
//#include <aspen.h>
#include <platform.h>
extern DWORD InterruptTable[];
DWORD dwReschedIncrement;
DWORD OEMCount1ms;
extern DWORD dwSleepMin;
extern BOOL fIntrTime;
volatile DWORD dwPerfCountHigh;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void InitClock(void)
{
extern void Timer0ISR(void);
extern void Timer2ISR(void);
extern BYTE IntrPrio[];
// Number of timer counts for reschedule interval
dwReschedIncrement = RESCHED_INCREMENT;
// Set OEM timer count for 1 ms
OEMCount1ms = OEM_COUNT_1MS;
// Set OEM clock frequency
OEMClockFreq = OEM_CLOCK_FREQ;
// TMUADDR->tstr &= ~TMU_START0; // make sure timer0 is stopped
// TMUADDR->tcr0 = TMUCR_UNIE | TMUCR_D16; // interrupt enable, divide by 16
// TMUADDR->tcor0 = dwReschedIncrement; // set timer constant register
// TMUADDR->tcnt0 = dwReschedIncrement; // initialize the counter
// INTC_PRA = (INTC_PRA&0x0FFF) | 0x1000; // priority 1 interrupt
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR)&(~TMU_TSTR_STR0));
WRITE_REGISTER_USHORT(TMU_TCR0, TMU_TCR_UNIE | TMU_TCR_D16); // interrupt enable, divide by 16
WRITE_REGISTER_ULONG(TMU_TCOR0, dwReschedIncrement); // set timer constant register
WRITE_REGISTER_ULONG(TMU_TCNT0, dwReschedIncrement); // initialize the counter
WRITE_REGISTER_USHORT(INTC_IPRA,
READ_REGISTER_USHORT(INTC_IPRA)&(INTC_IPRA_TMU0_MASK) | INTC_IPRA_TMU0_INT); // priority 1 interrupt
IntrPrio[16] = 1;
InterruptTable[16] = (DWORD)Timer0ISR;
// TMUADDR->tstr |= TMU_START0; // startup timer0
// TMUADDR->tstr &= ~TMU_START1; // make sure timer1 is stopped
// TMUADDR->tcr1 = TMUCR_D4; // interrupt disable, divide by 4
// TMUADDR->tcor1 = 0xffffffff; // set timer constant register
// TMUADDR->tcnt1 = 0xffffffff; // initialize the counter
// TMUADDR->tstr |= TMU_START1; // startup timer1
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) | TMU_TSTR_STR0); // startup timer0
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) & ~TMU_TSTR_STR1); // make sure timer1 is stopped
WRITE_REGISTER_USHORT(TMU_TCR1, TMU_TCR_D4); // interrupt disable, divide by 4
WRITE_REGISTER_ULONG(TMU_TCOR1, 0xffffffff); // set timer constant register
WRITE_REGISTER_ULONG(TMU_TCNT1, 0xffffffff); // initialize the counter
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) | TMU_TSTR_STR1); // startup timer1
//
// Use timer 2 for QueryPerformanceCounter (not used)
//
// TMUADDR->tstr &= ~TMU_START2; // make sure timer2 is stopped
// TMUADDR->tcr2 = TMUCR_D16; // interrupt disable, divide by 16
// TMUADDR->tcor2 = 0xffffffff; // set timer constant register
// TMUADDR->tcnt2 = 0xffffffff; // initialize the counter
// INTC_PRA = (INTC_PRA&0xFF0F) | 0x0010; // priority 1 interrupt
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) & ~TMU_TSTR_STR2); // make sure timer2 is stopped
WRITE_REGISTER_USHORT(TMU_TCR2, TMU_TCR_D16); // interrupt disable, divide by 4
WRITE_REGISTER_ULONG(TMU_TCOR2, 0xffffffff); // set timer constant register
WRITE_REGISTER_ULONG(TMU_TCNT2, 0xffffffff); // initialize the counter
WRITE_REGISTER_USHORT(INTC_IPRA,
READ_REGISTER_USHORT(INTC_IPRA)&(INTC_IPRA_TMU2_MASK) | INTC_IPRA_TMU2_INT); // priority 1 interrupt
IntrPrio[18] = 1;
InterruptTable[18] = (DWORD)Timer2ISR;
//TMUADDR->tstr |= TMU_START2; // startup timer2
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#pragma optimize("", off)
DWORD
PerfCountSinceTick()
{
DWORD dwTCR0 = READ_REGISTER_USHORT(TMU_TCR0);//TMUADDR->tcr0;
DWORD dwReschedTime =READ_REGISTER_ULONG(TMU_TCOR0); //TMUADDR->tcor0;
DWORD dwCount = READ_REGISTER_ULONG(TMU_TCNT0);//TMUADDR->tcnt0;
if (dwCount > dwReschedTime) {
// This is an error case. Recover gracefully.
DEBUGMSG(1, (L"PerfCountSinceTick( ): Correcting periodic timer read error\r\n"));
return 0;
}
// Note : this is a countdown timer, not count up.
if (dwTCR0 & TMU_TCR_UNF) {
// Rollover case with interrupt pending
return dwReschedTime + (dwReschedTime - dwCount);
} else {
return dwReschedTime - dwCount;
}
}
#pragma optimize("", on)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DWORD
PerfCountFreq()
{
return OEMClockFreq;
}
extern DWORD CurMSec;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
CPUSetSysTimerCount(
DWORD dwCountdownMSec
)
{
DWORD dwCount = OEMCount1ms * dwCountdownMSec;
// TMUADDR->tstr &= ~TMU_START0; // need to halt timer
// TMUADDR->tcor0 = dwCount; // set timer constant register
// TMUADDR->tcnt0 = dwCount; // initialize the counter
// TMUADDR->tstr |= TMU_START0; // restart timer
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR)&(~TMU_TSTR_STR0));
WRITE_REGISTER_ULONG(TMU_TCOR0, dwCount);
WRITE_REGISTER_ULONG(TMU_TCNT0, dwCount);
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) | TMU_TSTR_STR0);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
CPUClearSysTimerIRQ(
void
)
{
if (!(READ_REGISTER_USHORT(TMU_TCR0) & TMU_TCR_UNF)) { // if (!(TMUADDR->tcr0 & TMUCR_UNF)) {
return FALSE;
}
// clear out pending interrupts
do {
WRITE_REGISTER_USHORT(TMU_TCR0, READ_REGISTER_USHORT(TMU_TCR0) & (~TMU_TCR_UNF)); // TMUADDR->tcr0 &= ~TMUCR_UNF;
} while (READ_REGISTER_USHORT(TMU_TCR0) & TMU_TCR_UNF);//(TMUADDR->tcr0 & TMUCR_UNF);
return TRUE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#if (CE_MAJOR_VER == 0x0003)
//
// cedar
//
DWORD
CPUGetSysTimerCountElapsed(
DWORD dwTimerCountdownMSec,
volatile DWORD *pCurMSec,
volatile DWORD *pDiffMSec,
DWORD *pPartialCurMSec,
DWORD *pPartialDiffMSec,
volatile ULARGE_INTEGER *pCurTicks
)
{
DWORD dwTick = dwTimerCountdownMSec * OEMCount1ms;
DWORD dwCount, dwTemp;
// If timer IRQ pending, a full resched period elapsed
if (CPUClearSysTimerIRQ( )) {
*pCurMSec += dwTimerCountdownMSec;
*pDiffMSec += dwTimerCountdownMSec;
pCurTicks->QuadPart += dwTick;
return dwTimerCountdownMSec;
}
// No timer IRQ pending, calculate how much time has elapsed
dwCount = READ_REGISTER_ULONG(TMU_TCNT0);//TMUADDR->tcnt0;
if (dwCount > dwTick) {
// This is an error case. Recover gracefully.
DEBUGMSG(1, (L"CPUGetSysTimerCountElapsed( ): Correcting periodic timer read error\r\n"));
dwCount = dwTick;
} else {
dwCount = dwTick - dwCount;
}
pCurTicks->QuadPart += dwCount;
dwTemp = dwCount;
dwTemp += *pPartialDiffMSec;
*pPartialDiffMSec = dwTemp % OEMCount1ms;
*pDiffMSec += dwTemp / OEMCount1ms;
dwTemp = dwCount;
dwTemp += *pPartialCurMSec;
*pPartialCurMSec = dwTemp % OEMCount1ms;
dwTemp = dwTemp / OEMCount1ms;
*pCurMSec += dwTemp;
return dwTemp;
}
#else
//
// dougfir or later
//
DWORD
CPUGetSysTimerCountElapsed(
DWORD dwTimerCountdownMSec,
volatile DWORD *pCurMSec,
DWORD *pPartialCurMSec,
volatile ULARGE_INTEGER *pCurTicks
)
{
DWORD dwTick = dwTimerCountdownMSec * OEMCount1ms;
DWORD dwCount;
// If timer IRQ pending, a full resched period elapsed
if (CPUClearSysTimerIRQ( )) {
*pCurMSec += dwTimerCountdownMSec;
pCurTicks->QuadPart += dwTick;
return dwTimerCountdownMSec;
}
// No timer IRQ pending, calculate how much time has elapsed
dwCount = READ_REGISTER_ULONG(TMU_TCNT0);//TMUADDR->tcnt0;
if (dwCount > dwTick) {
// This is an error case. Recover gracefully.
DEBUGMSG(1, (L"CPUGetSysTimerCountElapsed( ): Correcting periodic timer read error\r\n"));
dwCount = dwTick;
} else {
dwCount = dwTick - dwCount;
}
pCurTicks->QuadPart += dwCount;
dwCount += *pPartialCurMSec;
*pPartialCurMSec = dwCount % OEMCount1ms;
*pCurMSec += (dwCount /= OEMCount1ms);
return dwCount;
}
#endif
#define IDLE_MAX_MS 30000
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?