sa1501Timer.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:18k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* sa1501Timer.c - Digital Semiconductor SA-1501 timer library */
  2. /* Copyright 1996-1998 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01b,16apr99,jpd  fix bugs in sysTimestampLock and sysAuxClkDisable (SPR #26727).
  8. 01a,11nov98,jpd  Written, based on ambaTimer.c, version 01i.
  9. */
  10. /*
  11. DESCRIPTION
  12. This library contains routines to manipulate the timer functions on a
  13. SA-1501 chip with a mostly board-independent interface. This driver
  14. provides 3 main functions, system clock support, auxiliary clock
  15. support, and timestamp timer support.  The timestamp function is always
  16. conditional upon the INCLUDE_TIMESTAMP macro.
  17. The SA-1501 chip is a companion to the SA-1500 Mediaprocessor, and is
  18. found within the Acorn EBSA-1500 board.  It contains four timers,
  19. clocked at the same rate to provide software programmable interval
  20. timers via interrupt generation.
  21. The four timers are 25-bit incrementers which have an associated limit
  22. value register and a comparator between the two.  They increment
  23. continuously until the timer limit value is reached, at which time they
  24. flag an interrupt, reset to zero and then continue incrementing.
  25. Timer 3 has a watchdog option that, once enabled, can reset the entire
  26. system when it triggers. This is not used by VxWorks.
  27. The SA-1501 timer registers are described below under the symbolic
  28. names used herein.
  29. At any time, the current timer values may be read from the Value
  30. registers.
  31. REGISTERS:
  32. LIMIT: (read/write) The limit register extend from bits 24 down to 0.
  33. Writing the register will set the limit value for the appropriate
  34. timer.  Note that setting the limit value to less than the current
  35. timer count value will cause the timer to count up to its maximum value
  36. and wrap around.  Reads return the value previously programmed.
  37. Programming a limit register to 0 will eventually cause the counter to
  38. stop incrementing.  The counter will count from its current value up to
  39. its maximum value, wrap around and then be continuously reloaded with
  40. 0, as if it has stopped incrementing.
  41. VALUE: (read only) The value register gives the current value of the
  42. timer on bits 24 down to 0.  Writing to this register when not in test
  43. mode will have unpredictable results.
  44. RESET: (read/write) Reading or writing to the reset register has the
  45. effect of resetting the appropriate timer value to 0.  Reading returns
  46. the appropriate current timer value.
  47. The macros SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN, and
  48. AUX_CLK_RATE_MAX must be defined to provide parameter checking for the
  49. sys[Aux]ClkRateSet() routines.  The following macros must also be defined:
  50. SYS_TIMER_CLK /@ frequency of clock feeding SYS_CLK timer @/
  51. AUX_TIMER_CLK /@ frequency of clock feeding AUX_CLK @/
  52. SYS_TIMER_LIMIT /@ addresses of timer registers @/
  53. SYS_TIMER_VALUE /@ "" @/
  54. SYS_TIMER_RESET /@ "" @/
  55. AUX_TIMER_LIMIT /@ "" @/
  56. AUX_TIMER_VALUE /@ "" @/
  57. AUX_TIMER_RESET /@ "" @/
  58. SYS_TIMER_INT_LVL /@ interrupt level for sys Clk @/
  59. AUX_TIMER_INT_LVL /@ interrupt level for aux Clk @/
  60. The following may also be defined, if required:
  61. SA1501_TIMER_READ (reg, result) /@ read a timer register @/
  62. SA1501_TIMER_WRITE (reg, data) /@ write ... @/
  63. SA1501_TIMER_INT_ENABLE (level) /@ enable an interrupt @/
  64. SA1501_TIMER_INT_DISABLE (level) /@ disable an interrpt @/
  65. BSP
  66. Apart from defining such macros described above as are needed, the BSP
  67. will need to connect the interrupt handlers (typically in sysHwInit2()).
  68. e.g.
  69. .CS
  70.     /@ connect sys clock interrupt and auxiliary clock interrupt @/
  71.     intConnect (INUM_TO_IVEC (INT_VEC...), sysClkInt, 0);
  72.     intConnect (INUM_TO_IVEC (INT_VEC...), sysAuxClkInt, 0);
  73. .CE
  74. INCLUDES:
  75. sa1501Timer.h
  76. timestampDev.h
  77. SEE ALSO:
  78. .I "Digital Semiconductor SA-1501 Microprocessor Technical Manual"
  79. */
  80. /* includes */
  81. #include "drv/timer/sa1501Timer.h"
  82. #include "drv/timer/timestampDev.h"
  83. /* defines */
  84. #ifndef SA1501_TIMER_READ
  85. #define SA1501_TIMER_READ(reg, result) 
  86. ((result) = *((volatile UINT32 *)(reg)))
  87. #endif /* SA1501_TIMER_READ */
  88. #ifndef SA1501_TIMER_WRITE
  89. #define SA1501_TIMER_WRITE(reg, data) 
  90. (*((volatile UINT32 *)(reg)) = (data))
  91. #endif /* SA1501_TIMER_WRITE */
  92. #ifndef SA1501_TIMER_INT_ENABLE
  93. #define SA1501_TIMER_INT_ENABLE(level) intEnable (level)
  94. #endif
  95. #ifndef SA1501_TIMER_INT_DISABLE
  96. #define SA1501_TIMER_INT_DISABLE(level) intDisable (level)
  97. #endif
  98. /* locals */
  99. LOCAL FUNCPTR sysClkRoutine = NULL; /* routine to call on clock interrupt */
  100. LOCAL int sysClkArg = NULL; /* its argument */
  101. LOCAL int sysClkRunning = FALSE;
  102. LOCAL int sysClkConnected = FALSE;
  103. LOCAL int sysClkTicksPerSecond = 60;
  104. LOCAL FUNCPTR sysAuxClkRoutine = NULL;
  105. LOCAL int sysAuxClkArg = NULL;
  106. LOCAL int sysAuxClkRunning = FALSE;
  107. LOCAL int sysAuxClkTicksPerSecond = 100;
  108. #ifdef INCLUDE_TIMESTAMP
  109. LOCAL BOOL sysTimestampRunning   = FALSE;   /* timestamp running flag */
  110. #endif /* INCLUDE_TIMESTAMP */
  111. #if !defined (SYS_CLK_RATE_MIN) || !defined (SYS_CLK_RATE_MAX) || 
  112.     !defined (AUX_CLK_RATE_MIN) || !defined (AUX_CLK_RATE_MAX) || 
  113.     !defined (SYS_TIMER_CLK) || !defined (AUX_TIMER_CLK) || 
  114.     !defined (SYS_TIMER_LIMIT) || !defined (AUX_TIMER_LIMIT) || 
  115.     !defined (SYS_TIMER_VALUE) || !defined (SYS_TIMER_RESET) || 
  116.     !defined (AUX_TIMER_VALUE) || !defined (AUX_TIMER_RESET) || 
  117.     !defined (SYS_TIMER_INT_LVL) || 
  118.     !defined (AUX_TIMER_INT_LVL)
  119. #error missing #defines in sa1501Timer.c.
  120. #endif
  121. /*******************************************************************************
  122. *
  123. * sysClkInt - interrupt level processing for system clock
  124. *
  125. * This routine handles the system clock interrupt.  It is attached to the
  126. * clock interrupt vector by the routine sysClkConnect().
  127. *
  128. * RETURNS: N/A.
  129. */
  130. LOCAL void sysClkInt (void)
  131.     {
  132.     /* If any routine is attached via sysClkConnect(), call it */
  133.     if (sysClkRoutine != NULL)
  134. (* sysClkRoutine) (sysClkArg);
  135.     }
  136. /*******************************************************************************
  137. *
  138. * sysClkConnect - connect a routine to the system clock interrupt
  139. *
  140. * This routine specifies the interrupt service routine to be called at each
  141. * clock interrupt.  It does not enable system clock interrupts.
  142. * Normally it is called from usrRoot() in usrConfig.c to connect
  143. * usrClock() to the system clock interrupt.
  144. *
  145. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  146. *
  147. * SEE ALSO: intConnect(), usrClock(), sysClkEnable()
  148. */
  149. STATUS sysClkConnect
  150.     (
  151.     FUNCPTR routine, /* routine to be called at each clock interrupt */
  152.     int arg /* argument with which to call routine */
  153.     )
  154.     {
  155.     if (sysClkConnected == FALSE)
  156.      {
  157.      sysHwInit2 (); /* XXX for now -- needs to be in usrConfig.c */
  158.      sysClkConnected = TRUE;
  159.      }
  160.     sysClkRoutine = NULL; /* ensure routine not called with wrong arg */
  161.     sysClkArg   = arg;
  162. #if ((CPU_FAMILY == ARM) && ARM_THUMB)
  163.     /* set b0 so that sysClkConnect() can be used from shell */
  164.     sysClkRoutine = (FUNCPTR)((UINT32)routine | 1);
  165. #else
  166.     sysClkRoutine = routine;
  167. #endif /* CPU_FAMILY == ARM */
  168.     return OK;
  169.     }
  170. /*******************************************************************************
  171. *
  172. * sysClkDisable - turn off system clock interrupts
  173. *
  174. * This routine disables system clock interrupts.
  175. *
  176. * RETURNS: N/A
  177. *
  178. * SEE ALSO: sysClkEnable()
  179. */
  180. void sysClkDisable (void)
  181.     {
  182.     if (sysClkRunning)
  183. {
  184. /* Disable timer itself: set limit register to 0 */
  185. SA1501_TIMER_WRITE (SYS_TIMER_LIMIT (SA1501_TIMER_BASE), 0);
  186. /* Disable the timer interrupt in the Interrupt Controller */
  187. SA1501_TIMER_INT_DISABLE (SYS_TIMER_INT_LVL);
  188. sysClkRunning = FALSE;
  189. }
  190.     }
  191. /*******************************************************************************
  192. *
  193. * sysClkEnable - turn on system clock interrupts
  194. *
  195. * This routine enables system clock interrupts.
  196. *
  197. * RETURNS: N/A
  198. *
  199. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  200. */
  201. void sysClkEnable (void)
  202.     {
  203.     UINT32 tl;
  204.     if (!sysClkRunning)
  205. {
  206. /*
  207.  * Calculate the timer limit value:
  208.  * counter limit value = (clock rate / sysClkTicksPerSecond)
  209.  */
  210. tl = (SYS_TIMER_CLK / sysClkTicksPerSecond);
  211. /* Load Limit value into Timer registers */
  212. SA1501_TIMER_WRITE (SYS_TIMER_LIMIT (SA1501_TIMER_BASE), tl);
  213. /* reset timer value to zero */
  214. SA1501_TIMER_WRITE (SYS_TIMER_RESET (SA1501_TIMER_BASE), 0);
  215. /* enable clock interrupt in interrupt controller */
  216. SA1501_TIMER_INT_ENABLE (SYS_TIMER_INT_LVL);
  217. sysClkRunning = TRUE;
  218. }
  219.     }
  220. /*******************************************************************************
  221. *
  222. * sysClkRateGet - get the system clock rate
  223. *
  224. * This routine returns the interrupt rate of the system clock.
  225. *
  226. * RETURNS: The number of ticks per second of the system clock.
  227. *
  228. * SEE ALSO: sysClkRateSet(), sysClkEnable()
  229. */
  230. int sysClkRateGet (void)
  231.     {
  232.     return sysClkTicksPerSecond;
  233.     }
  234. /*******************************************************************************
  235. *
  236. * sysClkRateSet - set the system clock rate
  237. *
  238. * This routine sets the interrupt rate of the system clock.
  239. * It does not enable system clock interrupts.
  240. * Normally it is called by usrRoot() in usrConfig.c.
  241. *
  242. * RETURNS:
  243. * OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  244. *
  245. * SEE ALSO: sysClkRateGet(), sysClkEnable()
  246. */
  247. STATUS sysClkRateSet
  248.     (
  249.     int ticksPerSecond     /* number of clock interrupts per second */
  250.     )
  251.     {
  252.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  253. return ERROR;
  254.     sysClkTicksPerSecond = ticksPerSecond;
  255.     if (sysClkRunning)
  256. {
  257. sysClkDisable ();
  258. sysClkEnable ();
  259. }
  260.     return OK;
  261.     }
  262. /*******************************************************************************
  263. *
  264. * sysAuxClkInt - handle an auxiliary clock interrupt
  265. *
  266. * This routine handles an auxiliary clock interrupt.  It acknowledges the
  267. * interrupt and calls the routine installed by sysAuxClkConnect().
  268. *
  269. * RETURNS: N/A
  270. */
  271. LOCAL void sysAuxClkInt (void)
  272.     {
  273.     /* If any routine is attached via sysAuxClkConnect(), call it */
  274.     if (sysAuxClkRoutine != NULL)
  275. (*sysAuxClkRoutine) (sysAuxClkArg);
  276.     }
  277. /*******************************************************************************
  278. *
  279. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  280. *
  281. * This routine specifies the interrupt service routine to be called at each
  282. * auxiliary clock interrupt.  It also connects the clock error interrupt
  283. * service routine.
  284. *
  285. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  286. *
  287. * SEE ALSO: intConnect(), sysAuxClkEnable()
  288. */
  289. STATUS sysAuxClkConnect
  290.     (
  291.     FUNCPTR routine,    /* routine called at each aux clock interrupt */
  292.     int arg             /* argument with which to call routine        */
  293.     )
  294.     {
  295.     sysAuxClkRoutine = NULL; /* ensure routine not called with wrong arg */
  296.     sysAuxClkArg = arg;
  297. #if ((CPU_FAMILY == ARM) && ARM_THUMB)
  298.     /* set b0 so that sysAuxClkConnect() can be used from shell */
  299.     sysAuxClkRoutine = (FUNCPTR)((UINT32)routine | 1);
  300. #else
  301.     sysAuxClkRoutine = routine;
  302. #endif /* CPU_FAMILY == ARM */
  303.     return OK;
  304.     }
  305. /*******************************************************************************
  306. *
  307. * sysAuxClkDisable - turn off auxiliary clock interrupts
  308. *
  309. * This routine disables auxiliary clock interrupts.
  310. *
  311. * RETURNS: N/A
  312. *
  313. * SEE ALSO: sysAuxClkEnable()
  314. */
  315. void sysAuxClkDisable (void)
  316.     {
  317.     if (sysAuxClkRunning)
  318.         {
  319. /* Disable timer itself: set limit register to 0 */
  320. SA1501_TIMER_WRITE (AUX_TIMER_LIMIT (SA1501_TIMER_BASE), 0);
  321. /* Disable the timer interrupt in the Interrupt Controller */
  322. SA1501_TIMER_INT_DISABLE (AUX_TIMER_INT_LVL);
  323. sysAuxClkRunning = FALSE;
  324.         }
  325.     }
  326. /*******************************************************************************
  327. *
  328. * sysAuxClkEnable - turn on auxiliary clock interrupts
  329. *
  330. * This routine enables auxiliary clock interrupts.
  331. *
  332. * RETURNS: N/A
  333. *
  334. * SEE ALSO: sysAuxClkDisable()
  335. */
  336. void sysAuxClkEnable (void)
  337.     {
  338.     UINT32 tl;
  339.     if (!sysAuxClkRunning)
  340. {
  341. /*
  342.  * Calculate the timer limit value:
  343.  * counter limit value = (clock rate / sysAuxClkTicksPerSecond)
  344.  */
  345. tl = (AUX_TIMER_CLK / sysAuxClkTicksPerSecond);
  346. /* Load Limit value into Timer registers */
  347. SA1501_TIMER_WRITE (AUX_TIMER_LIMIT (SA1501_TIMER_BASE), tl);
  348. /* reset timer value to zero */
  349. SA1501_TIMER_WRITE (AUX_TIMER_RESET (SA1501_TIMER_BASE), 0);
  350. /* enable clock interrupt in interrupt controller */
  351. SA1501_TIMER_INT_ENABLE (AUX_TIMER_INT_LVL);
  352. sysAuxClkRunning = TRUE;
  353. }
  354.     }
  355. /*******************************************************************************
  356. *
  357. * sysAuxClkRateGet - get the auxiliary clock rate
  358. *
  359. * This routine returns the interrupt rate of the auxiliary clock.
  360. *
  361. * RETURNS: The number of ticks per second of the auxiliary clock.
  362. *
  363. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  364. */
  365. int sysAuxClkRateGet (void)
  366.     {
  367.     return sysAuxClkTicksPerSecond;
  368.     }
  369. /*******************************************************************************
  370. *
  371. * sysAuxClkRateSet - set the auxiliary clock rate
  372. *
  373. * This routine sets the interrupt rate of the auxiliary clock.  If the
  374. * auxiliary clock is currently enabled, the clock is disabled and then
  375. * re-enabled with the new rate.
  376. *
  377. * RETURNS: OK or ERROR.
  378. *
  379. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  380. */
  381. STATUS sysAuxClkRateSet
  382.     (
  383.     int ticksPerSecond     /* number of clock interrupts per second */
  384.     )
  385.     {
  386.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  387. return ERROR;
  388.     sysAuxClkTicksPerSecond = ticksPerSecond;
  389.     if (sysAuxClkRunning)
  390. {
  391. sysAuxClkDisable ();
  392. sysAuxClkEnable ();
  393. }
  394.     return OK;
  395.     }
  396. #ifdef INCLUDE_TIMESTAMP
  397. /*******************************************************************************
  398. *
  399. * sysTimestampConnect - connect a user routine to a timestamp timer interrupt
  400. *
  401. * This routine specifies the user interrupt routine to be called at each
  402. * timestamp timer interrupt.
  403. *
  404. * RETURNS: ERROR, always.
  405. */
  406. STATUS sysTimestampConnect
  407.     (
  408.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  409.     int arg             /* argument with which to call routine */
  410.     )
  411.     {
  412.     return ERROR;
  413.     }
  414. /*******************************************************************************
  415. *
  416. * sysTimestampEnable - enable a timestamp timer interrupt
  417. *
  418. * This routine enables timestamp timer interrupts and resets the counter.
  419. *
  420. * RETURNS: OK, always.
  421. *
  422. * SEE ALSO: sysTimestampDisable()
  423. */
  424. STATUS sysTimestampEnable (void)
  425.    {
  426.    if (sysTimestampRunning)
  427.       {
  428.       return OK;
  429.       }
  430.    if (!sysClkRunning)          /* timestamp timer is derived from the sysClk */
  431.       return ERROR;
  432.    sysTimestampRunning = TRUE;
  433.    return OK;
  434.    }
  435. /*******************************************************************************
  436. *
  437. * sysTimestampDisable - disable a timestamp timer interrupt
  438. *
  439. * This routine disables timestamp timer interrupts.
  440. *
  441. * RETURNS: OK, always.
  442. *
  443. * SEE ALSO: sysTimestampEnable()
  444. */
  445. STATUS sysTimestampDisable (void)
  446.     {
  447.     if (sysTimestampRunning)
  448.         sysTimestampRunning = FALSE;
  449.     return OK;
  450.     }
  451. /*******************************************************************************
  452. *
  453. * sysTimestampPeriod - get the period of a timestamp timer
  454. *
  455. * This routine gets the period of the timestamp timer, in ticks.  The
  456. * period, or terminal count, is the number of ticks to which the timestamp
  457. * timer counts before rolling over and restarting the counting process.
  458. *
  459. * RETURNS: The period of the timestamp timer in counter ticks.
  460. */
  461. UINT32 sysTimestampPeriod (void)
  462.     {
  463.     /*
  464.      * The period of the timestamp depends on the clock rate of the system
  465.      * clock.
  466.      */
  467.     return ((UINT32)(SYS_TIMER_CLK / sysClkTicksPerSecond));
  468.     }
  469. /*******************************************************************************
  470. *
  471. * sysTimestampFreq - get a timestamp timer clock frequency
  472. *
  473. * This routine gets the frequency of the timer clock, in ticks per
  474. * second.  The rate of the timestamp timer is set explicitly by the
  475. * hardware and typically cannot be altered.
  476. *
  477. * NOTE: Because the system clock serves as the timestamp timer,
  478. * the system clock frequency is also the timestamp timer frequency.
  479. *
  480. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  481. */
  482. UINT32 sysTimestampFreq (void)
  483.     {
  484.     return ((UINT32)SYS_TIMER_CLK);
  485.     }
  486. /*******************************************************************************
  487. *
  488. * sysTimestamp - get a timestamp timer tick count
  489. *
  490. * This routine returns the current value of the timestamp timer tick counter.
  491. * The tick count can be converted to seconds by dividing it by the return of
  492. * sysTimestampFreq().
  493. *
  494. * This routine should be called with interrupts locked.  If interrupts are
  495. * not locked, sysTimestampLock() should be used instead.
  496. *
  497. * RETURNS: The current timestamp timer tick count.
  498. *
  499. * SEE ALSO: sysTimestampFreq(), sysTimestampLock()
  500. */
  501. UINT32 sysTimestamp (void)
  502.     {
  503.     UINT32 t;
  504.     SA1501_TIMER_READ (SYS_TIMER_VALUE (SA1501_TIMER_BASE), t);
  505. #if defined (SA1501_TIMER_VALUE_MASK)
  506.     t &= SA1501_TIMER_VALUE_MASK;
  507. #endif
  508.     return t;
  509.     }
  510. /*******************************************************************************
  511. *
  512. * sysTimestampLock - lock interrupts and get the timestamp timer tick count
  513. *
  514. * This routine locks interrupts when the tick counter must be stopped
  515. * in order to read it or when two independent counters must be read.
  516. * It then returns the current value of the timestamp timer tick
  517. * counter.
  518. *
  519. * The tick count can be converted to seconds by dividing it by the return of
  520. * sysTimestampFreq().
  521. *
  522. * If interrupts are already locked, sysTimestamp() should be
  523. * used instead.
  524. *
  525. * RETURNS: The current timestamp timer tick count.
  526. *
  527. * SEE ALSO: sysTimestampFreq(), sysTimestamp()
  528. */
  529. UINT32 sysTimestampLock (void)
  530.     {
  531.     UINT32 t;
  532.     SA1501_TIMER_READ (SYS_TIMER_VALUE (SA1501_TIMER_BASE), t);
  533. #if defined (SA1501_TIMER_VALUE_MASK)
  534.     t &= SA1501_TIMER_VALUE_MASK;
  535. #endif
  536.     return t;
  537.     }
  538. #endif  /* INCLUDE_TIMESTAMP */