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

VxWorks

开发平台:

C/C++

  1. /* i8254Timer.c - Intel 8254 timer library */
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01d,13mar97,kkk  fixed warnings. 
  8. 01c,19apr95,ism  added WindView timestamp support
  9. 01b,14mar94,caf  fixed sysClkDisable() to clear counter 0 (SPR #2859).
  10. 01b,14mar94,caf  changed intDisable() to intLock() (SPR #2858).
  11. 01a,28sep92,caf  created by moving routines from version 02e of star/sysLib.c,
  12.  ansified.
  13. */
  14. /*
  15. DESCRIPTION
  16. This library contains routines to manipulate the timer functions on the
  17. Intel 8254 chip with a board-independent interface.  This library handles
  18. both the system clock and the auxiliary clock functions.
  19. The macros SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN, and
  20. AUX_CLK_RATE_MAX must be defined to provide parameter checking for the
  21. sys[Aux]ClkRateSet() routines.
  22. If the board includes an external write buffer, define SYS_WB_FLUSH when
  23. including this driver and implement sysWbFlush() in the BSP.
  24. INTERNAL
  25. This driver is not completely board-independent.  It relies on several
  26. macros found in the star BSP.  The way interrupts are controlled may also
  27. reflect the organization of MIPS R3000 targets such as the star.
  28. */
  29. /* defines */
  30. #define PERIOD(x) (((10 * TIMER2_HZ / (x)) + 5) / 10) /* rounded */
  31. /* locals */
  32. LOCAL FUNCPTR sysClkRoutine = NULL; /* routine to call on clock interrupt */
  33. LOCAL int sysClkArg = NULL; /* its argument */
  34. LOCAL int sysClkTicksPerSecond = 60; /* system clock rate */
  35. LOCAL BOOL sysClkConnected = FALSE;/* hooked up to interrupt yet? */
  36. LOCAL BOOL sysClkRunning = FALSE;/* system clock enabled? */
  37. LOCAL FUNCPTR sysAuxClkRoutine = NULL; /* routine to call on clock interrupt */
  38. LOCAL int sysAuxClkArg = NULL; /* its argument */
  39. LOCAL int auxClkTicksPerSecond = 60; /* auxiliary clock rate */
  40. LOCAL BOOL auxClkConnected = FALSE;/* hooked up to interrupt yet? */
  41. LOCAL BOOL auxClkRunning = FALSE;/* auxiliary clock enabled? */
  42. #ifdef INCLUDE_TIMESTAMP
  43. LOCAL BOOL    sysTimestampRunning = FALSE; /* running flag */
  44. LOCAL int     sysTimestampPeriodValue = NULL;  /* Max counter value */
  45. UINT32        sysTimestamp (void);
  46. #endif  /* INCLUDE_TIMESTAMP */
  47. /*******************************************************************************
  48. *
  49. * sysClkInt - interrupt level processing for timer 0.
  50. *
  51. * This routine handles the interrupts associated with the Intel 8254 chip.
  52. * It is attached to the interrupt vector by sysClkConnect().
  53. */
  54. LOCAL void sysClkInt (void)
  55.     {
  56.     FAST char staleValue; /* dummy read character */
  57.     if (sysClkRoutine != NULL)
  58.         (* sysClkRoutine) (sysClkArg); /* call system clock routine */
  59.     staleValue = *(volatile char *) TIM0_ACK_ADDR; /* acknowledge int */
  60.     }
  61. /*******************************************************************************
  62. *
  63. * sysClkConnect - connect a routine to the system clock interrupt
  64. *
  65. * This routine specifies the interrupt service routine to be called at each
  66. * clock interrupt.  It does not enable system clock interrupts.  Normally,
  67. * it is called from usrRoot() in usrConfig.c to connect usrClock() to the
  68. * system clock interrupt.
  69. *
  70. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  71. *
  72. * SEE ALSO: intConnect(), usrClock(), sysClkEnable()
  73. */
  74. STATUS sysClkConnect
  75.     (
  76.     FUNCPTR routine, /* routine called at each system clock interrupt */
  77.     int     arg /* argument with which to call with routine      */
  78.     )
  79.     {
  80.     sysHwInit2 (); /* XXX for now -- needs to be in usrConfig.c */
  81.     sysClkRoutine = routine;
  82.     sysClkArg     = arg;
  83.     sysClkConnected = TRUE;
  84.     return (OK);
  85.     }
  86. /*******************************************************************************
  87. *
  88. * sysClkDisable - turn off system clock interrupts
  89. *
  90. * This routine disables system clock interrupts.
  91. *
  92. * RETURNS: N/A
  93. *
  94. * SEE ALSO: sysClkEnable()
  95. */
  96. void sysClkDisable (void)
  97.     {
  98.     FAST volatile TIMER *pTimer = (volatile TIMER *) TIMER_BASE_ADRS;
  99.     FAST ULONG statusReg;
  100.     statusReg = intLock (); /* LOCK INTERRUPTS */
  101.     if (sysClkRunning)
  102. {
  103. /* stop timer 0, actually we get one more interrupt after this */
  104.         pTimer->cntrl_word = CW_SELECT (0) | CW_BOTHBYTE | 
  105. CW_MODE (MD_SWTRIGSB);
  106.         pTimer->counter0 = LSB (0);
  107.         pTimer->counter0 = MSB (0);
  108. #ifdef SYS_WB_FLUSH
  109. sysWbFlush ();
  110. #endif /* SYS_WB_FLUSH */
  111. #ifdef  INCLUDE_TIMESTAMP
  112. sysTimestampRunning = FALSE;
  113. #endif  /* INCLUDE_TIMESTAMP */
  114. sysClkRunning = FALSE;
  115. }
  116.     intUnlock (statusReg); /* UNLOCK INTERRUPTS */
  117.     }
  118. /*******************************************************************************
  119. *
  120. * sysClkEnable - turn on system clock interrupts
  121. *
  122. * This routine enables system clock interrupts.
  123. *
  124. * RETURNS: N/A
  125. *
  126. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  127. */
  128. void sysClkEnable (void)
  129.     {
  130.     FAST volatile TIMER *pTimer = (volatile TIMER *) TIMER_BASE_ADRS;
  131.     /* Initialize timer 0, primary clock */
  132.     if (!sysClkRunning)
  133. {
  134. /* setup device */
  135.         pTimer->cntrl_word = CW_SELECT (0) | CW_BOTHBYTE | CW_MODE (MD_RATEGEN);
  136.         pTimer->counter0 = LSB (PERIOD (sysClkTicksPerSecond));
  137.         pTimer->counter0 = MSB (PERIOD (sysClkTicksPerSecond));
  138. #ifdef SYS_WB_FLUSH
  139. sysWbFlush ();
  140. #endif /* SYS_WB_FLUSH */
  141.         sysClkRunning = TRUE;
  142.         intEnable (INT_LVL_TIMER0); /* turn on timer 0 ints just in case */
  143. }
  144.     }
  145. /*******************************************************************************
  146. *
  147. * sysClkRateGet - get the system clock rate
  148. *
  149. * This routine returns the interrupt rate of the system clock.
  150. *
  151. * RETURNS: The number of ticks per second of the system clock.
  152. *
  153. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  154. */
  155. int sysClkRateGet (void)
  156.     {
  157.     return (sysClkTicksPerSecond);
  158.     }
  159. /*******************************************************************************
  160. *
  161. * sysClkRateSet - set the system clock rate
  162. *
  163. * This routine sets the interrupt rate of the system clock.  It does not
  164. * enable system clock interrupts.  Normally, it is called by usrRoot() in
  165. * usrConfig.c.
  166. *
  167. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  168. *
  169. * SEE ALSO: sysClkEnable(), sysClkRateGet()
  170. */
  171. STATUS sysClkRateSet
  172.     (
  173.     int ticksPerSecond     /* number of clock interrupts per second */
  174.     )
  175.     {
  176.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  177.         return (ERROR);
  178.     sysClkTicksPerSecond = ticksPerSecond;
  179.      
  180.     if (sysClkRunning)
  181. {
  182. sysClkDisable ();
  183. sysClkEnable ();
  184. }
  185.     return (OK);
  186.     }
  187. /*******************************************************************************
  188. *
  189. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  190. *
  191. * This routine specifies the interrupt service routine to be called at each
  192. * auxiliary clock interrupt.  It does not enable auxiliary clock
  193. * interrupts.
  194. *
  195. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  196. *
  197. * SEE ALSO: intConnect(), sysClkEnable()
  198. */
  199. STATUS sysAuxClkConnect
  200.     (
  201.     FUNCPTR routine, /* routine called at each aux. clock interrupt */
  202.     int     arg /* argument with which to call routine         */
  203.     )
  204.     {
  205.     sysAuxClkRoutine   = routine;
  206.     sysAuxClkArg       = arg;
  207.     auxClkConnected  = TRUE;
  208.     return (OK);
  209.     }
  210. /********************************************************************************
  211. * sysAuxClkDisable - turn off auxiliary clock interrupts
  212. *
  213. * This routine disables auxiliary clock interrupts.
  214. *
  215. * RETURNS: N/A
  216. *
  217. * SEE ALSO: sysAuxClkEnable()
  218. */
  219.  
  220. void sysAuxClkDisable (void)
  221.     {
  222.     FAST volatile TIMER *pTimer = (volatile TIMER *) TIMER_BASE_ADRS;
  223.     FAST ULONG statusReg;
  224.     statusReg = intLock (); /* turn of timer 1 ints just in case */
  225.     if (auxClkRunning)
  226. {
  227. /* stop timer 1, actually we get one more interrupt after this */
  228.      
  229.         pTimer->cntrl_word = CW_SELECT (1) | CW_BOTHBYTE | 
  230.     CW_MODE (MD_SWTRIGSB);
  231.         pTimer->counter1 = LSB (0);
  232.         pTimer->counter1 = MSB (0);
  233. #ifdef SYS_WB_FLUSH
  234. sysWbFlush ();
  235. #endif /* SYS_WB_FLUSH */
  236. auxClkRunning = FALSE;
  237. }
  238.     intUnlock (statusReg);
  239.     }
  240. /********************************************************************************
  241. * sysAuxClkEnable - turn on auxiliary clock interrupts
  242. *
  243. * This routine enables auxiliary clock interrupts.
  244. *
  245. * RETURNS: N/A
  246. *
  247. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), susAuxClkRateSet()
  248. */
  249.  
  250. void sysAuxClkEnable (void)
  251.     {
  252.     FAST volatile TIMER *pTimer = (volatile TIMER *) TIMER_BASE_ADRS;
  253.     if (!auxClkRunning)
  254. {
  255.         /* Initialize timer 1, aux clock */
  256.         pTimer->cntrl_word = CW_SELECT (1) | CW_BOTHBYTE | CW_MODE (MD_RATEGEN);
  257.         pTimer->counter1 = LSB (PERIOD (auxClkTicksPerSecond));
  258.         pTimer->counter1 = MSB (PERIOD (auxClkTicksPerSecond));
  259. #ifdef SYS_WB_FLUSH
  260. sysWbFlush ();
  261. #endif /* SYS_WB_FLUSH */
  262.  
  263.         auxClkRunning = TRUE;
  264.         intEnable (INT_LVL_TIMER1); /* turn on timer 1 ints just in case */
  265. }
  266.     }
  267. /*******************************************************************************
  268. *
  269. * sysAuxClkRateGet - get the auxiliary clock rate
  270. *
  271. * This routine returns the interrupt rate of the auxiliary clock.
  272. *
  273. * RETURNS: The number of ticks per second of the auxiliary clock.
  274. *
  275. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  276. */
  277. int sysAuxClkRateGet (void)
  278.     {
  279.     return (auxClkTicksPerSecond);
  280.     }
  281. /*******************************************************************************
  282. *
  283. * sysAuxClkRateSet - set the auxiliary clock rate
  284. *
  285. * This routine sets the interrupt rate of the auxiliary clock.
  286. * It does not enable auxiliary clock interrupts.
  287. *
  288. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  289. *
  290. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  291. */
  292. STATUS sysAuxClkRateSet
  293.     (
  294.     FAST int ticksPerSecond     /* number of clock interrupts per second */
  295.     )
  296.     {
  297.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  298.         return (ERROR);
  299.     auxClkTicksPerSecond = ticksPerSecond;
  300.      
  301.     if (auxClkRunning)
  302. {
  303. sysAuxClkDisable ();
  304. sysAuxClkEnable ();
  305. }
  306.     return (OK);
  307.     }
  308. #ifdef  INCLUDE_TIMESTAMP
  309. /*******************************************************************************
  310. *
  311. * sysTimestampConnect - connect a user routine to the timestamp timer interrupt
  312. *
  313. * This routine specifies the user interrupt routine to be called at each
  314. * timestamp timer interrupt.  It does not enable the timestamp timer itself.
  315. *
  316. * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used.
  317. */
  318. STATUS sysTimestampConnect
  319.     (
  320.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  321.     int arg     /* argument with which to call routine */
  322.     )
  323.     {
  324. return (ERROR);
  325.     }
  326. /*******************************************************************************
  327. *
  328. * sysTimestampEnable - initialize and enable the timestamp timer
  329. *
  330. * This routine connects the timestamp timer interrupt and initializes the
  331. * counter registers.  If the timestamp timer is already running, this routine
  332. * merely resets the timer counter.
  333. *
  334. * The rate of the timestamp timer should be set explicitly within the BSP,
  335. * in the sysHwInit() routine.  This routine does not intialize the timer
  336. * rate.
  337. *
  338. * RETURNS: OK, or ERROR if the timestamp timer cannot be enabled.
  339. */
  340. STATUS sysTimestampEnable (void)
  341.     {
  342.     sysTimestampPeriodValue = TIMER2_HZ / sysClkTicksPerSecond;
  343.     if (sysTimestampRunning)
  344.     return (OK);
  345.     sysTimestampRunning = TRUE;
  346.     return (OK);
  347.     }
  348. /*******************************************************************************
  349. *
  350. * sysTimestampDisable - disable the timestamp timer
  351. *
  352. * This routine disables the timestamp timer.  Interrupts are not disabled,
  353. * although the tick counter will not increment after the timestamp timer
  354. * is disabled, thus interrupts will no longer be generated.
  355. *
  356. * RETURNS: OK, or ERROR if the timestamp timer cannot be disabled.
  357. */
  358. STATUS sysTimestampDisable (void)
  359.     {
  360.     if (sysTimestampRunning)
  361.         sysTimestampRunning = FALSE;
  362.     return (OK);
  363.     }
  364. /*******************************************************************************
  365. *
  366. * sysTimestampPeriod - get the timestamp timer period
  367. *
  368. * This routine returns the period of the timestamp timer in ticks.
  369. * The period, or terminal count, is the number of ticks to which the timestamp
  370. * timer will count before rolling over and restarting the counting process.
  371. *
  372. * RETURNS: The period of the timestamp timer in counter ticks.
  373. */
  374. UINT32 sysTimestampPeriod (void)
  375.     {
  376.     sysTimestampPeriodValue = TIMER2_HZ / sysClkTicksPerSecond;
  377.     return (sysTimestampPeriodValue);
  378.     }
  379. /*******************************************************************************
  380. *
  381. * sysTimestampFreq - get the timestamp timer clock frequency
  382. *
  383. * This routine returns the frequency of the timer clock, in ticks per second.
  384. * The rate of the timestamp timer should be set explicitly within the BSP,
  385. * in the sysHwInit() routine.
  386. *
  387. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  388. */
  389. UINT32 sysTimestampFreq (void)
  390.     {
  391.     return (TIMER2_HZ);
  392.     }
  393. /*******************************************************************************
  394. *
  395. * sysTimestamp - get the timestamp timer tick count
  396. *
  397. * This routine returns the current value of the timestamp timer tick counter.
  398. * The tick count can be converted to seconds by dividing by the return of
  399. * sysTimestampFreq().
  400. *
  401. * This routine should be called with interrupts locked.  If interrupts are
  402. * not already locked, sysTimestampLock() should be used instead.
  403. *
  404. * RETURNS: The current timestamp timer tick count.
  405. *
  406. * SEE ALSO: sysTimestampLock()
  407. */
  408. UINT32 sysTimestamp (void)
  409.     {
  410.     unsigned int count;
  411.     FAST volatile TIMER *pTimer = (volatile TIMER *) TIMER_BASE_ADRS;
  412.     /* select timer 0, and latch current count */
  413.     pTimer->cntrl_word = CW_SELECT (0) | CW_COUNTLCH |
  414. CW_MODE (MD_RATEGEN);
  415.     count = (unsigned int) pTimer->counter0;
  416.     count += (((unsigned int) pTimer->counter0) << 8);
  417.     count = (sysTimestampPeriodValue-1) - count;
  418.     return (count);
  419.     }
  420. /*******************************************************************************
  421. *
  422. * sysTimestampLock - get the timestamp timer tick count
  423. *
  424. * This routine returns the current value of the timestamp timer tick counter.
  425. * The tick count can be converted to seconds by dividing by the return of
  426. * sysTimestampFreq().
  427. *
  428. * This routine locks interrupts for cases where it is necessary to stop the
  429. * tick counter in order to read it, or when two independent counters must
  430. * be read.  If interrupts are already locked, sysTimestamp() should be
  431. * used instead.
  432. *
  433. * RETURNS: The current timestamp timer tick count.
  434. *
  435. * SEE ALSO: sysTimestamp()
  436. */
  437. UINT32 sysTimestampLock (void)
  438.     {
  439.     FAST ULONG statusReg;
  440.     unsigned int count;
  441.     FAST volatile TIMER *pTimer = (volatile TIMER *) TIMER_BASE_ADRS;
  442.     statusReg = intLock (); /* turn of timer 1 ints just in case */
  443.     /* select timer 0, and latch current count */
  444.     pTimer->cntrl_word = CW_SELECT (0) | CW_COUNTLCH |
  445.         CW_MODE (MD_RATEGEN);
  446.     count = (unsigned int) pTimer->counter0;
  447.     count += (((unsigned int) pTimer->counter0) << 8);
  448.     intUnlock (statusReg);
  449.     count = (sysTimestampPeriodValue-1) - count;
  450.     return (count);
  451.     }
  452. #endif  /* INCLUDE_TIMESTAMP */