📄 ks8695timer.c
字号:
/* ks8695Timer.c - KS8695/P/X timer library */
/*
modification history
--------------------
11/13/2003 LIQUN RUAN (RLQ) modified for KS8695/X, and shared all the functions with KS8695P
09/15/2003 Ritter Yeh created
*/
/* includes */
#include "ks8695Timer.h"
#include "drv/timer/timestampDev.h"
/* defines */
#define KS8695P_TIMER_INT_ENABLE(level) intEnable (level)
#define KS8695P_TIMER_INT_DISABLE(level) intDisable (level)
/* locals */
LOCAL FUNCPTR sysClkRoutine = NULL; /* routine to call on clock interrupt */
LOCAL int sysClkArg = 0; /* its argument */
LOCAL int sysClkRunning = FALSE;
LOCAL int sysClkConnected = FALSE;
LOCAL int sysClkTicksPerSecond = 60;
LOCAL FUNCPTR sysAuxClkRoutine = NULL;
LOCAL int sysAuxClkArg = 0;
LOCAL int sysAuxClkRunning = FALSE;
LOCAL int sysAuxClkTicksPerSecond = 100;
#ifdef INCLUDE_TIMESTAMP
LOCAL BOOL sysTimestampRunning = FALSE; /* timestamp running flag */
#endif /* INCLUDE_TIMESTAMP */
/*******************************************************************************
*
* sysClkInt - interrupt level processing for system clock
*
* This routine handles the system clock interrupt. It is attached to the
* clock interrupt vector by the routine sysClkConnect().
*
* RETURNS: N/A.
*/
LOCAL void sysClkInt (void)
{
UINT32 isr;
KS8695P_REG_READ (REG_INT_STATUS, isr);
/* If not ours, simply return */
if ((isr & REG_INT_T0) == 0)
return ;
/* disable Timer 0 interrupt first */
KS8695P_REG_BIT_CLR (REG_INT_ENABLE, REG_INT_T0);
/* ACK */
KS8695P_REG_WRITE(REG_INT_STATUS, REG_INT_T0);
/* If any routine attached via sysClkConnect(), call it */
if (sysClkRoutine != NULL)
(* sysClkRoutine) (sysClkArg);
/* enable Timer 0 interrupt again */
KS8695P_REG_BIT_SET (REG_INT_ENABLE,REG_INT_T0);
}
/*******************************************************************************
*
* sysClkConnect - connect a routine to the system clock interrupt
*
* This routine specifies the interrupt service routine to be called at each
* clock interrupt. It does not enable system clock interrupts.
* 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 be called at each clock interrupt */
int arg /* argument with which to call routine */
)
{
if (sysClkConnected == FALSE)
{
sysHwInit2 (); /* XXX for now -- needs to be in usrConfig.c */
sysClkConnected = TRUE;
}
sysClkRoutine = NULL; /* ensure routine not called with wrong arg */
sysClkArg = arg;
if (routine)
sysClkRoutine = routine;
return OK;
}
/*******************************************************************************
*
* sysClkDisable - turn off system clock interrupts
*
* This routine disables system clock interrupts.
*
* RETURNS: N/A
*
* SEE ALSO: sysClkEnable()
*/
void sysClkDisable (void)
{
if (sysClkRunning)
{
/*
* Disable timer itself. Might as well leave it configured for
* Periodic mode, divided by 16.
*/
KS8695P_REG_BIT_CLR(REG_TIMER_CTRL, REG_TIMER_CTRL_TOUT0E);
/* Disable the timer interrupt in the Interrupt Controller */
intDisable (INT_LVL_T0MS);
sysClkRunning = FALSE;
}
}
/*******************************************************************************
*
* sysClkEnable - turn on system clock interrupts
*
* This routine enables system clock interrupts.
*
* RETURNS: N/A
*
* SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
*/
void sysClkEnable (void)
{
UINT32 tc;
if (!sysClkRunning)
{
/*
* Calculate the timer value
* Note that it may take some ticks to reload the counter
* so counter value = (clock rate / sysClkTicksPerSecond) - num_ticks
*/
tc = (SYS_TIMER_CLK / sysClkTicksPerSecond); /* 25M / 60 */
/* Load Timer Reload value into Timer registers */
KS8695P_REG_WRITE (REG_TIMER0, tc/2);
KS8695P_REG_WRITE (REG_TIMER0_PCOUNT, tc/2);
/* enable clock interrupt in interrupt controller */
intEnable (INT_LVL_T0MS);
/* Enable timer */
KS8695P_REG_BIT_SET (REG_TIMER_CTRL, REG_TIMER_CTRL_TOUT0E);
sysClkRunning = TRUE;
}
}
/*******************************************************************************
*
* sysClkRateGet - get the system clock rate
*
* This routine returns the interrupt rate of the system clock.
*
* RETURNS: The number of ticks per second of the system clock.
*
* SEE ALSO: sysClkRateSet(), sysClkEnable()
*/
int sysClkRateGet (void)
{
return sysClkTicksPerSecond;
}
/*******************************************************************************
*
* sysClkRateSet - set the system clock rate
*
* This routine sets the interrupt rate of the system clock. It does not
* enable system clock interrupts unilaterally, but if the system clock is
* currently enabled, the clock is disabled and then re-enabled with the new
* rate. Normally 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: sysClkRateGet(), sysClkEnable()
*/
STATUS sysClkRateSet
(
int ticksPerSecond /* number of clock interrupts per second */
)
{
if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
return ERROR;
sysClkTicksPerSecond = ticksPerSecond;
if (sysClkRunning)
{
sysClkDisable ();
sysClkEnable ();
}
return OK;
}
/*******************************************************************************
*
* sysAuxClkInt - handle an auxiliary clock interrupt
*
* This routine handles an auxiliary clock interrupt. It acknowledges the
* interrupt and calls the routine installed by sysAuxClkConnect().
*
* RETURNS: N/A
*/
LOCAL void sysAuxClkInt (void)
{
/* Acknowledge interrupt: any write to Clear Register clears interrupt */
KS8695P_REG_WRITE(REG_INT_STATUS, REG_INT_T1);
/* If any routine attached via sysAuxClkConnect(), call it */
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 also connects the clock error interrupt
* service routine.
*
* 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 with which to call routine */
)
{
sysAuxClkRoutine = NULL; /* ensure routine not called with wrong arg */
sysAuxClkArg = arg;
if (routine == NULL)
return OK;
#if ((CPU_FAMILY == ARM) && ARM_THUMB)
/* set b0 so that sysAuxClkConnect() can be used from shell */
sysAuxClkRoutine = (FUNCPTR)((UINT32)routine | 1);
#else
sysAuxClkRoutine = routine;
#endif /* CPU_FAMILY == ARM */
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)
{
/*
* Disable timer itself. Might as well leave it configured for
* Periodic mode, divided by 16.
*/
KS8695P_REG_BIT_CLR(REG_TIMER_CTRL, REG_TIMER_CTRL_TOUT1E);
/* Disable the timer interrupt in the Interrupt Controller */
KS8695P_TIMER_INT_DISABLE (AUX_TIMER_INT_LVL);
sysAuxClkRunning = FALSE;
}
}
/*******************************************************************************
*
* sysAuxClkEnable - turn on auxiliary clock interrupts
*
* This routine enables auxiliary clock interrupts.
*
* RETURNS: N/A
*
* SEE ALSO: sysAuxClkDisable()
*/
void sysAuxClkEnable (void)
{
UINT32 tc;
if (!sysAuxClkRunning)
{
/*
* Calculate the timer value
* Note that it may take some ticks to reload the counter
* so counter value = (clock rate / sysClkTicksPerSecond) - num_ticks
*/
tc = (SYS_TIMER_CLK / sysClkTicksPerSecond);
/* Load Timer Reload value into Timer registers */
KS8695P_REG_WRITE (REG_TIMER1, tc/2);
KS8695P_REG_WRITE (REG_TIMER1_PCOUNT, tc/2);
/* enable clock interrupt in interrupt controller */
KS8695P_TIMER_INT_ENABLE (AUX_TIMER_INT_LVL);
sysAuxClkRunning = TRUE;
}
}
/*******************************************************************************
*
* sysAuxClkRateGet - get the auxiliary clock rate
*
* This routine returns the interrupt rate of the auxiliary clock.
*
* RETURNS: The number of ticks per second of the auxiliary clock.
*
* SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
*/
int sysAuxClkRateGet (void)
{
return sysAuxClkTicksPerSecond;
}
/*******************************************************************************
*
* sysAuxClkRateSet - set the auxiliary clock rate
*
* This routine sets the interrupt rate of the auxiliary clock. It does
* not enable auxiliary clock interrupts unilaterally, but if the
* auxiliary clock is currently enabled, the clock is disabled and then
* re-enabled with the new rate.
*
* RETURNS: OK or ERROR.
*
* SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
*/
STATUS sysAuxClkRateSet
(
int ticksPerSecond /* number of clock interrupts per second */
)
{
if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
return ERROR;
sysAuxClkTicksPerSecond = ticksPerSecond;
if (sysAuxClkRunning)
{
sysAuxClkDisable ();
sysAuxClkEnable ();
}
return OK;
}
#ifdef INCLUDE_TIMESTAMP
/*******************************************************************************
*
* sysTimestampConnect - connect a user routine to a timestamp timer interrupt
*
* This routine specifies the user interrupt routine to be called at each
* timestamp timer interrupt.
*
* RETURNS: ERROR, always.
*/
STATUS sysTimestampConnect
(
FUNCPTR routine, /* routine called at each timestamp timer interrupt */
int arg /* argument with which to call routine */
)
{
return ERROR;
}
/*******************************************************************************
*
* sysTimestampEnable - enable a timestamp timer interrupt
*
* This routine enables timestamp timer interrupts and resets the counter.
*
* RETURNS: OK, always.
*
* SEE ALSO: sysTimestampDisable()
*/
STATUS sysTimestampEnable (void)
{
if (sysTimestampRunning)
{
return OK;
}
if (!sysClkRunning) /* timestamp timer is derived from the sysClk */
return ERROR;
sysTimestampRunning = TRUE;
return OK;
}
/*******************************************************************************
*
* sysTimestampDisable - disable a timestamp timer interrupt
*
* This routine disables timestamp timer interrupts.
*
* RETURNS: OK, always.
*
* SEE ALSO: sysTimestampEnable()
*/
STATUS sysTimestampDisable (void)
{
if (sysTimestampRunning)
sysTimestampRunning = FALSE;
return OK;
}
/*******************************************************************************
*
* sysTimestampPeriod - get the period of a timestamp timer
*
* This routine gets the period of the timestamp timer, in ticks. The
* period, or terminal count, is the number of ticks to which the timestamp
* timer counts before rolling over and restarting the counting process.
*
* RETURNS: The period of the timestamp timer in counter ticks.
*/
UINT32 sysTimestampPeriod (void)
{
/*
* The period of the timestamp depends on the clock rate of the system
* clock.
*/
return ((UINT32)(SYS_TIMER_CLK / sysClkTicksPerSecond));
}
/*******************************************************************************
*
* sysTimestampFreq - get a timestamp timer clock frequency
*
* This routine gets the frequency of the timer clock, in ticks per
* second. The rate of the timestamp timer is set explicitly by the
* hardware and typically cannot be altered.
*
* NOTE: Because the system clock serves as the timestamp timer,
* the system clock frequency is also the timestamp timer frequency.
*
* RETURNS: The timestamp timer clock frequency, in ticks per second.
*/
UINT32 sysTimestampFreq (void)
{
return ((UINT32)SYS_TIMER_CLK);
}
/*******************************************************************************
*
* sysTimestamp - get a timestamp timer tick count
*
* This routine returns the current value of the timestamp timer tick counter.
* The tick count can be converted to seconds by dividing it by the return of
* sysTimestampFreq().
*
* This routine should be called with interrupts locked. If interrupts are
* not locked, sysTimestampLock() should be used instead.
*
* RETURNS: The current timestamp timer tick count.
*
* SEE ALSO: sysTimestampFreq(), sysTimestampLock()
*/
UINT32 sysTimestamp (void)
{
UINT32 t, t1, t2;
t1=0;
t2=0;
KS8695P_REG_READ (REG_TIMER0, t1);
KS8695P_REG_READ (REG_TIMER0_PCOUNT, t2);
t = t1 + t2;
#if defined (KS8695P_TIMER_VALUE_MASK)
t &= KS8695P_TIMER_VALUE_MASK;
#endif
return (sysTimestampPeriod() - t);
}
/*******************************************************************************
*
* sysTimestampLock - lock interrupts and get the timestamp timer tick count
*
* This routine locks interrupts when the tick counter must be stopped
* in order to read it or when two independent counters must be read.
* It then returns the current value of the timestamp timer tick
* counter.
*
* The tick count can be converted to seconds by dividing it by the return of
* sysTimestampFreq().
*
* If interrupts are already locked, sysTimestamp() should be
* used instead.
*
* RETURNS: The current timestamp timer tick count.
*
* SEE ALSO: sysTimestampFreq(), sysTimestamp()
*/
UINT32 sysTimestampLock (void)
{
UINT32 t, t1, t2;
t1=0;
t2=0;
KS8695P_REG_WRITE (REG_TIMER0, t1);
KS8695P_REG_WRITE (REG_TIMER0_PCOUNT, t2);
t = t1 + t2;
#if defined (KS8695P_TIMER_VALUE_MASK)
t &= KS8695P_TIMER_VALUE_MASK;
#endif
return (sysTimestampPeriod() - t);
}
#endif /* INCLUDE_TIMESTAMP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -