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

VxWorks

开发平台:

C/C++

  1. /* m68230Timer.c - MC68230 Parallel Interface/Timer (PIT) timer driver */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01g,25oct96,wlf  doc: cleanup.
  8. 01f,22jul96,dat  merged in timestamp driver.
  9. 01e,16apr94,dzb  changed the file name from m68230Timer.c m68230TimerTS.c
  10. 01d,07apr94,dzb  added delay loop for initial timer enable.
  11. 01c,01feb94,dzb  added interrupt locks around timer reset.
  12.                  added PIT_TS_RESET_DELAY delay loop (SPR #2997).
  13. 01b,10jan94,dzb  added timestamp driver support for Force boards (2 PI/T's).
  14. 01a,26jan93,caf  derived from version 01o of frc30/sysLib.c.
  15. */
  16. /*
  17. DESCRIPTION
  18. This library contains routines to manipulate the timer functions on the
  19. MC68230 (PIT) chip with a board-independent interface.  This library handles
  20. either the auxiliary clock facility or the timestamp timer facility.  To
  21. support the timestamp timer facility, two PIT chip timers are required.
  22. To support the auxiliary clock, the macro PIT_BASE_ADRS must be defined
  23. to indicate the base address of the PIT control registers. Additionally,
  24. the macro PIT_HZ must be defined to indicate the frequency at which the
  25. PIT hardware operates.  The macros AUX_CLK_RATE_MIN and AUX_CLK_RATE_MAX
  26. must be defined to provide parameter checking for sysAuxClkRateSet().
  27. To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must be
  28. defined, and the macros FRC_PIT1_BASE_ADRS and FRC_PIT2_BASE_ADRS must be
  29. defined to indicate the base addresses of the two required PIT chips.
  30. The PIT #2 timer is used as the timestamp counter, but must be stopped to be
  31. read, thereby introducing time skew.  The PIT #1 timer periodically resets
  32. the PIT #2 timer in an effort to alleviate cumulative time skew.  In addition
  33. to resetting the PIT #2 timer, the PIT #1 timer interrupt is used to
  34. alert the user to a timestamp timer reset (analogous to a timestamp rollover
  35. event).
  36. The PIT_TS_CORRECTION_PERIOD macro defines the period of the PIT
  37. #1 timer, which translates to the period of the timestamp timer reset
  38. (analogous to a timestamp rollover event).  The PIT_TS_SKEW macro
  39. can be used to compensate for time skew incurred when the PIT #2 timer
  40. is stopped in sysTimestamp() and sysTimestampLock().  The value
  41. of PIT_TS_SKEW is added to the stopped timestamp counter in an attempt to 
  42. make up for "lost" time.  The correct value to adjust the timestamp counter
  43. is not only board-dependent, it is influenced by CPU speed, caching mode,
  44. memory speed, etc.  The PIT_TS_RESET_DELAY macro defines the length of
  45. a wait loop in sysTimestampEnable().  The wait loop should be used on
  46. extremely fast target boards where a delay of execution is necessary for
  47. the timestamp timer operation to take effect.
  48. The timestamp timer and auxiliary clock facility must exist on separate PIT
  49. chip timers if they are to run concurrently.  That is, a particular PIT timer
  50. may not be used for both the auxiliary clock and the timestamp timer at the
  51. same time.
  52. */
  53. /* includes */
  54. #include "drv/timer/timerDev.h"
  55. #include "drv/timer/timestampDev.h"
  56. #include "drv/multi/m68230.h"
  57. #ifdef INCLUDE_TIMESTAMP
  58. /* defines */
  59. #ifndef PIT_TS_CORRECTION_PERIOD
  60. #define PIT_TS_CORRECTION_PERIOD 0x00008fff /* timestamp skew correction per. */
  61. #endif /* PIT_TS_CORRECTION_PERIOD */
  62. #ifndef PIT_TS_SKEW
  63. #define PIT_TS_SKEW 0 /* timestamp skew correction time */
  64. #endif /* PIT_TS_SKEW */
  65. /* locals */
  66. LOCAL BOOL    sysTimestampRunning = FALSE; /* running flag */
  67. LOCAL FUNCPTR sysTimestampRoutine = NULL; /* user rollover routine */
  68. LOCAL int     sysTimestampArg     = NULL; /* arg to user routine */
  69. #endif /* INCLUDE_TIMESTAMP */
  70. #ifdef PIT_BASE_ADRS
  71. /* locals */
  72. LOCAL FUNCPTR sysAuxClkRoutine = NULL; /* routine to call on clock interrupt */
  73. LOCAL int sysAuxClkArg = NULL; /* its argument */
  74. LOCAL int sysAuxClkRunning = FALSE;
  75. LOCAL int auxClkConnected = FALSE;
  76. LOCAL int auxClkTicksPerSecond = 60;
  77. #endif /* PIT_BASE_ADRS */
  78. #ifdef PIT_BASE_ADRS
  79. /*******************************************************************************
  80. *
  81. * sysAuxClkInt - interrupt level processing for auxiliary clock
  82. *
  83. * This routine handles auxiliary clock interrupts.
  84. *
  85. * RETURNS: N/A
  86. *
  87. * NOMANUAL
  88. */
  89. void sysAuxClkInt (void)
  90.     {
  91.     *PIT_TSR (PIT_BASE_ADRS) = PIT_ACK_INTR;    /* ack timer interrupt */
  92.     if (sysAuxClkRoutine != NULL)
  93.         (*sysAuxClkRoutine) (sysAuxClkArg);
  94.     }
  95. /*******************************************************************************
  96. *
  97. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  98. *
  99. * This routine specifies the interrupt service routine to be called at each
  100. * auxiliary clock interrupt.  It does not enable auxiliary clock
  101. * interrupts.
  102. *
  103. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  104. *
  105. * SEE ALSO: intConnect(), sysAuxClkEnable()
  106. */
  107. STATUS sysAuxClkConnect
  108.     (
  109.     FUNCPTR  routine, /* routine called at each aux. clock interrupt */
  110.     int      arg /* argument to auxiliary clock interrupt routine */
  111.     )
  112.     {
  113.     sysAuxClkRoutine   = routine;
  114.     sysAuxClkArg       = arg;
  115.     auxClkConnected    = TRUE;
  116.     return (OK);
  117.     }
  118. /*******************************************************************************
  119. *
  120. * sysAuxClkDisable - turn off auxiliary clock interrupts
  121. *
  122. * This routine disables auxiliary clock interrupts.
  123. *
  124. * RETURNS: N/A
  125. *
  126. * SEE ALSO: sysAuxClkEnable()
  127. */
  128. void sysAuxClkDisable (void)
  129.     {
  130.     if (sysAuxClkRunning)
  131. {
  132. * PIT_TCR (PIT_BASE_ADRS)   = TIMER_CTL_5; /* disable timer */
  133. sysAuxClkRunning     = FALSE;
  134. }
  135.     }
  136. /*******************************************************************************
  137. *
  138. * sysAuxClkEnable - turn on auxiliary clock interrupts
  139. *
  140. * This routine enables auxiliary clock interrupts.
  141. *
  142. * RETURNS: N/A
  143. *
  144. * SEE ALSO: sysAuxClkConnect(),sysAuxClkDisable(), sysAuxClkRateSet()
  145. */
  146. void sysAuxClkEnable (void)
  147.     {
  148.     unsigned int tc;
  149.     if (!sysAuxClkRunning)
  150. {
  151. /* divide-by-32 prescaler is used on CLK input */
  152.         tc = PIT_HZ / (auxClkTicksPerSecond * 32);
  153.         /* write the timer value */
  154.         * PIT_CPRL (PIT_BASE_ADRS) = LSB(tc);
  155.         * PIT_CPRM (PIT_BASE_ADRS) = MSB(tc);
  156.         * PIT_CPRH (PIT_BASE_ADRS) = (tc >> 16) & 0xff;
  157.         /* enable PIT1 timer */
  158.         * PIT_TCR (PIT_BASE_ADRS) = TIMER_CTL_5 | TIMER_ENABLE;
  159. sysAuxClkRunning = TRUE;
  160. }
  161.     }
  162. /*******************************************************************************
  163. *
  164. * sysAuxClkRateGet - get the auxiliary clock rate
  165. *
  166. * This routine returns the interrupt rate of the auxiliary clock.
  167. *
  168. * RETURNS: The number of ticks per second of the auxiliary clock.
  169. *
  170. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  171. */
  172. int sysAuxClkRateGet (void)
  173.     {
  174.     return (auxClkTicksPerSecond);
  175.     }
  176. /*******************************************************************************
  177. *
  178. * sysAuxClkRateSet - set the auxiliary clock rate
  179. *
  180. * This routine sets the interrupt rate of the auxiliary clock.
  181. * It does not enable auxiliary clock interrupts.
  182. *
  183. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  184. *
  185. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  186. */
  187. STATUS sysAuxClkRateSet
  188.     (
  189.     int ticksPerSecond     /* number of clock interrupts per second */
  190.     )
  191.     {
  192.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  193. return (ERROR);
  194.     auxClkTicksPerSecond = ticksPerSecond;
  195.     if (sysAuxClkRunning)
  196. {
  197. sysAuxClkDisable ();
  198. sysAuxClkEnable ();
  199. }
  200.     return (OK);
  201.     }
  202. #endif /*PIT_BASE_ADRS*/
  203. #ifdef INCLUDE_TIMESTAMP
  204. /*******************************************************************************
  205. *
  206. * sysTimestampInt - correction timer interrupt handler
  207. *
  208. * This routine handles the correction timer interrupt.  A user routine is
  209. * called, if one was connected by sysTimestampConnect().
  210. *
  211. * RETURNS: N/A
  212. */
  213. LOCAL void sysTimestampInt (void)
  214.     {
  215.     /* acknowledge the timer interrupt */
  216.     *PIT_TSR (FRC_PIT1_BASE_ADRS) = PIT_ACK_INTR;
  217.     sysTimestampEnable ();
  218.     if (sysTimestampRoutine != NULL) /* call user connected routine */
  219.         (*sysTimestampRoutine) (sysTimestampArg);
  220.     }
  221. /*******************************************************************************
  222. *
  223. * sysTimestampConnect - connect a user routine to the timestamp timer interrupt
  224. *
  225. * This routine specifies the user interrupt routine to be called at each
  226. * timestamp timer interrupt.  It does not enable the timestamp timer itself.
  227. *
  228. * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used.
  229. */
  230.  
  231. STATUS sysTimestampConnect
  232.     (
  233.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  234.     int arg             /* argument with which to call routine */
  235.     )
  236.     {
  237.     sysTimestampRoutine = routine;
  238.     sysTimestampArg = arg;
  239.     return (OK);
  240.     }
  241.  
  242. /*******************************************************************************
  243. *
  244. * sysTimestampEnable - initialize and enable the timestamp timer
  245. *
  246. * This routine connects the timestamp timer interrupt and initializes the
  247. * counter registers.  If the timestamp timer is already running, this routine
  248. * merely resets the timer counter.
  249. *
  250. * The rate of the timestamp timer should be set explicitly within the BSP,
  251. * in the sysHwInit() routine.  This routine does not intialize the timer
  252. * rate.
  253. *
  254. * RETURNS: OK, or ERROR if the timestamp timer cannot be enabled.
  255. */
  256. STATUS sysTimestampEnable (void)
  257.     {
  258.     int lockKey;
  259. #ifdef PIT_TS_RESET_DELAY
  260.     int ix;
  261. #endif /* PIT_TS_RESET_DELAY */
  262.     if (sysTimestampRunning)
  263.         {
  264.         lockKey = intLock (); /* LOCK INTERRUPTS */
  265.         *PIT_CPR (FRC_PIT2_BASE_ADRS) = 0x00ffffff;
  266.         /* disable the timer */
  267.         *PIT_TCR (FRC_PIT2_BASE_ADRS) = TIMER_CTL_4;
  268.         /* enable the timer */
  269.         *PIT_TCR (FRC_PIT2_BASE_ADRS) = TIMER_CTL_4 | TIMER_ENABLE;
  270. #ifdef PIT_TS_RESET_DELAY
  271.         /* wait for reset operation to take effect on FAST boards */
  272. for (ix = 0; ix < PIT_TS_RESET_DELAY; ix++)
  273.     ;
  274. #endif /* PIT_TS_RESET_DELAY */
  275.         intUnlock (lockKey); /* UNLOCK INTERRUPTS */
  276.         return (OK);
  277.         }
  278.     /* connect interrupt handler for correction timer */
  279.     (void) intConnect (INUM_TO_IVEC (INT_VEC_PIT1), sysTimestampInt, NULL);
  280.     *PIT_TVIR (FRC_PIT1_BASE_ADRS) = INT_VEC_PIT1;
  281.     sysTimestampRunning = TRUE;
  282.     /* set the timer periods */
  283.  
  284.     *PIT_CPR (FRC_PIT1_BASE_ADRS) = PIT_TS_CORRECTION_PERIOD;
  285.     *PIT_CPR (FRC_PIT2_BASE_ADRS) = 0x00ffffff;
  286.     /* reset counters */
  287.     /* enable the timers */
  288.     *PIT_TCR (FRC_PIT1_BASE_ADRS) = TIMER_CTL_5 | TIMER_ENABLE;
  289.     *PIT_TCR (FRC_PIT2_BASE_ADRS) = TIMER_CTL_4 | TIMER_ENABLE;
  290. #ifdef PIT_TS_RESET_DELAY
  291.     /* wait for reset operation to take effect on FAST boards */
  292.     for (ix = 0; ix < PIT_TS_RESET_DELAY; ix++)
  293.         ;
  294. #endif /* PIT_TS_RESET_DELAY */
  295.     return (OK);
  296.     }
  297. /*******************************************************************************
  298. *
  299. * sysTimestampDisable - disable the timestamp timer
  300. *
  301. * This routine disables the timestamp timer.  Interrupts are not disabled,
  302. * although the tick counter will not increment after the timestamp timer
  303. * is disabled, thus interrupts will no longer be generated.
  304. *
  305. * RETURNS: OK, or ERROR if the timestamp timer cannot be disabled.
  306. */
  307.  
  308. STATUS sysTimestampDisable (void)
  309.     {
  310.     if (sysTimestampRunning)
  311. {
  312.         sysTimestampRunning = FALSE;
  313.         /* disable both timers */
  314.         *PIT_TCR (FRC_PIT1_BASE_ADRS) = TIMER_CTL_5;
  315.         *PIT_TCR (FRC_PIT2_BASE_ADRS) = TIMER_CTL_4;
  316.         }
  317.  
  318.     return (OK);
  319.     }
  320. /*******************************************************************************
  321. *
  322. * sysTimestampPeriod - get the timestamp timer period
  323. *
  324. * This routine returns the period of the timestamp timer in ticks.
  325. * The period, or terminal count, is the number of ticks to which the timestamp
  326. * timer will count before rolling over and restarting the counting process.
  327. *
  328. * RETURNS: The period of the timestamp timer in counter ticks.
  329. */
  330.  
  331. UINT32 sysTimestampPeriod (void)
  332.     {
  333.     /* set to reasonable correction period */
  334.     return (PIT_TS_CORRECTION_PERIOD);
  335.     }
  336. /*******************************************************************************
  337. *
  338. * sysTimestampFreq - get the timestamp timer clock frequency
  339. *
  340. * This routine returns the frequency of the timer clock, in ticks per second.
  341. * The rate of the timestamp timer should be set explicitly within the BSP,
  342. * in the sysHwInit() routine.
  343. *
  344. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  345. */
  346.  
  347. UINT32 sysTimestampFreq (void)
  348.     {
  349.     UINT32 timerFreq;
  350.     timerFreq = CLOCK_FREQ / 32;
  351.     return (timerFreq);
  352.     }
  353.  
  354. /*******************************************************************************
  355. *
  356. * sysTimestamp - get the timestamp timer tick count
  357. *
  358. * This routine returns the current value of the timestamp timer tick counter.
  359. * The tick count can be converted to seconds by dividing by the return of
  360. * sysTimestampFreq().
  361. *
  362. * This routine should be called with interrupts locked.  If interrupts are
  363. * not already locked, sysTimestampLock() should be used instead.
  364. *
  365. * RETURNS: The current timestamp timer tick count.
  366. *
  367. * SEE ALSO: sysTimestampLock()
  368. */
  369.  
  370. UINT32 sysTimestamp (void)
  371.     {
  372.     UINT32 tick = 0;
  373.     register UINT32 * pTick;
  374.     register UINT32 * pPreload;
  375.     if (sysTimestampRunning)
  376.         {
  377.         pTick = PIT_CNTR (FRC_PIT2_BASE_ADRS);
  378.         pPreload = PIT_CPR (FRC_PIT2_BASE_ADRS);
  379.         *PIT_TCR (FRC_PIT2_BASE_ADRS) = TIMER_CTL_4;
  380.         tick = *pTick;
  381.         *pPreload = tick - PIT_TS_SKEW;
  382.         *PIT_TCR (FRC_PIT2_BASE_ADRS) = TIMER_CTL_4 | TIMER_ENABLE;
  383.         tick = 0xffffff - tick;
  384.         }
  385.     return (tick);
  386.     }
  387. /*******************************************************************************
  388. *
  389. * sysTimestampLock - get the timestamp timer tick count
  390. *
  391. * This routine returns the current value of the timestamp timer tick counter.
  392. * The tick count can be converted to seconds by dividing by the return of
  393. * sysTimestampFreq().
  394. *
  395. * This routine locks interrupts for cases where it is necessary to stop the
  396. * tick counter in order to read it, or when two independent counters must
  397. * be read.  If interrupts are already locked, sysTimestamp() should be
  398. * used instead.
  399. *
  400. * RETURNS: The current timestamp timer tick count.
  401. *
  402. * SEE ALSO: sysTimestamp()
  403. */
  404.  
  405. UINT32 sysTimestampLock (void)
  406.     {
  407.     UINT32 tick = 0;
  408.     register UINT32 * pTick;
  409.     register UINT32 * pPreload;
  410.     register UINT8 * pControl;
  411.     int lockKey;
  412.     if (sysTimestampRunning)
  413. {
  414.         pTick = PIT_CNTR (FRC_PIT2_BASE_ADRS);
  415.         pPreload = PIT_CPR (FRC_PIT2_BASE_ADRS);
  416.         pControl = (UINT8 *) PIT_TCR (FRC_PIT2_BASE_ADRS);
  417.         lockKey = intLock (); /* LOCK INTERRUPTS */
  418.         *pControl = TIMER_CTL_4;
  419.         tick = *pTick;
  420.         *pPreload = tick - PIT_TS_SKEW;
  421.         *pControl = TIMER_CTL_4 | TIMER_ENABLE;
  422.         intUnlock (lockKey); /* UNLOCK INTERRUPTS */
  423.         tick = 0xffffff - tick;
  424. }
  425.     return (tick);
  426.     }
  427. #endif /* INCLUDE_TIMESTAMP */