📄 ktimer.c
字号:
//
// Copyright (c) Renesas Technology Corp. 2002-2003 All Rights Reserved.
//
// OEM Adaptation Layer
//
//----------------------------------------------------------------------------
//
// FILE : ktimer.c
// CREATED : 2002.1.31
// MODIFIED : 2003.08.06
// AUTHOR : Renesas Technology Corp.
// HARDWARE : RENESAS HS7751RSTC01H (S1-E, ITS-DS5)
// TARGET OS : Microsoft(R) Windows(R) CE .NET 4.2
// NOTES :
// FUNCTION : SH7751R kernel timer functions.
// HISTORY :
// 2002.01.31
// - Modified ASPEN for Hitachi HS7751RSTC01H (S1-E, ITS-DS5)
// 2002.09.27
// - Released for Hitachi HS7751RSTC01H (S1-E, ITS-DS5)
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <windows.h>
#include <nkintr.h>
#include <bldver.h> //P00001
#include "shx.h"
#include "s1e.h"
extern DWORD InterruptTable[];
// Begin ////////////////////////////////////////////////////////////// P00001
//extern volatile DWORD CurMSec;
//extern volatile DWORD DiffMSec;
//static volatile DWORD * pCurMSec = &CurMSec;
//static volatile DWORD * pDiffMSec = &DiffMSec;
// End //////////////////////////////////////////////////////////////// P00001
DWORD dwReschedIncrement;
DWORD OEMCount1ms;
extern DWORD dwSleepMin;
extern BOOL fIntrTime;
volatile DWORD dwPerfCountHigh;
void InitClock(void) {
extern void ASM_Timer0ISR(void);
extern void ASM_Timer2ISR(void);
extern BYTE IntrPrio[];
// Number of timer counts for reschedule interval
dwReschedIncrement = ((RESCHED_PERIOD * OEMClockFreq) / 1000);
// Set OEM timer count for 1 ms
OEMCount1ms = OEMClockFreq / 1000;
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)ASM_Timer0ISR;
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)
//
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 16
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)ASM_Timer2ISR;
}
/*
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
OEMProfileTimerDisable(void)
{
//
// Disable the profiling interrupts
//
WRITE_REGISTER_USHORT(TMU_TCR2, TMU_TCR_D16);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void OEMProfileTimerEnable(DWORD dwUSec)
{
DWORD dwCountVal;
if (dwUSec) {
//
// Rate specified (may need to be limited)
//
if (dwUSec < 20) {
dwUSec = 20;
}
} else {
//
// Use default rate (100 uS)
//
dwUSec = 100;
}
dwCountVal = (dwUSec * dwReschedIncrement) / 1000;
RETAILMSG(1, (TEXT("Starting profile timer at %d uS rate\r\n"), dwUSec));
//
// Enable the profiling interrupts
//
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) & ~TMU_TSTR_STR2); // make sure timer2 is stopped
WRITE_REGISTER_ULONG(TMU_TCOR2, dwCountVal); // set timer constant register
WRITE_REGISTER_ULONG(TMU_TCNT2, dwCountVal); // initialize the counter
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) | TMU_TSTR_STR2); // startup timer2
WRITE_REGISTER_USHORT(TMU_TCR2, TMU_TCR_UNIE | TMU_TCR_D16);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
*/
#pragma optimize("", off)
DWORD
PerfCountSinceTick()
{
DWORD dwTCR0 = READ_REGISTER_USHORT(TMU_TCR0);
DWORD dwReschedTime = READ_REGISTER_ULONG(TMU_TCOR0);
DWORD dwCount = READ_REGISTER_ULONG(TMU_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;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
CPUSetSysTimerCount(
DWORD dwCountdownMSec
)
{
DWORD dwCount = OEMCount1ms * dwCountdownMSec;
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR)&(~TMU_TSTR_STR0)); // need to halt timer
WRITE_REGISTER_ULONG(TMU_TCOR0, dwCount); // set timer constant register
WRITE_REGISTER_ULONG(TMU_TCNT0, dwCount); // initialize the counter
WRITE_REGISTER_UCHAR(TMU_TSTR, READ_REGISTER_UCHAR(TMU_TSTR) | TMU_TSTR_STR0); // restart timer
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
CPUClearSysTimerIRQ(
void
)
{
if (!(READ_REGISTER_USHORT(TMU_TCR0) & TMU_TCR_UNF)) {
return FALSE;
}
// clear out pending interrupts
do {
WRITE_REGISTER_USHORT(TMU_TCR0, READ_REGISTER_USHORT(TMU_TCR0) & ~TMU_TCR_UNF);
} while (READ_REGISTER_USHORT(TMU_TCR0) & TMU_TCR_UNF);
return TRUE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Begin ////////////////////////////////////////////////////////////// P00001
#if (CE_MAJOR_VER == 0x0003)
//
// cedar
//
// End //////////////////////////////////////////////////////////////// P00001
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);
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;
}
// Begin ////////////////////////////////////////////////////////////// P00001
#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 = TMUADDR->tcnt0;
dwCount = READ_REGISTER_ULONG(TMU_TCNT0);//P00001
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
// End //////////////////////////////////////////////////////////////// P00001
#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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -