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

VxWorks

开发平台:

C/C++

  1. /* ppcDecTimer.c - PowerPC decrementer timer library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01u,16oct01,dtr  Fix for SPR65678.Call vxKeyedDecReload for 860 with boot lockup
  8.  problem.
  9. 01t,21may01,kab  Added back sysHwInit2() for T2.1
  10. 01s,17apr01,dat  65984, portable C Code, added vxDecReload()
  11. 01r,16nov00,sbs  corrected docs for vxWorks AE.
  12. 01q,29mar00,dat  removed sysHwInit2()
  13. 01p,13jan00,dat  changed NULL to 0, as needed
  14. 01o,03mar98,jgn  Re-enable interrupts during system clock tick processing
  15.  (SPR #10000)
  16. 01n,04nov96,tam  renamed MEMORY_BUS_SPEED to DEC_CLOCK_FREQ, BUS_CLK_TO_INC
  17.  to DEC_CLK_TO_INC and DEFAULT_BUS_SPEED to DEFAULT_DEC_CLK_FREQ
  18.  (spr #7423).
  19. 01m,29oct96,wlf  doc: cleanup.
  20. 01l,31jul96,dat  added PPC_TMR_RATE_SET_ADJUST
  21. 01k,22jul96,tam  cleanup. added timestamp support. Changed CPU_SPEED macro to 
  22.  MEMORY_BUS_SPEED.
  23. 01j,17jun96,tpr  optimized sysClkInt() assembly code.
  24. 01i,14may96,tam  fixed drift in sysClkInt. Changed DEFAULT_CPU_SPEED to 
  25.  33333333 (33.33 Mhz)
  26. 01h,11mar96,ms   fixed roundoff in sysClkInt.
  27. 01g,12feb96,tpr  reworked.
  28. 01f,23oct95,kvk  cleanup.
  29. 01e,22may95,caf  added conditional compile for PowerPC 601.
  30. 01d,02may95,caf  cleanup.
  31. 01c,27apr95,caf  removed vxDecEnable() and PPC60x_TIMER_INT_VECTOR,
  32.  changed name to ppcDecTimer.c.
  33. 01b,25jan95,vin  cleanup.
  34. 01a,20jan95,kvk  written.
  35. */
  36. /*
  37. DESCRIPTION
  38. This library provides PowerPC decrementer timer routines.
  39. This library handles both the system clock and the auxiliary clock plus 
  40. and timestamp functions.  However, the auxiliary clock functions have no 
  41. effect.
  42. The parameter DEC_CLOCK_FREQ (frequency of the decrementer input clock) 
  43. should be defined before using this module.  The macro DEC_CLK_TO_INC (ratio 
  44. between the number of decrementer input clock cycles and one counter 
  45. increment) can be redefined prior to #including this file into sysLib.c.
  46. The parameters SYS_CLK_RATE_MIN and SYS_CLK_RATE_MAX must be defined to provide
  47. parameter checking for sysClkRateSet().
  48. To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP 
  49. must be included in the system. Note that changing the system clock rate will 
  50. effect the timestamp timer period, which can be read by calling 
  51. sysTimestampPeriod().
  52. If dynamic bus clock speed calculation is needed, the BSP can define the
  53. macro PPC_TMR_RATE_SET_ADJUST to be a call to the needed routine.
  54. This macro, if defined, will be executed during each call to sysClkRateSet().
  55. PPC_TMR_RATE_SET_ADJUST is usually not defined.
  56.     e.g. Assuming sysClkRateAdjust can compute a correct value
  57.     for sysDecClkFrequency.
  58.     #define PPC_TMR_RATE_SET_ADJUST 
  59. sysClkRateAdjust (&sysDecClkFrequency)
  60. INCLUDE FILES: ppcDecTimer.h
  61.    
  62. SEE ALSO:
  63. .pG "Configuration"
  64. */
  65. /* includes */
  66. #include "arch/ppc/vxPpcLib.h"
  67. #include "drv/timer/ppcDecTimer.h"
  68. #include "drv/timer/timestampDev.h"
  69. /* local defines */
  70. #ifndef DEC_CLK_TO_INC
  71. #define DEC_CLK_TO_INC 4 /* # bus clks per increment */
  72. #endif
  73. #define DEFAULT_DEC_CLK_FREQ 33333333 /* 33.33 Mhz default */
  74. #if (CPU == PPC601)
  75. #   define DEC_SHIFT 7 /* 7 low-order bits aren't used */
  76. #else
  77. #   define DEC_SHIFT 0
  78. #endif /* CPU == PPC601 */
  79. #ifndef CPU_INT_UNLOCK
  80. #    define  CPU_INT_UNLOCK(x) (intUnlock(x))
  81. #endif
  82. #ifndef CPU_INT_LOCK
  83. #    define  CPU_INT_LOCK(x) (*x = intLock())
  84. #endif
  85. /* extern declarations */
  86. IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
  87. /* Locals */
  88. LOCAL int  sysClkTicksPerSecond  = 60;   /* default 60 ticks/second */
  89. LOCAL FUNCPTR sysClkRoutine = NULL;
  90. LOCAL int sysClkArg = 0;
  91. LOCAL int       decCountVal = 10000000; /* default dec value */
  92. LOCAL BOOL sysClkRunning  = FALSE;
  93. LOCAL BOOL sysClkConnectFirstTime = TRUE;
  94. LOCAL int  sysDecClkFrequency = DEFAULT_DEC_CLK_FREQ/DEC_CLK_TO_INC;
  95. #ifdef INCLUDE_TIMESTAMP
  96. LOCAL BOOL sysTimestampRunning   = FALSE;   /* timestamp running flag */
  97. #endif /* INCLUDE_TIMESTAMP */
  98. /*******************************************************************************
  99. *
  100. * sysClkInt - clock interrupt handler
  101. *
  102. * This routine handles the clock interrupt on the PowerPC architecture. It is
  103. * attached to the decrementer vector by the routine sysClkConnect().
  104. *
  105. * RETURNS : N/A
  106. */
  107. LOCAL void sysClkInt (void)
  108.     {
  109. #ifdef USE_KEYED_REGS 
  110.     vxKeyedDecReload(decCountVal);
  111. #else
  112.     vxDecReload (decCountVal);
  113. #endif
  114.     /* Unlock interrupts during decrementer processing */
  115.     CPU_INT_UNLOCK (_PPC_MSR_EE);
  116.     /* execute the system clock routine */
  117.     if (sysClkRunning && (sysClkRoutine != NULL))
  118. (*(FUNCPTR) sysClkRoutine) (sysClkArg);
  119.     }
  120. /*******************************************************************************
  121. *
  122. * sysClkConnect - connect a routine to the system clock interrupt
  123. *
  124. * This routine specifies the interrupt service routine to be called at each
  125. * clock interrupt.  Normally, it is called from usrRoot() in usrConfig.c to
  126. * connect usrClock() to the system clock interrupt.
  127. *
  128. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  129. *
  130. * SEE ALSO: intConnect(), usrClock(), sysClkEnable()
  131. */
  132.     
  133. STATUS sysClkConnect
  134.     (
  135.     FUNCPTR  routine, /* routine to connect */
  136.     int  arg /* argument for the routine */
  137.     )
  138.     {
  139.     if (sysClkConnectFirstTime)
  140. {
  141. sysHwInit2();
  142. sysClkConnectFirstTime = FALSE;
  143. }
  144. #ifdef DEC_CLOCK_FREQ 
  145.     sysDecClkFrequency = DEC_CLOCK_FREQ / DEC_CLK_TO_INC;
  146. #endif /* DEC_CLOCK_FREQ */
  147.     /* connect the routine to the decrementer exception */
  148.     excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_DECR, (VOIDFUNCPTR) sysClkInt);
  149.     
  150.     sysClkRoutine = routine;
  151.     sysClkArg = arg;
  152.     return (OK);
  153.     }
  154. /******************************************************************************
  155. *
  156. * sysClkEnable - turn on system clock interrupts
  157. *
  158. * This routine enables system clock interrupts.
  159. *
  160. * RETURNS: N/A
  161. *
  162. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  163. */
  164. void sysClkEnable (void)
  165.     {
  166.     if (!sysClkRunning)
  167. {
  168. sysClkRunning = TRUE;
  169. vxDecSet (decCountVal);
  170. }
  171.     }
  172. /******************************************************************************
  173. *
  174. * sysClkDisable - turn off system clock interrupts
  175. *
  176. * This routine disables system clock interrupts.
  177. *
  178. * RETURNS: N/A
  179. *
  180. * SEE ALSO: sysClkEnable()
  181. */
  182. void sysClkDisable (void)
  183.     {
  184.     if (sysClkRunning)
  185. sysClkRunning = FALSE;
  186.     }
  187. /******************************************************************************
  188. *
  189. * sysClkRateGet - get the system clock rate
  190. *
  191. * This routine returns the system clock rate.
  192. *
  193. * RETURNS: The number of ticks per second of the system clock.
  194. *
  195. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  196. */
  197. int sysClkRateGet (void)
  198.     {
  199.     return (sysClkTicksPerSecond);
  200.     }
  201. /******************************************************************************
  202. *
  203. * sysClkRateSet - set the system clock rate
  204. *
  205. * This routine sets the interrupt rate of the system clock.  It is called
  206. * by usrRoot() in usrConfig.c.
  207. *
  208. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  209. *
  210. * SEE ALSO: sysClkEnable(), sysClkRateGet()
  211. */
  212.    
  213. STATUS sysClkRateSet
  214.     (
  215.     int  ticksPerSecond  /* number of clock interrupts per second */
  216.     )
  217.     {
  218.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  219.         return (ERROR);
  220.     /* save the clock speed */
  221.     sysClkTicksPerSecond = ticksPerSecond;
  222.     /* Calibrate the clock, if needed. */
  223. #ifdef PPC_TMR_RATE_SET_ADJUST
  224.     PPC_TMR_RATE_SET_ADJUST;
  225. #endif
  226.     /* 
  227.      * compute the value to load in the decrementer. The new value will be
  228.      * load in the decrementer after the end of the current period
  229.      */
  230.     decCountVal = sysDecClkFrequency / ticksPerSecond;
  231.     return (OK);
  232.     }
  233. #ifdef  INCLUDE_TIMESTAMP
  234. /*******************************************************************************
  235. *
  236. * sysTimestampConnect - connect a user routine to a timestamp timer interrupt
  237. *
  238. * This routine specifies the user interrupt routine to be called at each
  239. * timestamp timer interrupt.  
  240. *
  241. * NOTE: This routine has no effect, since the CPU decrementer has no
  242. * timestamp timer interrupt.
  243. *
  244. * RETURNS: ERROR, always.
  245. */
  246. STATUS sysTimestampConnect
  247.     (
  248.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  249.     int arg             /* argument with which to call routine */
  250.     )
  251.     {
  252.     return (ERROR);
  253.     }
  254. /*******************************************************************************
  255. *
  256. * sysTimestampEnable - enable a timestamp timer interrupt
  257. *
  258. * This routine enables timestamp timer interrupts and resets the counter.
  259. *
  260. * NOTE: This routine has no effect, since the CPU decrementer has no
  261. * timestamp timer interrupt.
  262. *
  263. * RETURNS: OK, always.
  264. *
  265. * SEE ALSO: sysTimestampDisable()
  266. */
  267. STATUS sysTimestampEnable (void)
  268.    {
  269.    if (sysTimestampRunning)
  270.       {
  271.       return (OK);
  272.       }
  273.    if (!sysClkRunning)          /* don't have any auxiliary clock ! */
  274.       return (ERROR);
  275.    sysTimestampRunning = TRUE;
  276.    return (OK);
  277.    }
  278. /*******************************************************************************
  279. *
  280. * sysTimestampDisable - disable a timestamp timer interrupt
  281. *
  282. * This routine disables timestamp timer interrupts.
  283. *
  284. * NOTE: This routine has no effect, since the CPU decrementer has no
  285. * timestamp timer interrupt.
  286. *
  287. * RETURNS: OK, always.
  288. *
  289. * SEE ALSO: sysTimestampEnable()
  290. */
  291. STATUS sysTimestampDisable (void)
  292.     {
  293.     if (sysTimestampRunning)
  294.         sysTimestampRunning = FALSE;
  295.     return (OK);
  296.     }
  297. /*******************************************************************************
  298. *
  299. * sysTimestampPeriod - get the period of a timestamp timer 
  300. *
  301. * This routine gets the period of the timestamp timer, in ticks.  The
  302. * period, or terminal count, is the number of ticks to which the timestamp
  303. * timer counts before rolling over and restarting the counting process.
  304. *
  305. * RETURNS: The period of the timestamp timer in counter ticks.
  306. */
  307. UINT32 sysTimestampPeriod (void)
  308.     {
  309.     /*
  310.      * The period of the timestamp depends on the clock rate of the on-chip
  311.      * timer (ie the Decrementer reload value).
  312.      */
  313.     
  314.     return (decCountVal);
  315.     }
  316. /*******************************************************************************
  317. *
  318. * sysTimestampFreq - get a timestamp timer clock frequency
  319. *
  320. * This routine gets the frequency of the timer clock, in ticks per 
  321. * second.  The rate of the timestamp timer is set explicitly by the 
  322. * hardware and typically cannot be altered.
  323. *
  324. * NOTE: Because the PowerPC decrementer clock serves as the timestamp timer,
  325. * the decrementer clock frequency is also the timestamp timer frequency.
  326. *
  327. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  328. */
  329. UINT32 sysTimestampFreq (void)
  330.     {
  331.     return (sysDecClkFrequency);
  332.     }
  333. /*******************************************************************************
  334. *
  335. * sysTimestamp - get a timestamp timer tick count
  336. *
  337. * This routine returns the current value of the timestamp timer tick counter.
  338. * The tick count can be converted to seconds by dividing it by the return of
  339. * sysTimestampFreq().
  340. *
  341. * This routine should be called with interrupts locked.  If interrupts are
  342. * not locked, sysTimestampLock() should be used instead.
  343. *
  344. * RETURNS: The current timestamp timer tick count.
  345. *
  346. * SEE ALSO: sysTimestampFreq(), sysTimestampLock()
  347. */
  348. UINT32 sysTimestamp (void)
  349.     {
  350.     return (decCountVal - (INT32) vxDecGet());
  351.     }
  352. /*******************************************************************************
  353. *
  354. * sysTimestampLock - lock interrupts and get the timestamp timer tick count
  355. *
  356. * This routine locks interrupts when the tick counter must be stopped 
  357. * in order to read it or when two independent counters must be read.  
  358. * It then returns the current value of the timestamp timer tick
  359. * counter.
  360. * The tick count can be converted to seconds by dividing it by the return of
  361. * sysTimestampFreq().
  362. *
  363. * If interrupts are already locked, sysTimestamp() should be
  364. * used instead.
  365. *
  366. * RETURNS: The current timestamp timer tick count.
  367. *
  368. * SEE ALSO: sysTimestampFreq(), sysTimestamp()
  369. */
  370. UINT32 sysTimestampLock (void)
  371.     {
  372.     UINT32 currentDecValue;
  373.     int oldLevel;
  374.     oldLevel = intLock ();                              /* LOCK INTERRUPT */
  375.     currentDecValue = vxDecGet();
  376.     intUnlock (oldLevel);                               /* UNLOCK INTERRUPT */
  377.     return (decCountVal - currentDecValue);
  378.     }
  379. #endif  /* INCLUDE_TIMESTAMP */