⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ktimer.c

📁 Wince4.2 BSP for SH4 engineering development board
💻 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 + -