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

📄 ppc860timer.c

📁 motorola mpc系列 mpc852cpu bsp
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ppc860Timer.c - PowerPC/860 timer library */

/* Copyright 1984-1997 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01, 25jul02,liuxu changed the DEC param
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		50000000	/* 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 	= 100;	  /* default 100 ticks/second */
LOCAL FUNCPTR	sysClkRoutine		= NULL;
LOCAL int	sysClkArg		= NULL;
LOCAL BOOL	sysClkConnectFirstTime	= TRUE;
LOCAL int       decCountVal		= 1000000;	/* default dec value */
LOCAL BOOL	sysClkRunning 		= FALSE;
LOCAL int 	sysDecClkFrequency	= DEC_CLOCK_FREQ/DEC_CLK_TO_INC;

LOCAL FUNCPTR	sysAuxClkRoutine	= NULL;
LOCAL int	sysAuxClkArg		= NULL;
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		= NULL;
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)
    {
    /*
     * The PowerPC decrementer doesn't reload the value by itself. The reload
     * need to be performed in this handler. The reload value should be 
     * adjusted each time because the time spent between the exception
     * generation and the moment the register is reloaded changes.
     * By reading the decrementer we obtain the time spent between the 
     * two events and can adjust the value to reload. This is done in assembly
     * language in order to minimize time spent between reading and writing
     * to the decrementer register in order to maximize system clock accuracy.
     */

__asm__ ("
    mfdec   	3	/*lint !e10*/
sysClkIntLoop:
    add. 	3, %0, 3    /*lint !e24*/
    ble		sysClkIntLoop		/* check if we missed tick(s) *//*lint !e10*/
    mtdec	3"
    :					/* no output operands  */
    : "r" (decCountVal)			/* input operand, %0 = decCountVal */
    : "3", "cc"/* side-effects: r3 clobbered, 'condition code' is clobbered *//*lint !e10*/
    );

    /* execute the system clock routine */

    if (sysClkRunning && (sysClkRoutine != NULL))
    	(*(FUNCPTR) sysClkRoutine) (sysClkArg);     /*lint !e522 !e746*/

    }

/*******************************************************************************
*
* 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;
        (void)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 ((UINT32)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 */
    )
    {
    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 = (sysDecClkFrequency / ticksPerSecond)/4;

    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)
    {
    *TER4(CPM_MEM_BASE) |= TER_REF;     /* clear event register */
    *CISR(CPM_MEM_BASE) = /*CISR_TIMER2*/CISR_TIMER4;  /* clear in-service bit */

    if (sysAuxClkRoutine != NULL)
        (*sysAuxClkRoutine) (sysAuxClkArg);     /*lint !e522 !e746*/
    }

/*******************************************************************************
*
* 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_TIMER4/*CISR_TIMER2*/;	/* disable interrupt */
	*TGCR(CPM_MEM_BASE) |= TGCR_STP4/*TGCR_STP2*/;	/* stop timer */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -