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

VxWorks

开发平台:

C/C++

  1. /* templateTimer.c - template timer library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01d,15sep01,dat  removed inline assembly, used vxDecReload()
  7. 01c,08sep99,cmc  test
  8. 01b,15apr99,cmc  Fixed a bug in sysAuxClkRateSet
  9. 01a,15apr99,cmc   ppc555Timer.c created 
  10. */
  11. /*
  12. DESCRIPTION
  13. This library provides PowerPC/555 system clock, auxiliary clock, and timestamp
  14. support.
  15. The PPC555 Decrementer Timer is used to implement the system clock and timestamp.
  16. The PPC555 PIT (Periodic Interrupt Timer) is used to implement the auxiliary clock.
  17. The macro DEC_CLOCK_FREQ (frequency of the decrementer input clock) should be
  18. defined before using this module. The macro DEC_CLK_TO_INC (ratio between the
  19. number of decrementer input clock cycles and one counter increment) can be 
  20. redefined prior to #including this file into sysLib.c.
  21. The macros SYS_CLK_RATE_MIN and SYS_CLK_RATE_MAX must be defined to provide
  22. parameter checking for sysClkRateSet().
  23. To include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must be
  24. defined. Note that changing the system clock rate will affect the timestamp
  25. timer period, which can be read by calling sysTimestampPeriod().
  26. If dynamic bus clock speed calculation is needed, the BSP can define the
  27. macro PPC_TMR_RATE_SET_ADJUST to be a call to the needed routine.
  28. This macro, if defined, will be executed during each call to sysClkRateSet().
  29. PPC_TMR_RATE_SET_ADJUST is usually not defined.
  30.     e.g. Assuming sysClkRateAdjust can compute a correct value
  31.     for sysDecClkFrequency.
  32.     #define PPC_TMR_RATE_SET_ADJUST 
  33. sysClkRateAdjust (&sysDecClkFrequency)
  34. INCLUDE FILES: ppc555Timer.h
  35.    
  36. SEE ALSO:
  37. .pG "Configuration"
  38. */
  39. /* includes */
  40. #include "vxWorks.h"
  41. #include "config.h"
  42. #include "arch/ppc/vxPpcLib.h"
  43. #include "drv/timer/timerDev.h"
  44. #include "drv/timer/timestampDev.h"
  45. /* local defines */
  46. #ifndef DEC_CLK_TO_INC
  47. #define DEC_CLK_TO_INC 1 /* # bus clks per increment */
  48. #endif
  49. #define DEFAULT_DEC_CLK_FREQ 33333333 /* 33.33 Mhz default */
  50. #define DEC_SHIFT 0
  51. #ifndef CPU_INT_UNLOCK
  52. #    define  CPU_INT_UNLOCK(x) (intUnlock(x))
  53. #endif
  54. #ifndef CPU_INT_LOCK
  55. #    define  CPU_INT_LOCK(x) (*x = intLock())
  56. #endif
  57. /* extern declarations */
  58. IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
  59. IMPORT UINT32 vxImemBaseGet();
  60. /* Locals */
  61. LOCAL int  sysClkTicksPerSecond  = 60;   /* default 60 ticks/second */
  62. LOCAL FUNCPTR sysClkRoutine = NULL;
  63. LOCAL int sysClkArg = NULL;
  64. LOCAL BOOL sysClkConnectFirstTime = TRUE;
  65. LOCAL int decCountVal = 10000000; /* default dec value */
  66. LOCAL BOOL sysClkRunning  = FALSE;
  67. LOCAL int  sysDecClkFrequency = DEFAULT_DEC_CLK_FREQ/DEC_CLK_TO_INC;
  68. LOCAL FUNCPTR sysAuxClkRoutine = NULL;
  69. LOCAL int sysAuxClkArg = NULL;
  70. LOCAL BOOL sysAuxClkRunning = FALSE;
  71. LOCAL BOOL sysAuxClkIntConnected = FALSE;
  72. LOCAL int sysAuxClkTicksPerSecond = 60;
  73. #ifdef INCLUDE_TIMESTAMP
  74. LOCAL BOOL sysTimestampRunning   = FALSE;   /* timestamp running flag */
  75. #endif /* INCLUDE_TIMESTAMP */
  76. /*******************************************************************************
  77. *
  78. * sysClkInt - clock interrupt handler
  79. *
  80. * This routine handles the clock interrupt on the PowerPC architecture. It is
  81. * attached to the decrementer vector by the routine sysClkConnect().
  82. *
  83. * RETURNS : N/A
  84. */
  85. LOCAL void sysClkInt (void)
  86.     {
  87.     vxDecReload (decCountVal); /* reload decrementer */
  88.     /* Unlock interrupts during decrementer processing */
  89.     CPU_INT_UNLOCK (_PPC_MSR_EE);
  90.     /* execute the system clock routine */
  91.     if (sysClkRunning && (sysClkRoutine != NULL))
  92. (*(FUNCPTR) sysClkRoutine) (sysClkArg);
  93.     }
  94. /*******************************************************************************
  95. *
  96. * sysClkConnect - connect a routine to the system clock interrupt
  97. *
  98. * This routine specifies the interrupt service routine to be called at each
  99. * clock interrupt.  Normally, it is called from usrRoot() in usrConfig.c to
  100. * connect usrClock() to the system clock interrupt.
  101. *
  102. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  103. *
  104. * SEE ALSO: intConnect(), usrClock(), sysClkEnable()
  105. */
  106.     
  107. STATUS sysClkConnect
  108.     (
  109.     FUNCPTR  routine, /* routine to connect */
  110.     int  arg /* argument for the routine */
  111.     )
  112.     {
  113.     if (sysClkConnectFirstTime)
  114. {
  115. sysHwInit2();
  116. sysClkConnectFirstTime = FALSE;
  117. }
  118. #ifdef DEC_CLOCK_FREQ 
  119.     sysDecClkFrequency = DEC_CLOCK_FREQ / DEC_CLK_TO_INC;
  120. #endif /* DEC_CLOCK_FREQ */
  121.     /* connect the routine to the decrementer exception */
  122.     excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_DECR, (VOIDFUNCPTR) sysClkInt);
  123.     
  124.     sysClkRoutine = routine;
  125.     sysClkArg = arg;
  126.     return (OK);
  127.     }
  128. /******************************************************************************
  129. *
  130. * sysClkEnable - turn on system clock interrupts
  131. *
  132. * This routine enables system clock interrupts.
  133. *
  134. * RETURNS: N/A
  135. *
  136. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  137. */
  138. void sysClkEnable (void)
  139.     {
  140.     if (!sysClkRunning)
  141. {
  142. sysClkRunning = TRUE;
  143. vxDecSet (decCountVal);
  144. }
  145.     }
  146. /******************************************************************************
  147. *
  148. * sysClkDisable - turn off system clock interrupts
  149. *
  150. * This routine disables system clock interrupts.
  151. *
  152. * RETURNS: N/A
  153. *
  154. * SEE ALSO: sysClkEnable()
  155. */
  156. void sysClkDisable (void)
  157.     {
  158.     if (sysClkRunning)
  159. sysClkRunning = FALSE;
  160.     }
  161. /******************************************************************************
  162. *
  163. * sysClkRateGet - get the system clock rate
  164. *
  165. * This routine returns the system clock rate.
  166. *
  167. * RETURNS: The number of ticks per second of the system clock.
  168. *
  169. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  170. */
  171. int sysClkRateGet (void)
  172.     {
  173.     return (sysClkTicksPerSecond);
  174.     }
  175. /******************************************************************************
  176. *
  177. * sysClkRateSet - set the system clock rate
  178. *
  179. * This routine sets the interrupt rate of the system clock.  It is called
  180. * by usrRoot() in usrConfig.c.
  181. *
  182. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  183. *
  184. * SEE ALSO: sysClkEnable(), sysClkRateGet()
  185. */
  186.    
  187. STATUS sysClkRateSet
  188.     (
  189.     int  ticksPerSecond  /* number of clock interrupts per second */
  190.     )
  191.     {
  192.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  193.         return (ERROR);
  194.     /* save the clock speed */
  195.     sysClkTicksPerSecond = ticksPerSecond;
  196.     /* Calibrate the clock, if needed. */
  197. #ifdef PPC_TMR_RATE_SET_ADJUST
  198.     PPC_TMR_RATE_SET_ADJUST;
  199. #endif
  200.     /* 
  201.      * compute the value to load in the decrementer. The new value will be
  202.      * load in the decrementer after the end of the current period
  203.      */
  204.     decCountVal = sysDecClkFrequency / ticksPerSecond;
  205.     return (OK);
  206.     }
  207. #ifdef  INCLUDE_TIMESTAMP
  208. /*******************************************************************************
  209. *
  210. * sysTimestampConnect - connect a user routine to a timestamp timer interrupt
  211. *
  212. * This routine specifies the user interrupt routine to be called at each
  213. * timestamp timer interrupt.  
  214. *
  215. * NOTE: This routine has no effect, since the CPU decrementer has no
  216. * timestamp timer interrupt.
  217. *
  218. * RETURNS: ERROR, always.
  219. */
  220. STATUS sysTimestampConnect
  221.     (
  222.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  223.     int arg             /* argument with which to call routine */
  224.     )
  225.     {
  226.     return (ERROR);
  227.     }
  228. /*******************************************************************************
  229. *
  230. * sysTimestampEnable - enable a timestamp timer interrupt
  231. *
  232. * This routine enables timestamp timer interrupts and resets the counter.
  233. *
  234. * NOTE: This routine has no effect, since the CPU decrementer has no
  235. * timestamp timer interrupt.
  236. *
  237. * RETURNS: OK, always.
  238. *
  239. * SEE ALSO: sysTimestampDisable()
  240. */
  241. STATUS sysTimestampEnable (void)
  242.    {
  243.    if (sysTimestampRunning)
  244.       {
  245.       return (OK);
  246.       }
  247.    if (!sysClkRunning)          /* don't have any auxiliary clock ! */
  248.       return (ERROR);
  249.    sysTimestampRunning = TRUE;
  250.    return (OK);
  251.    }
  252. /*******************************************************************************
  253. *
  254. * sysTimestampDisable - disable a timestamp timer interrupt
  255. *
  256. * This routine disables timestamp timer interrupts.
  257. *
  258. * NOTE: This routine has no effect, since the CPU decrementer has no
  259. * timestamp timer interrupt.
  260. *
  261. * RETURNS: OK, always.
  262. *
  263. * SEE ALSO: sysTimestampEnable()
  264. */
  265. STATUS sysTimestampDisable (void)
  266.     {
  267.     if (sysTimestampRunning)
  268.         sysTimestampRunning = FALSE;
  269.     return (OK);
  270.     }
  271. /*******************************************************************************
  272. *
  273. * sysTimestampPeriod - get the period of a timestamp timer 
  274. *
  275. * This routine gets the period of the timestamp timer, in ticks.  The
  276. * period, or terminal count, is the number of ticks to which the timestamp
  277. * timer counts before rolling over and restarting the counting process.
  278. *
  279. * RETURNS: The period of the timestamp timer in counter ticks.
  280. */
  281. UINT32 sysTimestampPeriod (void)
  282.     {
  283.     /*
  284.      * The period of the timestamp depends on the clock rate of the on-chip
  285.      * timer (ie the Decrementer reload value).
  286.      */
  287.     
  288.     return (decCountVal);
  289.     }
  290. /*******************************************************************************
  291. *
  292. * sysTimestampFreq - get a timestamp timer clock frequency
  293. *
  294. * This routine gets the frequency of the timer clock, in ticks per 
  295. * second.  The rate of the timestamp timer is set explicitly by the 
  296. * hardware and typically cannot be altered.
  297. *
  298. * NOTE: Because the PowerPC decrementer clock serves as the timestamp timer,
  299. * the decrementer clock frequency is also the timestamp timer frequency.
  300. *
  301. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  302. */
  303. UINT32 sysTimestampFreq (void)
  304.     {
  305.     return (sysDecClkFrequency);
  306.     }
  307. /*******************************************************************************
  308. *
  309. * sysTimestamp - get a timestamp timer tick count
  310. *
  311. * This routine returns the current value of the timestamp timer tick counter.
  312. * The tick count can be converted to seconds by dividing it by the return of
  313. * sysTimestampFreq().
  314. *
  315. * This routine should be called with interrupts locked.  If interrupts are
  316. * not locked, sysTimestampLock() should be used instead.
  317. *
  318. * RETURNS: The current timestamp timer tick count.
  319. *
  320. * SEE ALSO: sysTimestampFreq(), sysTimestampLock()
  321. */
  322. UINT32 sysTimestamp (void)
  323.     {
  324.     return (decCountVal - (INT32) vxDecGet());
  325.     }
  326. /*******************************************************************************
  327. *
  328. * sysTimestampLock - lock interrupts and get the timestamp timer tick count
  329. *
  330. * This routine locks interrupts when the tick counter must be stopped 
  331. * in order to read it or when two independent counters must be read.  
  332. * It then returns the current value of the timestamp timer tick
  333. * counter.
  334. * The tick count can be converted to seconds by dividing it by the return of
  335. * sysTimestampFreq().
  336. *
  337. * If interrupts are already locked, sysTimestamp() should be
  338. * used instead.
  339. *
  340. * RETURNS: The current timestamp timer tick count.
  341. *
  342. * SEE ALSO: sysTimestampFreq(), sysTimestamp()
  343. */
  344. UINT32 sysTimestampLock (void)
  345.     {
  346.     UINT32 currentDecValue;
  347.     int oldLevel;
  348.     oldLevel = intLock ();                              /* LOCK INTERRUPT */
  349.     currentDecValue = vxDecGet();
  350.     intUnlock (oldLevel);                               /* UNLOCK INTERRUPT */
  351.     return (decCountVal - currentDecValue);
  352.     }
  353. #endif  /* INCLUDE_TIMESTAMP */
  354. /*******************************************************************************
  355. *
  356. * sysAuxClkInt - handle an auxiliary clock interrupt
  357. *
  358. * This routine handles an auxiliary clock interrupt.  It acknowledges the
  359. * interrupt and calls the routine installed by sysAuxClkConnect().
  360. *
  361. * RETURNS: N/A
  362. */
  363. void sysAuxClkInt (void)
  364.     {
  365.     UINT32 imemBase = vxImemBaseGet();  /* internal memory Base Address */
  366.     /* read PS bit in PISCR, and then reset it to terminate int request */
  367.     if(*PISCR(imemBase) & PISCR_PS)
  368.             *PISCR(imemBase) |= PISCR_PS;
  369.     /* call auxiliary clock service routine */
  370.     if (sysAuxClkRoutine != NULL)
  371. (*sysAuxClkRoutine) (sysAuxClkArg);
  372.     }
  373. /*******************************************************************************
  374. *
  375. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  376. *
  377. * This routine specifies the interrupt service routine to be called at each
  378. * auxiliary clock interrupt.  It does not enable auxiliary clock interrupts.
  379. *
  380. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  381. *
  382. * SEE ALSO: intConnect(), sysAuxClkEnable()
  383. */
  384. STATUS sysAuxClkConnect
  385.     (
  386.     FUNCPTR routine,    /* routine called at each aux clock interrupt */
  387.     int arg             /* argument to auxiliary clock interrupt routine */
  388.     )
  389.     {
  390.     /* connect the ISR to PIT exception */
  391.     sysAuxClkRoutine = routine;
  392.     sysAuxClkArg = arg;
  393.     return (OK);
  394.     }
  395. /*******************************************************************************
  396. *
  397. * sysAuxClkDisable - turn off auxiliary clock interrupts
  398. *
  399. * This routine disables auxiliary clock interrupts.
  400. *
  401. * RETURNS: N/A
  402. *
  403. * SEE ALSO: sysAuxClkEnable()
  404. */
  405. void sysAuxClkDisable (void)
  406.     {
  407.     UINT32 imemBase = vxImemBaseGet();  /* internal memory Base Address */
  408.     if (sysAuxClkRunning)
  409.         {
  410.         *PISCR(imemBase) &= ~PISCR_PIE;      /* disable PIT interrupts */
  411.         *PISCR(imemBase) &= ~PISCR_PTE;       /* stop PIT */
  412. intDisable (PIT_INT_LVL); /* disable int controller PIT level */
  413.         sysAuxClkRunning = FALSE;
  414.         }
  415.     }
  416. /*******************************************************************************
  417. *
  418. * sysAuxClkEnable - turn on auxiliary clock interrupts
  419. *
  420. * This routine enables auxiliary clock interrupts.
  421. *
  422. * RETURNS: N/A
  423. *
  424. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  425. */
  426. void sysAuxClkEnable (void)
  427.     {
  428.     UINT32 imemBase = vxImemBaseGet();  /* internal memory Base Address */
  429.     if (!sysAuxClkIntConnected)
  430.         {
  431. *PISCR(imemBase) |= PISCR_PIRQ; /* set PIT int level */
  432.         /* connect sysAuxClkInt to PIT interrupt */
  433.         (void) intConnect (INUM_TO_IVEC(PIT_INT_LVL), (VOIDFUNCPTR) sysAuxClkInt, NULL);
  434.         
  435.         sysAuxClkIntConnected = TRUE;
  436.         }
  437.     if (!sysAuxClkRunning)
  438.         {
  439.         /* clear any pendding PIT int request */
  440.         if(*PISCR(imemBase) & PISCR_PS)
  441.             *PISCR(imemBase) |= PISCR_PS;
  442.         /* set clock divider */
  443. *SCCR(imemBase) &= ~SCCR_RTDIV_MSK;
  444. *SCCR(imemBase) |= SCCR_RTDIV;
  445.         /* set counter preload value */
  446.         *PITC(imemBase) = (PIT_CLOCK_FREQ / sysAuxClkTicksPerSecond) << 16; 
  447.         *PISCR(imemBase) |= PISCR_PTE;      /* start PIT */
  448.         *PISCR(imemBase) |= PISCR_PIE;      /* enable PIT interrupts */
  449. intEnable (PIT_INT_LVL); /* enable int controller PIT level */
  450.         sysAuxClkRunning = TRUE;
  451.         }
  452.     }
  453. /*******************************************************************************
  454. *
  455. * sysAuxClkRateGet - get the auxiliary clock rate
  456. *
  457. * This routine returns the interrupt rate of the auxiliary clock.
  458. *
  459. * RETURNS: The number of ticks per second of the auxiliary clock.
  460. *
  461. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  462. */
  463. int sysAuxClkRateGet (void)
  464.     {
  465.     return (sysAuxClkTicksPerSecond);
  466.     }
  467. /*******************************************************************************
  468. *
  469. * sysAuxClkRateSet - set the auxiliary clock rate
  470. *
  471. * This routine sets the interrupt rate of the auxiliary clock.  It does not
  472. * enable auxiliary clock interrupts.
  473. *
  474. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  475. *
  476. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  477. */
  478. STATUS sysAuxClkRateSet
  479.     (
  480.     int ticksPerSecond  /* number of clock interrupts per second */
  481.     )
  482.     {
  483.     /* return ERROR if rate is not supported */
  484.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  485.         return (ERROR);
  486.     sysAuxClkTicksPerSecond = ticksPerSecond;
  487.     if (sysAuxClkRunning)
  488.         {
  489.         sysAuxClkDisable ();
  490.         sysAuxClkEnable ();
  491.         }
  492.     return (OK);
  493.     }