📄 ep860timer.c
字号:
/* ppc860Timer.c - PowerPC/860 timer library */
/* Copyright 1984-2001 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
02a,11nov03,gad Modified to use EPCFG structure
01d,22dec01,g_h Remove compilation warning
01c,09oct01,dtr Removing unwanted NULLs(funcptrs) when int required.
Also put in fix for SPR65678.
01b,15sep01,dat Use new vxDecReload function
01a,11nov97,map written from ppcDecTimer.c (v 01n), and m68360Timer.c (v 01f).
*/
/*
DESCRIPTION
This library provides PowerPC/860 system clock, auxiliary clock, and timestamp
support.
The PowerPC decrementer timer, is used to implement a system clock, and CPM
TIMER2 for a 16-bit auxiliary clock. CPM timers TIMER3, and TIMER4
are cascaded into a free-running 32-bit timer for timestamp support.
The macro, DEC_CLOCK_FREQ, the frequency of the decrementer input clock, must
be defined before using this module. The macro, DEC_CLK_TO_INC, the ratio
between the number of decrementer input clock cycles and one counter
increment, may be redefined prior to including this file in sysLib.c.
The macros SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN, and
AUX_CLK_RATE_MAX must be defined to provide parameter checking for
sysClkRateSet(), and sysAuxClkRateSet() routines.
To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must be
defined.
To enable dynamic bus clock rates, the BSP should set the macro,
PPC_TMR_RATE_SET_ADJUST, to call an apropriate routine. This call, will be
made each time sysClkRateSet() is called. E.g. To use sysClkRateAdjust to
compute a correct value for sysDecClkFrequency.
#define PPC_TMR_RATE_SET_ADJUST sysClkRateAdjust (&sysDecClkFrequency)
The macro, PPC_TMR_RATE_SET_ADJUST, is by default not defined.
INCLUDE FILES: timerDev.h, vxPpcLib.h
SEE ALSO:
.pG "Configuration"
*/
/* includes */
#include "arch/ppc/vxPpcLib.h"
#include "drv/timer/timerDev.h"
/* local defines */
#ifndef DEC_CLK_TO_INC
#define DEC_CLK_TO_INC 4 /* # bus clks per increment */
#endif
#ifndef DEC_CLOCK_FREQ
#define DEC_CLOCK_FREQ 33333333 /* 33.33 Mhz default */
#endif /* DEC_CLOCK_FREQ */
#define CPM_MEM_BASE INTERNAL_MEM_MAP_ADDR
/* extern declarations */
IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
/* locals */
LOCAL int sysClkTicksPerSecond = 60; /* default 60 ticks/second */
LOCAL FUNCPTR sysClkRoutine = NULL;
LOCAL int sysClkArg = 0;
LOCAL BOOL sysClkConnectFirstTime = TRUE;
LOCAL int decCountVal = 10000000; /* default dec value */
LOCAL BOOL sysClkRunning = FALSE;
LOCAL FUNCPTR sysAuxClkRoutine = NULL;
LOCAL int sysAuxClkArg = 0;
LOCAL BOOL sysAuxClkRunning = FALSE;
LOCAL BOOL sysAuxClkIntConnected = FALSE;
LOCAL int sysAuxClkTicksPerSecond = 60;
#ifdef INCLUDE_TIMESTAMP
LOCAL BOOL sysTimestampRunning = FALSE; /* timestamp running flag */
LOCAL FUNCPTR sysTimestampRoutine = NULL;
LOCAL int sysTimestampArg = 0;
LOCAL BOOL sysTimestampIntConnected = FALSE;
#endif /* INCLUDE_TIMESTAMP */
/*******************************************************************************
*
* sysClkInt - clock interrupt handler
*
* This routine handles the clock interrupt on the PowerPC architecture. It is
* attached to the decrementer vector by the routine sysClkConnect().
*
* RETURNS : N/A
*/
LOCAL void sysClkInt (void)
{
#ifdef USE_KEYED_REGS
vxKeyedDecReload(decCountVal);
#else
vxDecReload (decCountVal); /* reload decrementer */
#endif /*USE_KEYED_REGS*/
/* execute the system clock routine */
if (sysClkRunning && (sysClkRoutine != NULL))
(*(FUNCPTR) sysClkRoutine) (sysClkArg);
}
/*******************************************************************************
*
* sysClkConnect - connect a routine to the system clock interrupt
*
* This routine specifies the interrupt service routine to be called at each
* clock interrupt. Normally, it is called from usrRoot() in usrConfig.c to
* connect usrClock() to the system clock interrupt.
*
* RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
*
* SEE ALSO: intConnect(), usrClock(), sysClkEnable()
*/
STATUS sysClkConnect
(
FUNCPTR routine, /* routine to connect */
int arg /* argument for the routine */
)
{
if (sysClkConnectFirstTime)
{
sysHwInit2();
sysClkConnectFirstTime = FALSE;
excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_DECR, (VOIDFUNCPTR) sysClkInt);
}
sysClkRoutine = routine;
sysClkArg = arg;
return (OK);
}
/******************************************************************************
*
* sysClkEnable - turn on system clock interrupts
*
* This routine enables system clock interrupts.
*
* RETURNS: N/A
*
* SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
*/
void sysClkEnable (void)
{
if (!sysClkRunning)
{
sysClkRunning = TRUE;
vxDecSet (decCountVal);
}
}
/******************************************************************************
*
* sysClkDisable - turn off system clock interrupts
*
* This routine disables system clock interrupts.
*
* RETURNS: N/A
*
* SEE ALSO: sysClkEnable()
*/
void sysClkDisable (void)
{
if (sysClkRunning)
sysClkRunning = FALSE;
}
/******************************************************************************
*
* sysClkRateGet - get the system clock rate
*
* This routine returns the system clock rate.
*
* RETURNS: The number of ticks per second of the system clock.
*
* SEE ALSO: sysClkEnable(), sysClkRateSet()
*/
int sysClkRateGet (void)
{
return (sysClkTicksPerSecond);
}
/******************************************************************************
*
* sysClkRateSet - set the system clock rate
*
* This routine sets the interrupt rate of the system clock. It is called
* by usrRoot() in usrConfig.c.
*
* RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
*
* SEE ALSO: sysClkEnable(), sysClkRateGet()
*/
STATUS sysClkRateSet
(
int ticksPerSecond /* number of clock interrupts per second */
)
{
EPCFG *cfg = getEpCfg();
if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
return (ERROR);
/* save the clock speed */
sysClkTicksPerSecond = ticksPerSecond;
/* Calibrate the clock, if needed. */
#ifdef PPC_TMR_RATE_SET_ADJUST
PPC_TMR_RATE_SET_ADJUST;
#endif
/*
* compute the value to load in the decrementer. The new value will be
* load in the decrementer after the end of the current period
*/
decCountVal = cfg->sysDecFreq / ticksPerSecond;
return (OK);
}
/*******************************************************************************
*
* sysAuxClkInt - auxiliary clock interrupt handler
*
* This routine handles the auxiliary clock interrupt. It calls a user routine
* if one was specified by the routine sysAuxClkConnect().
*/
LOCAL void sysAuxClkInt (void)
{
*TER2(CPM_MEM_BASE) |= TER_REF; /* clear event register */
*CISR(CPM_MEM_BASE) = CISR_TIMER2; /* clear in-service bit */
if (sysAuxClkRoutine != NULL)
(*sysAuxClkRoutine) (sysAuxClkArg);
}
/*******************************************************************************
*
* sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
*
* This routine specifies the interrupt service routine to be called at each
* auxiliary clock interrupt. It does not enable auxiliary clock
* interrupts.
*
* RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
*
* SEE ALSO: intConnect(), sysAuxClkEnable()
*/
STATUS sysAuxClkConnect
(
FUNCPTR routine, /* routine called at each aux. clock interrupt */
int arg /* argument to auxiliary clock interrupt routine */
)
{
/* connect the ISR to the TIMER2 exception */
sysAuxClkRoutine = routine;
sysAuxClkArg = arg;
return (OK);
}
/*******************************************************************************
*
* sysAuxClkDisable - turn off auxiliary clock interrupts
*
* This routine disables auxiliary clock interrupts.
*
* RETURNS: N/A
*
* SEE ALSO: sysAuxClkEnable()
*/
void sysAuxClkDisable (void)
{
if (sysAuxClkRunning)
{
*CIMR(CPM_MEM_BASE) &= ~CISR_TIMER2; /* disable interrupt */
*TGCR(CPM_MEM_BASE) |= TGCR_STP2; /* stop timer */
sysAuxClkRunning = FALSE; /* clock is no longer running */
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -