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

VxWorks

开发平台:

C/C++

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