📄 m68681timer.c
字号:
/* m68681Timer.c - MC68681/SC2681 timer driver *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01h,10jun97,wlf doc: cleanup01g,03mar97,kkk added timestamp support. Added macro M68681_PRESCALER.01f,04feb97,dat changed timer to run in counter mode.01e,04jan97,p_m removed "," in param list that was introduced by doc cleanup.01d,25oct96,wlf doc: cleanup.01c,27mar96,dat new timer driver, to be used with new sio serial drivers01b,08feb93,caf fixed ansi warning (SPR 1851).01a,21aug92,caf created.*//*DESCRIPTIONThis is the timer driver for the MC68681/SC2681 DUART.It uses the DUART for the system clock only.This driver relies on the serial driver m68681Serial.c for its operation.The macros SYS_CLK_RATE_MIN and SYS_CLK_RATE_MAX must be defined to provideparameter checking for sysClkRateSet().The macro DUART_CLOCK_DEVICE must be defined.If the driver controls only one DUART, DUART_CLOCK_DEVICE must be 0.The macro DUART_HZ must be defined to reflect the clock frequency suppliedto the DUART hardware. The typical value is 3686400.If this driver is being used with the new bi-modal driver m68681Sio.c, thea completely new interface is used. This is expected to be a model fora new class of timer devices altogether. This new interface is initializedby the m68681DevInit() function which links the m68681Duart to the newm68681Clk structures.*/#ifdef INCLUDE_TYCODRV_5_2/* TO BE USED WITH SINGLE-MODE SERIAL DRIVER *//* locals */LOCAL int sysClkTicksPerSecond = 60;LOCAL int sysClkRunning = FALSE;LOCAL BOOL sysClkConnected = FALSE;LOCAL FUNCPTR sysClkRoutine = NULL;LOCAL int sysClkArg = NULL;IMPORT void tyImrSet ();IMPORT void tyCoClkConnect ();/********************************************************************************* sysClkInt - handle system clock interrupts** This routine handles system clock interrupts.** RETURNS: N/A*/LOCAL void sysClkInt (void) { if (*tyCoDv [2 * DUART_CLOCK_DEVICE].ctroff) /* reset the interrupt */ ; if (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. ** RETURN: OK, or ERROR if the routine cannot be connected to the interrupt.** SEE ALSO: intConnect(), usrClock(), sysClkEnable()*/STATUS sysClkConnect ( FUNCPTR routine, /* routine called at each system clock interrupt */ int arg /* argument with which to call routine */ ) { sysHwInit2 (); /* XXX for now -- needs to be in usrConfig.c */ /* DUART serial driver handles the timer interrupt */ tyCoClkConnect (DUART_CLOCK_DEVICE, sysClkInt); sysClkRoutine = routine; sysClkArg = arg; sysClkConnected = TRUE; 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) { tyImrSet (& tyCoDv [2 * DUART_CLOCK_DEVICE], 0, CTR_RDY_INT); *tyCoDv [2 * DUART_CLOCK_DEVICE].acr = BRG_SELECT; 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) { if (!sysClkRunning) { int temp; /* preload the preload register */ temp = (DUART_HZ / 2) / sysClkTicksPerSecond; *tyCoDv [2 * DUART_CLOCK_DEVICE].ctlr = LSB (temp); *tyCoDv [2 * DUART_CLOCK_DEVICE].ctur = MSB (temp); *tyCoDv [2 * DUART_CLOCK_DEVICE].acr = BRG_SELECT | TMR_EXT_CLK; tyImrSet (& tyCoDv [2 * DUART_CLOCK_DEVICE], CTR_RDY_INT, 0); if (* tyCoDv [2 * DUART_CLOCK_DEVICE].ctron) ; /* start timer */ sysClkRunning = TRUE; } }/********************************************************************************* 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 does not* enable system clock interrupts. 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); sysClkTicksPerSecond = ticksPerSecond; if (sysClkRunning) { sysClkDisable (); sysClkEnable (); } return (OK); }#else /* INCLUDE_TYCODRV_5_2 *//* TO BE USED WITH NEW DUAL-MODE SIO DRIVER *//*DESCRIPTIONThis is the timer driver for the MC68681/SC2681 DUART.Each MC68681 device provides one counter/timer device. This driverpresumes counter mode operation.This driver relies on the serial driver m68681Sio.c for its operation.This driver should not be used if m68681Sio.o is not included in the system.The default clock rate can be specified by setting the macro M68681_CLK_TICKS to the desired value. If not set, the value used will be 60 hertz.To use this driver, the user creates and initializes the data in a M68681_CLK structure. The address of that structure, and the addressof the associated M68681_DUART structure (which has already been createdand completely initialized) are passed to the m68681ClkInit routine.i.e..CS/@ data structures, serial and clock @/M68681_DUART myDuart;M68681_CLK myClock;sysHwInit2 () { ... /@ 68681 Duart must be initialized first @/ m68681DevInit (&myDuart); ... /@ interrupt should be connected before m68681ClkInit @/ intConnect (INUM_TO_IVEC(CLK_INUM), m68681ClkInt, &myClock); ... /@ initialize clock structure elements, as needed @/ myClock->min = SYS_CLK_RATE_MIN; myClock->max = SYS_CLK_RATE_MAX; myClock->hertz = 3686400; myClock->rate = 60; /@ call initialization procedure @/ m68681ClkInit (&myClock, &myDuart); ... }.CE*/#include "drv/sio/m68681Sio.h"/* default clock rate */#ifndef M68681_CLK_TICKS#define M68681_CLK_TICKS (60)#endif/* default prescaler value in counter mode */#ifndef M68681_PRESCALER#define M68681_PRESCALER (16)#endif/* * Allow user to redefine the register access procedure. * Default is to assume normal memory accesses. * The register pointer argument comes directly from the * data structures. */#ifndef M68681_READ#define M68681_READ(x) (*(x)) /* arg is register pointer */#endif#ifndef M68681_WRITE#define M68681_WRITE(x,y) (*(x) = y) /* args are reg ptr, data to write */#endif/* Oscillator frequency input to m68681 */#define M68681_OSC_HZ (3686400)#define MAX_CTR_VALUE (0xffff)#define MIN_CTR_VALUE (0x2)/*********************************************************************** m68681ClkInit - initialize an MC68681 counter/timer** This routine initializes a clock device. It requires a pointer to* the associated DUART structure.** After initialization, the MC68681 CLK structure is disabled with no attached* routines.** If the structure elements <hertz>, <rate>, <min>, or <max> are uninitialized,* this routine initializes them. If these values are invalid, they* are corrected.** RETURNS: OK, or ERROR if either <pClk> or <pDuart> is invalid.*/STATUS m68681ClkInit ( M68681_CLK *pClk, /* clock to be initialized */ M68681_DUART *pDuart /* associated DUART for this clock */ ) { int temp; if (pClk == NULL || pDuart == NULL) return ERROR; /* initialize clock data fields */ pClk->running = FALSE; pClk->routine = NULL; pClk->arg = 0; /* normalize and fix up ticks, hertz, min, max */ if (pClk->rate <= 0) pClk->rate = M68681_CLK_TICKS; if (pClk->hertz <= 0) pClk->hertz = M68681_OSC_HZ; temp = pClk->hertz / (M68681_PRESCALER * MAX_CTR_VALUE); if (pClk->min < temp) pClk->min = temp; temp = pClk->hertz / (M68681_PRESCALER * MIN_CTR_VALUE); if (pClk->max > temp || pClk->max <= 0) pClk->max = temp; /* connect DUART to clock */ pClk->pDuart = pDuart; /* connect clock to DUART */ pDuart->tickArg = pClk; pDuart->tickRtn = m68681ClkInt; return OK; }/********************************************************************** m68681ClkInt - MC68681 clock interrupt handler** This is the clock interrupt handler for the MC68681/SC2681 DUART. The* system connects this routine to the appropriate interrupt vector.** Because the counter is actually stopped for a very small amount of* time, there is some amount of clock skew in the system. It should* be less than the actual clock frequency error.** RETURNS: N/A*/void m68681ClkInt ( M68681_CLK *pClk /* clock to be serviced */ ) { char resetTimer; UINT16 temp; /* turn off the counter */ resetTimer = M68681_READ (pClk->pDuart->ctroff); /* adjust for clock skew */ temp = (M68681_READ (pClk->pDuart->ctur) << 8); temp |= M68681_READ (pClk->pDuart->ctlr); temp += pClk->preload; M68681_WRITE (pClk->pDuart->ctlr, LSB (temp)); M68681_WRITE (pClk->pDuart->ctur, MSB (temp)); /* restart counter */ resetTimer = M68681_READ (pClk->pDuart->ctron); if (pClk->routine != NULL) (*pClk->routine) (pClk->arg); }/********************************************************************** m68681ClkConnect - connect a routine to the clock interrupt** This routine specifies the user routine to be called at each clock* interrupt of a Motorola MC68681 timer. It does not enable system * clock interrupts.** RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.** SEE ALSO: m68681ClkEnable()*/STATUS m68681ClkConnect ( M68681_CLK *pClk, /* clock to connect to */ VOIDFUNCPTR routine,/* routine called at each clock interrupt */ void * arg /* argument with which to call routine */ ) { pClk->routine = NULL; pClk->arg = arg; pClk->routine = routine; return OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -