📄 m8260timerdriver.c
字号:
/* ghM8260Timer.c - Eastcomtd M8260 Timer Library *//* Copyright 2000 Eastcomtd *//*modification history--------------------05-05-2000 /0 DP - adapted from drv/timer/m8260Timer.c*//*DESCRIPTIONThis library provides MPC8260 system clock, auxiliary clock, and timestampsupport.The PowerPC decrementer timer is used to implement the system clock, the CPMTIMER2 is used for a 16-bit auxiliary clock, and CPM timers TIMER3 and TIMER4are cascaded into a free-running 32-bit timer for timestamp support.The macro DEC_CLOCK_FREQ, the frequency of the decrementer input clock, mustbe defined before using this module. The macro DEC_CLK_TO_INC, the ratiobetween the number of decrementer input clock cycles and one counterincrement, may be redefined prior to including this file in sysLib.c.The macros SYS_CLK_RATE_MIN and SYS_CLK_RATE_MAX must be defined to provide parameter checking for sysClkRateSet() the routine.The auxiliary clock period is modified by programming the Timer ReferenceRegister. The input is the general system clock, which can be optionallydivided by 16. The prescaler is always used to divide by 256. The TimerReference Register is 16 bits. This information dictates the minimum and maximum auxiliarly clock rates.The slowest rate is when the general system clock is divided by 16 and the value for the Reference register is the highest i.e. 65535. This gives us a minimum auxiliarly clock rate of .CS SYS_CPU_FREQ / (256 * 65535 * 16) = 40000000 / 268431360 = .15.CEWe define AUX_CLK_RATE_MIN as 1The highest rate is when the general system clock is not divided by16, and the reference register is set to its minimum value i.e. 1.This tells us the maximum auxiliary clock rate:.CS SYS_CPU_FREQ / 256 = 40000000 / 256 = 156250.CEWe define AUX_CLK_RATE_MAX as 8000INCLUDE FILES: timerDev.h, vxPpcLib.h SEE ALSO:.pG "Configuration"*//* includes */#include "arch/ppc/vxPpcLib.h"#include "drv/timer/timerDev.h"#include "drv/timer/ghM8260Timer.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 FREQ_BUS /* 66.00 Mhz default */#endif /* DEC_CLOCK_FREQ */#ifndef SYS_CPU_FREQ #define SYS_CPU_FREQ FREQ_BUS /* 66.00 Mhz default */#endif /* SYS_CPU_FREQ *//* locals */LOCAL int sysClkTicksPerSecond = 60; /* default 60 ticks/second */LOCAL FUNCPTR sysClkRoutine = NULL;LOCAL int sysClkArg = NULL;LOCAL BOOL sysClkConnectFirstTime = TRUE;LOCAL int decCountVal = 10000000; /* 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_TIMESTAMPLOCAL 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 : None*/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 sysClkIntLoop: add. 3, %0, 3 ble sysClkIntLoop /* check if we missed tick(s) */ mtdec 3" : /* no output operands */ : "r" (decCountVal) /* input operand, %0 = decCountVal */ : "3", "cc"/* side-effects: r3 clobbered, 'condition code' is clobbered */ ); /* 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: None** 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: None** SEE ALSO: sysClkEnable()*/void sysClkDisable (void){ 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; /* * compute the value to load in the decrementer. The new value will be * loaded into the decrementer after the current period */ /* decCountVal = sysDecClkFrequency / ticksPerSecond; */ decCountVal = ((sysDecClkFrequency + ticksPerSecond/2) / ticksPerSecond) - 1; 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 int sysAuxClkInt (void){ char *immrVal; /* get immr value */ immrVal = vxImmrGet(); *M8260_TER2(immrVal) = M8260_TER_REF | M8260_TER_CAP; /* clear all events */ if (sysAuxClkRoutine != NULL) { (*sysAuxClkRoutine) (sysAuxClkArg); } return(IT_PROCESSED);}/***************************************************************************** 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: None** SEE ALSO: sysAuxClkEnable()*/void sysAuxClkDisable (void){ char *immrVal; if (sysAuxClkRunning) { /* get immr value */ immrVal = vxImmrGet(); intDisable(INUM_TIMER2); *M8260_TGCR1(immrVal) |= M8260_TGCR_STP2; /* stop timer */ sysAuxClkRunning = FALSE; /* clock is no longer running */ }}/***************************************************************************** sysAuxClkEnable - turn on auxiliary clock interrupts** This routine enables auxiliary clock interrupts.* The timer is used in "reference mode" i.e. a value is programmed into * the reference register and an interrupt occurs when the timer reaches* that value. ** RETURNS: None** SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()*/void sysAuxClkEnable (void){ char *immrVal; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -