📄 s3c2410timer.c
字号:
/* ambaTimer.c - Advanced RISC Machines AMBA timer library *//* Copyright 1996-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01l,18apr02,dat null check in sysClkConnect, SPR 2672901k,31oct01,rec integrator AP changes01j,04sep98,cdp enable Thumb support for all ARM CPUs with ARM_THUMB==TRUE.01i.10mar98,jpd comments/layout tidying.01h,23jan98,jpd fixed bug in sysAuxClkConnect() (SPR #20349)01g,11dec97,kkk fixed typo in AMBA_TIMER_READ macro.01f,02dec97,jpd updated to latest coding standards.01e,28oct97,cdp set b0 in sysClkConnect/sysAuxClkConnect for Thumb.01d,28oct97,tam added TIMESTAMP support.01c,08oct97,kkk fixed bug in sysClkConnect().01b,18aug97,jpd Made more generic.01a,09jul96,jpd Written, based on i8253Timer.c, version 01i.*//*DESCRIPTIONThis library contains routines to manipulate the timer functions on anAMBA timer with a mostly board-independent interface. This driverprovides 3 main functions, system clock support, auxiliary clocksupport, and timestamp timer support. The timestamp function is alwaysconditional upon the INCLUDE_TIMESTAMP macro.The AMBA Timer is a generic design of timer used within a number ofsystems including the ARM PID7T development system and the DigitalSemiconductor 21285 chips as used in the EBSA-285 Evaluation Board.Different implementations of the design may vary slightly, such asproviding more timers.Two timers are defined as the minimum (21285 provides 4). Each timer isa down counter (16 bits wide in PID7T, 24 on 21285), with selectablepre-scale.Two modes of operation are available, free-running and periodic timer.In periodic timer mode, the counter will generate an interrupt at aconstant interval. In free-running mode, the timer will underflow afterreaching its zero value and continue to count down from the maximumvalue.The timer is loaded by writing to the Load register, and then, ifenabled, the timer will count down to zero. On reaching a count ofzero, an interrupt will be generated. The interrupt may be cleared bywriting to the Clear register.After reaching a zero count, if the timer is operating in free-runningmode, then the timer will continue to decrement from its maximum value.If periodic timer mode is selected, then the timer will reload from theLoad register and continue to decrement. In this mode, the timer willeffectively generate a periodic interrupt. The mode is selected by abit in the Control register and the timer is enabled by a bit in theControl register. At reset, the timer will be disabled, the interruptwill be cleared and the Load register will be undefined. The mode andpre-scale vale will also be undefined.At any time, the current timer value may be read from the Value register.The timer clock is generated by a pre-scale unit. The timer clock maybe fed by the system clock or an external clock, then divided by 1, 16,or 256, which is generated by 0, 4 or 8 bits of pre-scale.REGISTERS:LOAD: (read/write) The load register contains the initial value of the timerand is also used as the reload value in periodic timer mode. When writing tothis register, the unused high bits should be written as 0, and when reading,the unused bits will be undefined.VALUE: (read only) The Value location gives the current value of the timer.When reading this location, the unused bits are undefined.CLEAR: (write only) Writing to the Clear location clears an interrupt generatedby the counter/timer.CTRL: (read/write) The Control register provides enable/disable, mode,pre-scale and clock source configurations for the timer.bits0:1 unused2:3 prescale: 00 = system clock divded by 1 01 = system clock divded by 16 10 = system clock divded by 256 11 = fed by external clock source (21285)4:5 unused6 mode: 0 => free-running 1 => periodic7 enable: 0 => disable 1 => enableall unused bits must be written as zero and read as undefined.Only periodic mode is explicitly supported by this driver.Configuration of the control register is done via macros, so the BSPcan choose suitable configuration values.Note that the system clock timer provides for the timestamp facility aswell, therefore changing the system clock rate will affect thetimestamp timer period, which can be read by callingsysTimestampPeriod().The macros SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN, andAUX_CLK_RATE_MAX must be defined to provide parameter checking for thesys[Aux]ClkRateSet() routines. The following macros must also be defined:SYS_TIMER_CLK /@ frequency of clock feeding SYS_CLK timer @/AUX_TIMER_CLK /@ frequency of clock feeding AUX_CLK @/AMBA_RELOAD_TICKS /@ any overhead in ticks when timer reloads @/SYS_TIMER_CLEAR /@ addresses of timer registers @/SYS_TIMER_CTRL /@ "" @/SYS_TIMER_LOAD /@ "" @/SYS_TIMER_VALUE /@ "" @/AUX_TIMER_CLEAR /@ "" @/AUX_TIMER_CTRL /@ "" @/AUX_TIMER_LOAD /@ "" @/AUX_TIMER_VALUE /@ "" @/SYS_TIMER_INT_LVL /@ interrupt level for sys Clk @/AUX_TIMER_INT_LVL /@ interrupt level for aux Clk @/AMBA_TIMER_SYS_TC_DISABLE /@ Control register values used when @/AMBA_TIMER_SYS_TC_ENABLE /@ enabling and disabling the two timers @/AMBA_TIMER_AUX_TC_DISABLE /@ "" @/AMBA_TIMER_AUX_TC_ENABLE /@ "" @/The following may also be defined, if required:AMBA_TIMER_READ (reg, result) /@ read an AMBA timer register @/AMBA_TIMER_WRITE (reg, data) /@ write ... @/AMBA_TIMER_INT_ENABLE (level) /@ enable an interrupt @/AMBA_TIMER_INT_DISABLE (level) /@ disable an interrpt @/BSPApart from defining such macros described above as are needed, the BSPwill need to connect the interrupt handlers (typically in sysHwInit2()).e.g..CS /@ connect sys clock interrupt and auxiliary clock interrupt @/ intConnect (INUM_TO_IVEC (INT_VEC...), sysClkInt, 0); intConnect (INUM_TO_IVEC (INT_VEC...), sysAuxClkInt, 0);.CEINCLUDES:ambaTimer.htimestampDev.hSEE ALSO:.I "ARM Reference Peripheral Specification, ARM DDI 0062D,".I "AMBA Timer Data Sheet, ARM DDI 0049B,".I "ARM Target Development System User Guide, ARM DUI 0061A,".I "Digital Semiconductor 21285 Core Logic for SA-110 Microprocessor DataSheet."*//* includes *//*#include "drv/timer/ambaTimer.h"#include "drv/timer/timestampDev.h"*/#include "config.h"/* defines */#ifndef AMBA_TIMER_READ#define AMBA_TIMER_READ(reg, result) \ ((result) = *((volatile UINT32 *)(reg)))#endif /* AMBA_TIMER_READ */#ifndef AMBA_TIMER_WRITE#define AMBA_TIMER_WRITE(reg, data) \ (*((volatile UINT32 *)(reg)) = (data))#endif /* AMBA_TIMER_WRITE */#ifndef AMBA_TIMER_INT_ENABLE#define AMBA_TIMER_INT_ENABLE(level) intEnable (level)#endif#ifndef AMBA_TIMER_INT_DISABLE#define AMBA_TIMER_INT_DISABLE(level) intDisable (level)#endif/* 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_TIMESTAMPLOCAL BOOL sysTimestampRunning = FALSE; /* timestamp running flag */#endif /* INCLUDE_TIMESTAMP */#if !defined (SYS_CLK_RATE_MIN) || !defined (SYS_CLK_RATE_MAX) || \ !defined (AUX_CLK_RATE_MIN) || !defined (AUX_CLK_RATE_MAX) || \ !defined (SYS_TIMER_CLK) || !defined (AUX_TIMER_CLK) || \ !defined (AMBA_RELOAD_TICKS) || !defined (SYS_TIMER_CLEAR) || \ !defined (SYS_TIMER_CTRL) || !defined (SYS_TIMER_LOAD) || \ !defined (SYS_TIMER_VALUE) || !defined (AUX_TIMER_CLEAR) || \ !defined (AUX_TIMER_CTRL) || !defined (AUX_TIMER_LOAD) || \ !defined (AUX_TIMER_VALUE) || !defined (SYS_TIMER_INT_LVL) || \ !defined (AUX_TIMER_INT_LVL) || !defined (AMBA_TIMER_SYS_TC_DISABLE) || \ !defined (AMBA_TIMER_SYS_TC_ENABLE) || \ !defined (AMBA_TIMER_AUX_TC_ENABLE) || !defined (AMBA_TIMER_AUX_TC_DISABLE)/*#error missing #defines in ambaTimer.c.*/#endif/********************************************************************************* 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){ /* acknowledge interrupt: any write to Clear Register clears interrupt */ /*AMBA_TIMER_WRITE (SYS_TIMER_CLEAR (AMBA_TIMER_BASE), 0);*/ /* If any routine attached via sysClkConnect(), call it */ /*ClearPending(BIT_TIMER4);*/ if (sysClkRoutine != NULL) (* 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. 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 == NULL) return OK; 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. */ /*AMBA_TIMER_WRITE( SYS_TIMER_CTRL (AMBA_TIMER_BASE), AMBA_TIMER_SYS_TC_DISABLE);*/ /* Disable the timer interrupt in the Interrupt Controller */ /*AMBA_TIMER_INT_DISABLE (SYS_TIMER_INT_LVL);*/ rTCON = ((rTCON&0xff0fffff)|0x600000); rINTMSK |= BIT_TIMER4; 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) { rTCNTB4 = ( rTCNTB4 & ~(0xffff) ) | (PCLK/(TIMER_PRESCALER+1)/TIMER_DIVIDER/sysClkTicksPerSecond); rTCON = ((rTCON&0xff0fffff)|0x600000); rTCON = ((rTCON&0xff0fffff)|0X500000); rINTMSK &= (~BIT_TIMER4); 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()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -