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

VxWorks

开发平台:

C/C++

  1. /* ppc860Timer.c - PowerPC/860 timer library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01d,22dec01,g_h  Remove compilation warning
  8. 01c,09oct01,dtr  Removing unwanted NULLs(funcptrs) when int required.
  9.  Also put in fix for SPR65678.
  10. 01b,15sep01,dat  Use new vxDecReload function
  11. 01a,11nov97,map  written from ppcDecTimer.c (v 01n), and m68360Timer.c (v 01f).
  12. */
  13. /*
  14. DESCRIPTION
  15. This library provides PowerPC/860 system clock, auxiliary clock, and timestamp
  16. support.
  17. The PowerPC decrementer timer, is used to implement a system clock, and CPM
  18. TIMER2 for a 16-bit auxiliary clock. CPM timers TIMER3, and TIMER4
  19. are cascaded into a free-running 32-bit timer for timestamp support.
  20. The macro, DEC_CLOCK_FREQ, the frequency of the decrementer input clock, must
  21. be defined before using this module. The macro, DEC_CLK_TO_INC, the ratio
  22. between the number of decrementer input clock cycles and one counter
  23. increment, may be redefined prior to including this file in sysLib.c.
  24. The macros SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN, and
  25. AUX_CLK_RATE_MAX must be defined to provide parameter checking for
  26. sysClkRateSet(), and sysAuxClkRateSet() routines.
  27. To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must be
  28. defined. 
  29. To enable dynamic bus clock rates, the BSP should set the macro,
  30. PPC_TMR_RATE_SET_ADJUST, to call an apropriate routine. This call, will be
  31. made each time sysClkRateSet() is called. E.g. To use sysClkRateAdjust to
  32. compute a correct value for sysDecClkFrequency.
  33.   #define PPC_TMR_RATE_SET_ADJUST sysClkRateAdjust (&sysDecClkFrequency)
  34. The macro, PPC_TMR_RATE_SET_ADJUST, is by default not defined.
  35. INCLUDE FILES: timerDev.h, vxPpcLib.h
  36.    
  37. SEE ALSO:
  38. .pG "Configuration"
  39. */
  40. /* includes */
  41. #include "arch/ppc/vxPpcLib.h"
  42. #include "drv/timer/timerDev.h"
  43. /* local defines */
  44. #ifndef DEC_CLK_TO_INC
  45. #define DEC_CLK_TO_INC 4 /* # bus clks per increment */
  46. #endif
  47. #ifndef DEC_CLOCK_FREQ
  48. #define DEC_CLOCK_FREQ 33333333 /* 33.33 Mhz default */
  49. #endif /* DEC_CLOCK_FREQ */
  50. #define CPM_MEM_BASE INTERNAL_MEM_MAP_ADDR
  51. /* extern declarations */
  52. IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
  53. /* locals */
  54. LOCAL int  sysClkTicksPerSecond  = 60;   /* default 60 ticks/second */
  55. LOCAL FUNCPTR sysClkRoutine = NULL;
  56. LOCAL int sysClkArg = 0;
  57. LOCAL BOOL sysClkConnectFirstTime = TRUE;
  58. LOCAL int       decCountVal = 10000000; /* default dec value */
  59. LOCAL BOOL sysClkRunning  = FALSE;
  60. LOCAL int  sysDecClkFrequency = DEC_CLOCK_FREQ/DEC_CLK_TO_INC;
  61. LOCAL FUNCPTR sysAuxClkRoutine = NULL;
  62. LOCAL int sysAuxClkArg = 0;
  63. LOCAL BOOL sysAuxClkRunning = FALSE;
  64. LOCAL BOOL sysAuxClkIntConnected = FALSE;
  65. LOCAL int sysAuxClkTicksPerSecond = 60;
  66. #ifdef INCLUDE_TIMESTAMP
  67. LOCAL BOOL sysTimestampRunning   = FALSE;   /* timestamp running flag */
  68. LOCAL FUNCPTR sysTimestampRoutine = NULL;
  69. LOCAL int sysTimestampArg = 0;
  70. LOCAL BOOL sysTimestampIntConnected = FALSE;
  71. #endif /* INCLUDE_TIMESTAMP */
  72. /*******************************************************************************
  73. *
  74. * sysClkInt - clock interrupt handler
  75. *
  76. * This routine handles the clock interrupt on the PowerPC architecture. It is
  77. * attached to the decrementer vector by the routine sysClkConnect().
  78. *
  79. * RETURNS : N/A
  80. */
  81. LOCAL void sysClkInt (void)
  82.     {
  83. #ifdef USE_KEYED_REGS
  84.     vxKeyedDecReload(decCountVal);
  85. #else
  86.     vxDecReload (decCountVal); /* reload decrementer */
  87. #endif /*USE_KEYED_REGS*/
  88.     /* execute the system clock routine */
  89.     if (sysClkRunning && (sysClkRoutine != NULL))
  90. (*(FUNCPTR) 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. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  101. *
  102. * SEE ALSO: intConnect(), usrClock(), sysClkEnable()
  103. */
  104.     
  105. STATUS sysClkConnect
  106.     (
  107.     FUNCPTR  routine, /* routine to connect */
  108.     int  arg /* argument for the routine */
  109.     )
  110.     {
  111.     if (sysClkConnectFirstTime)
  112. {
  113. sysHwInit2();
  114. sysClkConnectFirstTime = FALSE;
  115.         excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_DECR, (VOIDFUNCPTR) sysClkInt);
  116. }
  117.     sysClkRoutine = routine;
  118.     sysClkArg = arg;
  119.     return (OK);
  120.     }
  121. /******************************************************************************
  122. *
  123. * sysClkEnable - turn on system clock interrupts
  124. *
  125. * This routine enables system clock interrupts.
  126. *
  127. * RETURNS: N/A
  128. *
  129. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  130. */
  131. void sysClkEnable (void)
  132.     {
  133.     if (!sysClkRunning)
  134. {
  135. sysClkRunning = TRUE;
  136. vxDecSet (decCountVal);
  137. }
  138.     }
  139. /******************************************************************************
  140. *
  141. * sysClkDisable - turn off system clock interrupts
  142. *
  143. * This routine disables system clock interrupts.
  144. *
  145. * RETURNS: N/A
  146. *
  147. * SEE ALSO: sysClkEnable()
  148. */
  149. void sysClkDisable (void)
  150.     {
  151.     if (sysClkRunning)
  152. sysClkRunning = FALSE;
  153.     }
  154. /******************************************************************************
  155. *
  156. * sysClkRateGet - get the system clock rate
  157. *
  158. * This routine returns the system clock rate.
  159. *
  160. * RETURNS: The number of ticks per second of the system clock.
  161. *
  162. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  163. */
  164. int sysClkRateGet (void)
  165.     {
  166.     return (sysClkTicksPerSecond);
  167.     }
  168. /******************************************************************************
  169. *
  170. * sysClkRateSet - set the system clock rate
  171. *
  172. * This routine sets the interrupt rate of the system clock.  It is called
  173. * by usrRoot() in usrConfig.c.
  174. *
  175. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  176. *
  177. * SEE ALSO: sysClkEnable(), sysClkRateGet()
  178. */
  179.    
  180. STATUS sysClkRateSet
  181.     (
  182.     int  ticksPerSecond  /* number of clock interrupts per second */
  183.     )
  184.     {
  185.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  186.         return (ERROR);
  187.     /* save the clock speed */
  188.     sysClkTicksPerSecond = ticksPerSecond;
  189.     /* Calibrate the clock, if needed. */
  190. #ifdef PPC_TMR_RATE_SET_ADJUST
  191.     PPC_TMR_RATE_SET_ADJUST;
  192. #endif
  193.     /* 
  194.      * compute the value to load in the decrementer. The new value will be
  195.      * load in the decrementer after the end of the current period
  196.      */
  197.     decCountVal = sysDecClkFrequency / ticksPerSecond;
  198.     return (OK);
  199.     }
  200. /*******************************************************************************
  201. *
  202. * sysAuxClkInt - auxiliary clock interrupt handler
  203. *
  204. * This routine handles the auxiliary clock interrupt.  It calls a user routine
  205. * if one was specified by the routine sysAuxClkConnect().
  206. */
  207. LOCAL void sysAuxClkInt (void)
  208.     {
  209.     *TER2(CPM_MEM_BASE) |= TER_REF;     /* clear event register */
  210.     *CISR(CPM_MEM_BASE) = CISR_TIMER2;  /* clear in-service bit */
  211.     if (sysAuxClkRoutine != NULL)
  212.         (*sysAuxClkRoutine) (sysAuxClkArg);
  213.     }
  214. /*******************************************************************************
  215. *
  216. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  217. *
  218. * This routine specifies the interrupt service routine to be called at each
  219. * auxiliary clock interrupt.  It does not enable auxiliary clock
  220. * interrupts.
  221. *
  222. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  223. *
  224. * SEE ALSO: intConnect(), sysAuxClkEnable()
  225. */
  226. STATUS sysAuxClkConnect
  227.     (
  228.     FUNCPTR routine, /* routine called at each aux. clock interrupt */
  229.     int     arg /* argument to auxiliary clock interrupt routine */
  230.     )
  231.     {
  232.     /* connect the ISR to the TIMER2 exception */
  233.     sysAuxClkRoutine   = routine;
  234.     sysAuxClkArg       = arg;
  235.     return (OK);
  236.     }
  237. /*******************************************************************************
  238. *
  239. * sysAuxClkDisable - turn off auxiliary clock interrupts
  240. *
  241. * This routine disables auxiliary clock interrupts.
  242. *
  243. * RETURNS: N/A
  244. *
  245. * SEE ALSO: sysAuxClkEnable()
  246. */
  247. void sysAuxClkDisable (void)
  248.     {
  249.     if (sysAuxClkRunning)
  250. {
  251. *CIMR(CPM_MEM_BASE) &= ~CISR_TIMER2; /* disable interrupt */
  252. *TGCR(CPM_MEM_BASE) |= TGCR_STP2; /* stop timer */
  253. sysAuxClkRunning = FALSE; /* clock is no longer running */
  254. }
  255.     }
  256. /*******************************************************************************
  257. *
  258. * sysAuxClkEnable - turn on auxiliary clock interrupts
  259. *
  260. * This routine enables auxiliary clock interrupts.
  261. *
  262. * RETURNS: N/A
  263. *
  264. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  265. */
  266. void sysAuxClkEnable (void)
  267.     {
  268.     UINT32  tempDiv = SYS_CPU_FREQ / (sysAuxClkTicksPerSecond << 8);
  269.     if ((!sysAuxClkRunning) && (tempDiv <= USHRT_MAX * 16))
  270. {
  271.         /* start, reset, but disable timer2 */
  272.         
  273.         *TGCR(CPM_MEM_BASE) &= ~(TGCR_RST2 | TGCR_STP2);
  274.         *TCN2(CPM_MEM_BASE) = 0x0;
  275. if (tempDiv <= USHRT_MAX)
  276.     {
  277.             *TRR2(CPM_MEM_BASE) = (UINT16) tempDiv;
  278.             *TMR2(CPM_MEM_BASE) = (TMR_ICLK_IN_GEN | TMR_ORI |
  279.                                    TMR_FRR | (TMR_PS_MSK & 0xff00));
  280.     }
  281. else
  282.     {
  283.             *TRR2(CPM_MEM_BASE) = (UINT16) (tempDiv / 16);
  284.             *TMR2(CPM_MEM_BASE) = (TMR_ICLK_IN_GEN_DIV16 | TMR_ORI |
  285.                                    TMR_FRR | (TMR_PS_MSK & 0xff00));
  286.     }
  287.  
  288.         *TER2(CPM_MEM_BASE) = 0xffff; /* clear event */
  289.         *CIMR(CPM_MEM_BASE) |= CISR_TIMER2; /* unmask interupt */
  290.         if (! sysAuxClkIntConnected)
  291.             {
  292.             (void) intConnect (IV_TIMER2, (VOIDFUNCPTR) sysAuxClkInt, 0);
  293.             sysAuxClkIntConnected = TRUE;
  294.             }
  295.         
  296.         *TGCR(CPM_MEM_BASE) |= TGCR_RST2; /* enable timer2 */
  297. sysAuxClkRunning = TRUE;
  298. }
  299.     }
  300. /*******************************************************************************
  301. *
  302. * sysAuxClkRateGet - get the auxiliary clock rate
  303. *
  304. * This routine returns the interrupt rate of the auxiliary clock.
  305. *
  306. * RETURNS: The number of ticks per second of the auxiliary clock.
  307. *
  308. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  309. */
  310. int sysAuxClkRateGet (void)
  311.     {
  312.     return (sysAuxClkTicksPerSecond);
  313.     }
  314. /*******************************************************************************
  315. *
  316. * sysAuxClkRateSet - set the auxiliary clock rate
  317. *
  318. * This routine sets the interrupt rate of the auxiliary clock.
  319. * It does not enable auxiliary clock interrupts.
  320. *
  321. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be
  322. * set.
  323. *
  324. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  325. */
  326. STATUS sysAuxClkRateSet
  327.     (
  328.     int ticksPerSecond     /* number of clock interrupts per second */
  329.     )
  330.     {
  331.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  332. return (ERROR);
  333.     sysAuxClkTicksPerSecond = ticksPerSecond;
  334.     if (sysAuxClkRunning)
  335. {
  336. sysAuxClkDisable ();
  337. sysAuxClkEnable ();
  338. }
  339.     return (OK);
  340.     }
  341. #ifdef  INCLUDE_TIMESTAMP
  342. /*******************************************************************************
  343. *
  344. * sysTimestampInt - timestamp timer interrupt handler
  345. *
  346. * This rountine handles the timestamp timer interrupt.  A user routine is
  347. * called, if one was connected by sysTimestampConnect().
  348. *
  349. * RETURNS: N/A
  350. *
  351. * SEE ALSO: sysTimestampConnect()
  352. */
  353. LOCAL void sysTimestampInt (void)
  354.     {
  355.     *TER4(CPM_MEM_BASE) |= TER_REF; /* clear TMR4 reference bit */
  356.     *CISR(CPM_MEM_BASE) = CISR_TIMER4; /* clear TMR4 interrupt 
  357. register bit */
  358.     if (sysTimestampRoutine != NULL)    /* call user routine */
  359.         (*sysTimestampRoutine) (sysTimestampArg);
  360.     }
  361. /*******************************************************************************
  362. *
  363. * sysTimestampConnect - connect a user routine to the timestamp timer interrupt
  364. *
  365. * This routine specifies the user interrupt routine to be called at each
  366. * timestamp timer interrupt.  It does not enable the timestamp timer itself.
  367. *
  368. * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used.
  369. */
  370. STATUS sysTimestampConnect
  371.     (
  372.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  373.     int arg             /* argument with which to call routine */
  374.     )
  375.     {
  376.     sysTimestampRoutine = routine;
  377.     sysTimestampArg = arg;
  378.     return (OK);
  379.     }
  380. /*******************************************************************************
  381. *
  382. * sysTimestampEnable - initialize and enable the timestamp timer
  383. *
  384. * This routine connects interrupts, and enables the timer device
  385. *
  386. * RETURNS: TRUE always
  387. */
  388. STATUS sysTimestampEnable (void)
  389.     {
  390.     if (sysTimestampRunning)
  391.         {
  392.         *TCN3(CPM_MEM_BASE) = (UINT32) 0; /* clear the counter */
  393.         return (OK);
  394.         }
  395.     if (! sysTimestampIntConnected)
  396.         {
  397.         (void) intConnect (IV_TIMER4, (VOIDFUNCPTR) sysTimestampInt, 0);
  398.         sysTimestampIntConnected = FALSE;
  399.         }
  400.     sysTimestampRunning = TRUE;
  401.     /* cascade timer 3 and 4 in order to get a 32 bit timer */
  402.     *TGCR(CPM_MEM_BASE) |= TGCR_CAS4;
  403.     /* start, reset, but disable timers 3 and 4 */
  404.     
  405.     *TGCR(CPM_MEM_BASE) &= ~(TGCR_RST4 | TGCR_RST3 | TGCR_STP4 | TGCR_STP3 );
  406.     /*
  407.      * When timers 3 and 4 are cascaded, TMR4 is the mode register, while
  408.      * TMR3 is ignored.
  409.      * Set prescaler to 0, to divide the clock (SYS_CPU_FREQ) by 1.
  410.      */
  411.     *TMR4(CPM_MEM_BASE) = 0x0000 | TMR_ICLK_IN_GEN | TMR_ORI | TMR_FRR;
  412.     *TMR3(CPM_MEM_BASE) = TMR_ICLK_IN_CAS;
  413.     *((UINT32 *)TRR3(CPM_MEM_BASE)) = (UINT32) sysTimestampPeriod ();
  414.     *((UINT32 *)TCN3(CPM_MEM_BASE)) = (UINT32) 0;
  415.     *TER4(CPM_MEM_BASE) = (UINT16) 0xffff;
  416.     *CIMR(CPM_MEM_BASE) |= CISR_TIMER4;
  417.     *TGCR(CPM_MEM_BASE) |= TGCR_RST4 | TGCR_RST3; /* enable */
  418.     return (OK);
  419.     }
  420. /*******************************************************************************
  421. *
  422. * sysTimestampDisable - turn off auxiliary clock interrupts
  423. *
  424. * This routine disables auxiliary clock interrupts.
  425. *
  426. * RETURNS: OK, always
  427. *
  428. * SEE ALSO: sysTimestampEnable()
  429. */
  430. STATUS sysTimestampDisable (void)
  431.     {
  432.     if (sysTimestampRunning)
  433.         {
  434.         *CIMR(CPM_MEM_BASE) &= ~CISR_TIMER4; /* disable interrupt */
  435.         *CIMR(CPM_MEM_BASE) &= ~CISR_TIMER3; /* disable interrupt */
  436.         *TGCR(CPM_MEM_BASE) |= TGCR_STP4; /* stop timer */
  437.         *TGCR(CPM_MEM_BASE) |= TGCR_STP3; /* stop timer */
  438.         sysTimestampRunning = FALSE;            /* clock is no longer running */
  439.         }
  440.     return (OK);
  441.     }
  442. /*******************************************************************************
  443. *
  444. * sysTimestampPeriod - get the period of a timestamp timer 
  445. *
  446. * This routine gets the period of the timestamp timer, in ticks.  The
  447. * period, or terminal count, is the number of ticks to which the timestamp
  448. * timer counts before rolling over and restarting the counting process.
  449. *
  450. * RETURNS: The period of the timestamp timer in counter ticks.
  451. */
  452. UINT32 sysTimestampPeriod (void)
  453.     {
  454.     /*
  455.      * The period of the timestamp depends on the clock rate of the on-chip
  456.      * timer (ie the Decrementer reload value).
  457.      */
  458.     
  459.     return (0xffffffff); /* highest period -> freerunning */
  460.     }
  461. /*******************************************************************************
  462. *
  463. * sysTimestampFreq - get a timestamp timer clock frequency
  464. *
  465. * This routine gets the frequency of the timer clock, in ticks per 
  466. * second.  The rate of the timestamp timer is set explicitly by the 
  467. * hardware and typically cannot be altered.
  468. *
  469. * NOTE: Because the PowerPC decrementer clock serves as the timestamp timer,
  470. * the decrementer clock frequency is also the timestamp timer frequency.
  471. *
  472. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  473. */
  474. UINT32 sysTimestampFreq (void)
  475.     {
  476.     /* Get the prescaler value from TMR4. TMR3 is ignored in cascade mode. */
  477.     return (SYS_CPU_FREQ / ((*TMR4(CPM_MEM_BASE) >> 8) + 1));
  478.     }
  479. /*******************************************************************************
  480. *
  481. * sysTimestamp - get a timestamp timer tick count
  482. *
  483. * This routine returns the current value of the timestamp timer tick counter.
  484. * The tick count can be converted to seconds by dividing it by the return of
  485. * sysTimestampFreq().
  486. *
  487. * This routine should be called with interrupts locked.  If interrupts are
  488. * not locked, sysTimestampLock() should be used instead.
  489. *
  490. * RETURNS: The current timestamp timer tick count.
  491. *
  492. * SEE ALSO: sysTimestampFreq(), sysTimestampLock()
  493. */
  494. UINT32 sysTimestamp (void)
  495.     {
  496.     return (*((UINT32 *) TCN3(CPM_MEM_BASE)));
  497.     }
  498. /*******************************************************************************
  499. *
  500. * sysTimestampLock - lock interrupts and get the timestamp timer tick count
  501. *
  502. * This routine locks interrupts when the tick counter must be stopped 
  503. * in order to read it or when two independent counters must be read.  
  504. * It then returns the current value of the timestamp timer tick
  505. * counter.
  506. * The tick count can be converted to seconds by dividing it by the return of
  507. * sysTimestampFreq().
  508. *
  509. * If interrupts are already locked, sysTimestamp() should be
  510. * used instead.
  511. *
  512. * RETURNS: The current timestamp timer tick count.
  513. *
  514. * SEE ALSO: sysTimestampFreq(), sysTimestamp()
  515. */
  516. UINT32 sysTimestampLock (void)
  517.     {
  518.     return (*((UINT32 *) TCN3(CPM_MEM_BASE)));
  519.     }
  520. #endif  /* INCLUDE_TIMESTAMP */