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

VxWorks

开发平台:

C/C++

  1. /* m5204Timer.c - Timer driver for Motorola MCF5204 */
  2. /* Copyright 1984-2000 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01c,06jul00,dh   changed IMR_Tn to IMR_TIMERn throughout.
  7. 01b,10jul97,mem  added timestamp driver support.
  8. 01a,09dec96,mem  written.
  9. */
  10. /*
  11. DESCRIPTION
  12. This is the timer for the MCF5204 ColdFire CPU.  It provides system clock,
  13. auxillary clock and timestamp functionality.
  14. If INCLUDE_M5204_SYS_CLK is defined, the system clock is provided.
  15. The macro SYS_CLK_TIMER must be defined (as 1 or 2) to select which
  16. on-chip timer to use for the system clock. The macros SYS_CLK_RATE_MIN
  17. and SYS_CLK_RATE_MAX must be defined to provide parameter checking for
  18. sysClkRateSet().
  19. If INCLUDE_M5204_AUX_CLK is defined, the auxillary clock is provided.
  20. The macro AUX_CLK_TIMER must be defined (as 1 or 2) to select which
  21. on-chip timer to use for the auxillary clock. The macros AUX_CLK_RATE_MIN
  22. and AUX_CLK_RATE_MAX must be defined to provide parameter checking for
  23. auxClkRateSet().
  24. If INCLUDE_M5204_TIMESTAMP is defined, a timestamp driver based on the
  25. system clock is provided.  If this option is selected,
  26. INCLUDE_M5204_SYS_CLK must also be defined.
  27. */
  28. #include "drv/multi/m5204.h"
  29. /* defines */
  30. #ifdef INCLUDE_M5204_SYS_CLK
  31. #ifndef SYS_CLK_TIMER
  32. #error "INCLUDE_M5204_SYS_CLK requires SYS_CLK_TIMER be defined"
  33. #endif
  34. #if ((SYS_CLK_TIMER != 1) && (SYS_CLK_TIMER != 2))
  35. #error "Bad value for SYS_CLK_TIMER, must be 1 or 2"
  36. #endif
  37. #endif
  38. #ifdef INCLUDE_M5204_AUX_CLK
  39. #ifndef AUX_CLK_TIMER
  40. #error "INCLUDE_M5204_AUX_CLK requires AUX_CLK_TIMER be defined"
  41. #endif
  42. #if ((AUX_CLK_TIMER != 1) && (AUX_CLK_TIMER != 2))
  43. #error "Bad value for AUX_CLK_TIMER, must be 1 or 2"
  44. #endif
  45. #endif
  46. #if (defined(INCLUDE_M5204_SYS_CLK) && defined(INCLUDE_M5204_AUX_CLK) 
  47.     && (SYS_CLK_TIMER == AUX_CLK_TIMER))
  48. #error "SYS_CLK_TIMER and AUX_CLK_TIMER must be different"
  49. #endif
  50. #if defined(INCLUDE_M5204_TIMESTAMP) && !defined(INCLUDE_M5204_SYS_CLK)
  51. #error "INCLUDE_M5204_TIMESTAMP requires INCLUDE_M5204_SYS_CLK"
  52. #endif
  53. /* locals */
  54. #ifdef INCLUDE_M5204_SYS_CLK
  55. LOCAL FUNCPTR sysClkRoutine = NULL; /* routine to call on clock int */
  56. LOCAL int sysClkArg = NULL; /* its argument */
  57. LOCAL int sysClkRunning = FALSE;
  58. LOCAL int sysClkConnected = FALSE;
  59. LOCAL int sysClkTicksPerSecond = 60;
  60. LOCAL int sysClkPrescale = 0;
  61. LOCAL int sysClkCount = 0;
  62. #endif /* INCLUDE_M5204_SYS_CLK */
  63. #ifdef INCLUDE_M5204_AUX_CLK
  64. LOCAL FUNCPTR sysAuxClkRoutine = NULL; /* routine to call on clock int */
  65. LOCAL int sysAuxClkArg = NULL; /* its argument */
  66. LOCAL int sysAuxClkRunning = FALSE;
  67. LOCAL int sysAuxClkConnected = FALSE;
  68. LOCAL int sysAuxClkTicksPerSecond = 60;
  69. LOCAL int sysAuxClkPrescale = 0;
  70. LOCAL int sysAuxClkCount = 0;
  71. #endif /* INCLUDE_M5204_AUX_CLK */
  72. #ifdef INCLUDE_M5204_TIMESTAMP
  73. #include "drv/timer/timestampDev.h"
  74. LOCAL BOOL sysTimestampRunning = FALSE; 
  75. #endif /* INCLUDE_M5204_TIMESTAMP */
  76. #ifdef INCLUDE_M5204_SYS_CLK
  77. /*****************************************************************************
  78. *
  79. * sysClkInt - interrupt level processing for system clock
  80. *
  81. * This routine handles the system clock interrupt.  It is attached to the
  82. * clock interrupt vector by the routine sysClkConnect().
  83. */
  84. LOCAL void sysClkInt (void)
  85.     {
  86.     /* Clear interrupt condition */
  87.     *M5204_TIMER_TER(SIM_BASE, SYS_CLK_TIMER) = 0x02;
  88.     
  89.     if (sysClkRoutine != NULL)
  90. (* sysClkRoutine) (sysClkArg);
  91.     }
  92. /*****************************************************************************
  93. *
  94. * sysClkConnect - connect a routine to the system clock interrupt
  95. *
  96. * This routine specifies the interrupt service routine to be called at each
  97. * clock interrupt.  Normally, it is called from usrRoot() in usrConfig.c to 
  98. * connect usrClock() to the system clock interrupt.
  99. *
  100. * RETURN: OK, or ERROR if the routine cannot be connected to the interrupt.
  101. *
  102. * SEE ALSO: intConnect(), usrClock(), sysClkEnable()
  103. */
  104. STATUS sysClkConnect
  105.     (
  106.     FUNCPTR routine, /* routine to be called at each clock interrupt */
  107.     int arg /* argument with which to call routine */
  108.     )
  109.     {
  110.     sysHwInit2 (); /* XXX for now -- needs to be in usrConfig.c */
  111.     sysClkRoutine   = routine;
  112.     sysClkArg     = arg;
  113.     sysClkConnected = TRUE;
  114.     return (OK);
  115.     }
  116. /*****************************************************************************
  117. *
  118. * sysClkDisable - turn off system clock interrupts
  119. *
  120. * This routine disables system clock interrupts.
  121. *
  122. * RETURNS: N/A
  123. *
  124. * SEE ALSO: sysClkEnable()
  125. */
  126. void sysClkDisable (void)
  127.     {
  128.     if (sysClkRunning && sysClkConnected)
  129. {
  130. #if (SYS_CLK_TIMER == 1)
  131. *M5204_SIM_IMR(SIM_BASE) |= M5204_IMR_TIMER1;
  132. #else /* (SYS_CLK_TIMER == 1) */
  133. *M5204_SIM_IMR(SIM_BASE) |= M5204_IMR_TIMER2;
  134. #endif /* (SYS_CLK_TIMER == 1) */
  135. /* Clear CLK1-CLK0 to stop timer. */
  136. *M5204_TIMER_TMR(SIM_BASE, SYS_CLK_TIMER) = 0x00;
  137. sysClkRunning = FALSE;
  138. }
  139.     }
  140. /*****************************************************************************
  141. *
  142. * sysClkEnable - turn on system clock interrupts
  143. *
  144. * This routine enables system clock interrupts.
  145. *
  146. * RETURNS: N/A
  147. *
  148. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  149. */
  150. void sysClkEnable (void)
  151.     {
  152.     if (!sysClkRunning && sysClkConnected)
  153. {
  154. /* Disable timer */
  155. *M5204_TIMER_TMR(SIM_BASE, SYS_CLK_TIMER) = 0x00;
  156. /* Reset timer count */
  157. *M5204_TIMER_TCN(SIM_BASE, SYS_CLK_TIMER) = 0x00;
  158. sysClkPrescale = (MASTER_CLOCK / sysClkTicksPerSecond) >> 16;
  159. sysClkCount = ((MASTER_CLOCK / (sysClkPrescale + 1))
  160.        / sysClkTicksPerSecond);
  161. /* Set reference register */
  162. *M5204_TIMER_TRR(SIM_BASE, SYS_CLK_TIMER) = sysClkCount;
  163. /* Start timer */
  164. *M5204_TIMER_TMR(SIM_BASE, SYS_CLK_TIMER) = 0x1b | (sysClkPrescale<<8);
  165. #if (SYS_CLK_TIMER == 1)
  166. *M5204_SIM_IMR(SIM_BASE) &= ~M5204_IMR_TIMER1;
  167. #else /* (SYS_CLK_TIMER == 1) */
  168. *M5204_SIM_IMR(SIM_BASE) &= ~M5204_IMR_TIMER2;
  169. #endif /* (SYS_CLK_TIMER == 1) */
  170. sysClkRunning = TRUE;
  171. }
  172.     }
  173. /*****************************************************************************
  174. *
  175. * sysClkRateGet - get the system clock rate
  176. *
  177. * This routine returns the system clock rate.
  178. *
  179. * RETURNS: The number of ticks per second of the system clock.
  180. *
  181. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  182. */
  183. int sysClkRateGet (void)
  184.     
  185.     {
  186.     return (sysClkTicksPerSecond);
  187.     }
  188. /*****************************************************************************
  189. *
  190. * sysClkRateSet - set the system clock rate
  191. *
  192. * This routine sets the interrupt rate of the system clock.
  193. * It is called by usrRoot() in usrConfig.c.
  194. *
  195. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  196. *
  197. * SEE ALSO: sysClkEnable(), sysClkRateGet()
  198. */
  199. STATUS sysClkRateSet
  200.     (
  201.     int ticksPerSecond     /* number of clock interrupts per second */
  202.     )
  203.     {
  204.     UINT count, prescale;
  205.     if (ticksPerSecond > SYS_CLK_RATE_MAX || ticksPerSecond < SYS_CLK_RATE_MIN)
  206. return (ERROR);
  207.     prescale = (MASTER_CLOCK / ticksPerSecond) >> 16;
  208.     if (prescale & ~0x00ff)
  209. return (ERROR);
  210.     count = (MASTER_CLOCK / (prescale + 1)) / ticksPerSecond;
  211.     if (count & 0xffff0000)
  212. return (ERROR);
  213.     sysClkTicksPerSecond = ticksPerSecond;
  214.     if (sysClkRunning)
  215. {
  216. sysClkDisable ();
  217. sysClkEnable ();
  218. }
  219.     return (OK);
  220.     }
  221. #endif /* INCLUDE_M5204_SYS_CLK */
  222. #ifdef INCLUDE_M5204_AUX_CLK
  223. /*****************************************************************************
  224. *
  225. * sysAuxClkInt - interrupt level processing for system clock
  226. *
  227. * This routine handles the aux clock interrupt.  It is attached to the
  228. * clock interrupt vector by the routine sysAuxClkConnect().
  229. */
  230. LOCAL void sysAuxClkInt (void)
  231.     {
  232.     /* Clear interrupt condition */
  233.     *M5204_TIMER_TER(SIM_BASE, AUX_CLK_TIMER) = 0x02;
  234.     
  235.     if (sysAuxClkRoutine != NULL)
  236. (* sysAuxClkRoutine) (sysAuxClkArg);
  237.     }
  238. /*****************************************************************************
  239. *
  240. * sysAuxClkConnect - connect a routine to the aux clock interrupt
  241. *
  242. * This routine specifies the interrupt service routine to be called at each
  243. * aux clock interrupt.
  244. *
  245. * RETURN: OK, or ERROR if the routine cannot be connected to the interrupt.
  246. *
  247. * SEE ALSO: intConnect(), usrClock(), sysAuxClkEnable()
  248. */
  249. STATUS sysAuxClkConnect
  250.     (
  251.     FUNCPTR routine, /* routine to be called at each clock interrupt */
  252.     int arg /* argument with which to call routine */
  253.     )
  254.     {
  255.     sysAuxClkRoutine   = routine;
  256.     sysAuxClkArg       = arg;
  257.     sysAuxClkConnected = TRUE;
  258.     return (OK);
  259.     }
  260. /*****************************************************************************
  261. *
  262. * sysAuxClkDisable - turn off aux clock interrupts
  263. *
  264. * This routine disables auxilliary clock interrupts.
  265. *
  266. * RETURNS: N/A
  267. *
  268. * SEE ALSO: sysAuxClkEnable()
  269. */
  270. void sysAuxClkDisable (void)
  271.     {
  272.     if (sysAuxClkRunning && sysAuxClkConnected)
  273. {
  274. #if (AUX_CLK_TIMER == 1)
  275. *M5204_SIM_IMR(SIM_BASE) |= M5204_IMR_TIMER1;
  276. #else /* (AUX_CLK_TIMER == 1) */
  277. *M5204_SIM_IMR(SIM_BASE) |= M5204_IMR_TIMER2;
  278. #endif /* (AUX_CLK_TIMER == 1) */
  279. /* Clear CLK1-CLK0 to stop timer. */
  280. *M5204_TIMER_TMR(SIM_BASE, AUX_CLK_TIMER) = 0x00;
  281. sysAuxClkRunning = FALSE;
  282. }
  283.     }
  284. /*****************************************************************************
  285. *
  286. * sysAuxClkEnable - turn on system clock interrupts
  287. *
  288. * This routine enables system clock interrupts.
  289. *
  290. * RETURNS: N/A
  291. *
  292. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  293. */
  294. void sysAuxClkEnable (void)
  295.     {
  296.     if (!sysAuxClkRunning && sysAuxClkConnected)
  297. {
  298. /* Disable timer */
  299. *M5204_TIMER_TMR(SIM_BASE, AUX_CLK_TIMER) = 0x00;
  300. /* Reset timer count */
  301. *M5204_TIMER_TCN(SIM_BASE, AUX_CLK_TIMER) = 0x00;
  302. sysAuxClkPrescale = (MASTER_CLOCK / sysAuxClkTicksPerSecond) >> 16;
  303. sysAuxClkCount = ((MASTER_CLOCK / (sysAuxClkPrescale + 1))
  304.   / sysAuxClkTicksPerSecond);
  305. /* Set reference register */
  306. *M5204_TIMER_TRR(SIM_BASE, AUX_CLK_TIMER) = sysAuxClkCount;
  307. /* Start timer */
  308. *M5204_TIMER_TMR(SIM_BASE, AUX_CLK_TIMER) =
  309.   0x1b | (sysAuxClkPrescale<<8);
  310. #if (AUX_CLK_TIMER == 1)
  311. *M5204_SIM_IMR(SIM_BASE) &= ~M5204_IMR_TIMER1;
  312. #else /* (AUX_CLK_TIMER == 1) */
  313. *M5204_SIM_IMR(SIM_BASE) &= ~M5204_IMR_TIMER2;
  314. #endif /* (AUX_CLK_TIMER == 1) */
  315. sysAuxClkRunning = TRUE;
  316. }
  317.     }
  318. /*****************************************************************************
  319. *
  320. * sysAuxClkRateGet - get the system clock rate
  321. *
  322. * This routine returns the system clock rate.
  323. *
  324. * RETURNS: The number of ticks per second of the system clock.
  325. *
  326. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  327. */
  328. int sysAuxClkRateGet (void)
  329.     
  330.     {
  331.     return (sysAuxClkTicksPerSecond);
  332.     }
  333. /*****************************************************************************
  334. *
  335. * sysAuxClkRateSet - set the system clock rate
  336. *
  337. * This routine sets the interrupt rate of the system clock.
  338. * It is called by usrRoot() in usrConfig.c.
  339. *
  340. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  341. *
  342. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  343. */
  344. STATUS sysAuxClkRateSet
  345.     (
  346.     int ticksPerSecond     /* number of clock interrupts per second */
  347.     )
  348.     {
  349.     UINT count, prescale;
  350.     if (ticksPerSecond > AUX_CLK_RATE_MAX ||
  351. ticksPerSecond < AUX_CLK_RATE_MIN)
  352. return (ERROR);
  353.     prescale = (MASTER_CLOCK / ticksPerSecond) >> 16;
  354.     if (prescale & ~0x00ff)
  355. return (ERROR);
  356.     count = (MASTER_CLOCK / (prescale + 1)) / ticksPerSecond;
  357.     if (count & 0xffff0000)
  358. return (ERROR);
  359.     sysAuxClkTicksPerSecond = ticksPerSecond;
  360.     if (sysAuxClkRunning)
  361. {
  362. sysAuxClkDisable ();
  363. sysAuxClkEnable ();
  364. }
  365.     return (OK);
  366.     }
  367. #endif /* INCLUDE_M5204_AUX_CLK */
  368. #ifdef INCLUDE_M5204_TIMESTAMP
  369. /**************************************************************************
  370. *
  371. * sysTimestampConnect - connect a user routine to the timestamp timer 
  372. *                       interrupt
  373. *
  374. * This routine specifies the user interrupt routine to be called at each
  375. * timestamp timer interrupt. It does not enable the timestamp timer itself.
  376. *
  377. * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used.
  378. */
  379. STATUS sysTimestampConnect
  380.     (
  381.     FUNCPTR routine, /* routine called at each timestamp timer interrupt */
  382.     int arg          /* argument with which to call routine */
  383.     )
  384.     {
  385.     return (ERROR);
  386.     }
  387. /**************************************************************************
  388. *
  389. * sysTimestampEnable - initialize and enable the timestamp timer
  390. *
  391. * This routine connects the timestamp timer interrupt and initializes the
  392. * counter registers. If the timestamp timer is already running, this 
  393. * routine merely resets the timer counter.
  394. *
  395. * Set the rate of the timestamp timer input clock explicitly within the 
  396. * BSP, in the sysHwInit() routine. This routine does not initialize 
  397. * the timer clock rate.
  398. *
  399. * RETURNS: OK, or ERROR if the timestamp timer cannot be enabled.
  400. */
  401. STATUS sysTimestampEnable(void)
  402.     {
  403.     if (sysTimestampRunning)
  404. return (OK);
  405.     sysTimestampRunning = TRUE;
  406.     sysClkEnable (); /* ensure the system clock is running */
  407.     return (OK);
  408.     }
  409. /**************************************************************************
  410. *
  411. * sysTimestampDisable - disable the timestamp timer
  412. *
  413. * This routine disables the timestamp timer. Interrupts are not disabled.
  414. * However, the tick counter will not increment after the timestamp timer
  415. * is disabled, ensuring that interrupts are no longer generated.
  416. * routine merely resets the timer counter.
  417. *
  418. * RETURNS: OK, or ERROR if the timestamp timer cannot be disabled.
  419. */
  420. STATUS sysTimestampDisable (void)
  421.     {
  422.     sysTimestampRunning = FALSE;
  423.     return (ERROR);
  424.     }
  425. /**************************************************************************
  426. *
  427. * sysTimestampPeriod - get the timestamp timer period
  428. *
  429. * This routine returns the period of the timer in timestamp ticks.
  430. * The period, or terminal count, is the number of ticks to which the 
  431. * timestamp timer counts before rolling over and restarting the counting
  432. * process.
  433. *
  434. * RETURNS: The period of the timer in timestamp ticks.
  435. */
  436. UINT32 sysTimestampPeriod (void)
  437.     {
  438.     /* Return the system clock period in timestamp ticks */
  439.     return (sysTimestampFreq () / sysClkRateGet ());
  440.     }
  441. /**************************************************************************
  442. *
  443. * sysTimestampFreq - get the timestamp timer clock frequency
  444. *
  445. * This routine returns the frequency of the timer clock, in ticks per 
  446. * second. The rate of the timestamp timer should be set explicitly in the 
  447. * BSP, in the sysHwInit() routine.
  448. *
  449. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  450. */
  451. UINT32 sysTimestampFreq (void)
  452.     {
  453.     UINT32 prescale;
  454.     /*
  455.      * Return the timestamp tick output frequency here.
  456.      * This value can be determined from the following equation:
  457.      *     timerFreq = clock input frequency / prescaler
  458.      *
  459.      * When possible, read the clock input frequency and prescaler values
  460.      * directly from chip registers.
  461.      */
  462.     prescale = ((*M5204_TIMER_TMR(SIM_BASE, SYS_CLK_TIMER) >> 8) + 1);
  463.     return (MASTER_CLOCK / prescale);
  464.     }
  465. /**************************************************************************
  466. *
  467. * sysTimestamp - get the timestamp timer tick count
  468. *
  469. * This routine returns the current value of the timestamp timer tick counter.
  470. * The tick count can be converted to seconds by dividing by the return of
  471. * sysTimestampFreq().
  472. *
  473. * Call this routine with interrupts locked. If interrupts are 
  474. * not already locked, use sysTimestampLock() instead.
  475. *
  476. * RETURNS: The current timestamp timer tick count.
  477. * SEE ALSO: sysTimestampLock()
  478. */
  479. UINT32 sysTimestamp (void)
  480.     {
  481.     return (*M5204_TIMER_TCN(SIM_BASE, SYS_CLK_TIMER));
  482.     }
  483. /**************************************************************************
  484. *
  485. * sysTimestampLock - lock interrupts for reading the timer
  486. *
  487. * This routine returns the current value of the timestamp timer tick counter.
  488. * The tick count can be converted to seconds by dividing by the return of
  489. * sysTimestampFreq().
  490. *
  491. * Call this routine with interrupts locked. If interrupts are 
  492. * not already locked, use sysTimestampLock() instead.
  493. *
  494. * RETURNS: The current timestamp timer tick count.
  495. * SEE ALSO: sysTimestampLock()
  496. */
  497. UINT32 sysTimestampLock (void)
  498.     {
  499.     int lockKey;
  500.     UINT32 value;
  501.     lockKey = intLock();
  502.     value = sysTimestamp ();
  503.     intUnlock (lockKey);
  504.     
  505.     return (value);
  506.     }
  507. #endif /* INCLUDE_M5204_TIMESTAMP */