📄 timer.c
字号:
//------------------------------------------------------------------------------
//
// 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.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Freescale Semiconductor, Inc. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// FREESCALE SEMICONDUCTOR, INC.
//
//------------------------------------------------------------------------------
//
// Module: timer.c
//
// Interface to OAL timer services.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <oal.h>
#include "mxarm11.h"
//------------------------------------------------------------------------------
// External Functions
extern UINT32 OALTimerGetClkSrc(void);
extern UINT32 OALTimerGetClkPrescalar(void);
//------------------------------------------------------------------------------
// Defines
#define EPIT_MAX_PERIOD 0x10000000
//------------------------------------------------------------------------------
// Local Variables
PCSP_EPIT_REG g_pEPIT;
static UINT32 g_BaseTimerCount;
//------------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
//
// Function: OALTimerInit
//
// This function is typically called from the OEMInit to initialize
// Windows CE system timer. This implementation uses the SoC EPIT1
// for a system timer.
//
// Parameters:
// msecPerSysTick
// [in] Defines the system-tick period in msec.
//
// countsPerMSec
// [in] States the timer input clock frequency. The value is equal to
// the frequency divided by 1000.
//
// countsMargin
// [in] Used in the timer manipulation routines
// to define a safe time range in raw timer ticks where the timer
// can be modified without errors.
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL OALTimerInit(UINT32 msecPerSysTick, UINT32 countsPerMSec,
UINT32 countsMargin)
{
BOOL rc = FALSE;
UINT32 countsPerSysTick;
UINT32 irq, sysIntr;
OALMSG(OAL_TIMER&&OAL_FUNC, (
L"+OALTimerInit( %d, %d, %d )\r\n",
msecPerSysTick, countsPerMSec, countsMargin
));
// Validate Input parameters
countsPerSysTick = countsPerMSec * msecPerSysTick;
if (msecPerSysTick < 1 || msecPerSysTick > 1000 ||
countsPerSysTick < 1 || countsPerSysTick > EPIT_CNT_COUNT_MAX)
{
OALMSG(OAL_ERROR, (
L"ERROR: OALTimerInit: System tick period out of range..."
));
goto cleanUp;
}
// Initialize timer state global variables
g_oalTimer.msecPerSysTick = msecPerSysTick;
g_oalTimer.actualMSecPerSysTick = msecPerSysTick;
g_oalTimer.countsPerMSec = countsPerMSec;
g_oalTimer.countsMargin = countsMargin;
g_oalTimer.countsPerSysTick = countsPerSysTick;
g_oalTimer.actualCountsPerSysTick = countsPerSysTick;
g_oalTimer.curCounts = 0;
g_oalTimer.maxPeriodMSec = ((UINT32) EPIT_MAX_PERIOD)/g_oalTimer.countsPerMSec;
// g_oalTimer.maxPeriodMSec = 1;
// Set kernel exported globals to initial values
idleconv = countsPerMSec;
curridlehigh = 0;
curridlelow = 0;
// Initialize high resolution timer function pointers
pQueryPerformanceFrequency = OALTimerQueryPerformanceFrequency;
pQueryPerformanceCounter = OALTimerQueryPerformanceCounter;
// Request IRQ to SYSINTR mapping
irq = IRQ_EPIT1;
sysIntr = OALIntrRequestSysIntr(1, &irq, OAL_INTR_FORCE_STATIC);
// Make sure we have a valid sysIntr
if (sysIntr == SYSINTR_UNDEFINED)
{
OALMSG(OAL_ERROR, (L"+OALTimerInit: SYSINTR_UNDEFINED\r\n"));
goto cleanUp;
}
// Get uncached virtual addresses for system timer
g_pEPIT = (PCSP_EPIT_REG) OALPAtoUA(CSP_BASE_REG_PA_EPIT1);
if (g_pEPIT == NULL)
{
OALMSG(OAL_ERROR, (L"+OALTimerInit: EPIT1 null pointer!\r\n"));
goto cleanUp;
}
// Disable EPIT and clear all configuration bits
OUTREG32(&g_pEPIT->CR, 0);
// Assert software reset for the timer
OUTREG32(&g_pEPIT->CR, CSP_BITFMASK(EPIT_CR_SWR));
// Wait for the software reset to complete
while (INREG32(&g_pEPIT->CR) & CSP_BITFMASK(EPIT_CR_SWR));
// Enable timer for "free-running" mode where timer rolls
// over from 0x00000000 to 0xFFFFFFFF
OUTREG32(&g_pEPIT->CR,
CSP_BITFVAL(EPIT_CR_EN, EPIT_CR_EN_ENABLE) |
CSP_BITFVAL(EPIT_CR_ENMOD, EPIT_CR_ENMOD_RESUME) |
CSP_BITFVAL(EPIT_CR_OCIEN, EPIT_CR_OCIEN_ENABLE) |
CSP_BITFVAL(EPIT_CR_RLD, EPIT_CR_RLD_ROLLOVER) |
CSP_BITFVAL(EPIT_CR_PRESCALAR, OALTimerGetClkPrescalar()) |
CSP_BITFVAL(EPIT_CR_SWR, EPIT_CR_SWR_NORESET) |
CSP_BITFVAL(EPIT_CR_IOVW, EPIT_CR_IOVW_NOOVR) |
CSP_BITFVAL(EPIT_CR_DBGEN, EPIT_CR_DBGEN_ACTIVE) |
CSP_BITFVAL(EPIT_CR_WAITEN, EPIT_CR_WAITEN_ENABLE) |
CSP_BITFVAL(EPIT_CR_DOZEN, EPIT_CR_DOZEN_ENABLE) |
CSP_BITFVAL(EPIT_CR_STOPEN, EPIT_CR_STOPEN_ENABLE) |
CSP_BITFVAL(EPIT_CR_OM, EPIT_CR_OM_DICONNECT) |
CSP_BITFVAL(EPIT_CR_CLKSRC, OALTimerGetClkSrc()));
// Initialize timer global for calculating counts since last system tick
g_BaseTimerCount = INREG32(&g_pEPIT->CNT);
// Configure the compare register to generate an interrupt when
// the EPIT ticks for the desired system tick have expired
OALTimerSetCompare(g_BaseTimerCount - countsPerSysTick);
// Enable system tick interrupt
if (!OEMInterruptEnable(sysIntr, NULL, 0)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALTimerInit: Interrupt enable for system timer failed"
));
goto cleanUp;
}
//
// Define ENABLE_WATCH_DOG to enable watchdog timer support.
// NOTE: When watchdog is enabled, the device will reset itself if watchdog timer is not refreshed within ~4.5 second.
// Therefore it should not be enabled when kernel debugger is connected, as the watchdog timer will not be refreshed.
//
#ifdef ENABLE_WATCH_DOG
{
extern void InitWatchDogTimer (void);
InitWatchDogTimer ();
}
#endif
// Done
rc = TRUE;
cleanUp:
OALMSG(OAL_TIMER && OAL_FUNC, (L"-OALTimerInit(rc = %d)\r\n", rc));
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: OALTimerIntrHandler
//
// This function implements the timer interrupt handler. It is called from
// the common ARM interrupt handler.
//
// Parameters:
// None.
//
// Returns:
// SYSINTR value from the interrupt handler
//
//-----------------------------------------------------------------------------
UINT32 OALTimerIntrHandler()
{
UINT32 sysIntr = SYSINTR_NOP;
#ifdef OAL_ILTIMING
if (g_oalILT.active) {
if (--g_oalILT.counter == 0) {
sysIntr = SYSINTR_TIMING;
g_oalILT.counter = g_oalILT.counterSet;
g_oalILT.isrTime2 = OALTimerCountsSinceSysTick();
}
}
#endif
// Update timer globals
g_oalTimer.curCounts += g_oalTimer.countsPerSysTick;
CurMSec += g_oalTimer.msecPerSysTick;
// Advance to next system tick
OALTimerRecharge(g_oalTimer.countsPerSysTick, g_oalTimer.countsMargin);
// Reschedule?
if ((int)(CurMSec - dwReschedTime) >= 0) sysIntr = SYSINTR_RESCHED;
return sysIntr;
}
//-----------------------------------------------------------------------------
//
// Function: OALTimerCountsSinceSysTick
//
// This function returns the time that has expired since the current
// system tick.
//
// Parameters:
// None.
//
// Returns:
// Raw clock ticks since last system tick.
//
//-----------------------------------------------------------------------------
INT32 OALTimerCountsSinceSysTick()
{
// Time difference since last system tick can be measured by
// calculating the delta between timer starting point for the
// current system tick and the current timer value
return g_oalTimer.countsPerSysTick - (INREG32(&g_pEPIT->CNT) - INREG32(&g_pEPIT->CMPR));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -