xos_timer.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /** @file */
  2. // xos_timer.h - XOS Timer API interface and data structures.
  3. // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining
  6. // a copy of this software and associated documentation files (the
  7. // "Software"), to deal in the Software without restriction, including
  8. // without limitation the rights to use, copy, modify, merge, publish,
  9. // distribute, sublicense, and/or sell copies of the Software, and to
  10. // permit persons to whom the Software is furnished to do so, subject to
  11. // the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included
  14. // in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20. // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22. // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. // NOTE: Do not include this file directly in your application. Including
  24. // xos.h will automatically include this file.
  25. #ifndef __XOS_TIMER_H__
  26. #define __XOS_TIMER_H__
  27. #include "xos_types.h"
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. //-----------------------------------------------------------------------------
  32. ///
  33. /// Function pointer type for timer callbacks.
  34. ///
  35. //-----------------------------------------------------------------------------
  36. typedef void (XosTimerFunc)(void * arg);
  37. //-----------------------------------------------------------------------------
  38. ///
  39. /// Timer event structure. Used to track pending timer events.
  40. ///
  41. //-----------------------------------------------------------------------------
  42. typedef struct XosTimer {
  43. struct XosTimer * next; ///< Pointer to next event in list.
  44. uint64_t when; ///< Time (clock cycles) at which to trigger.
  45. uint64_t delta; ///< Delta for next re-trigger, 0 if none.
  46. XosTimerFunc * fn; ///< Function to call when timer expires.
  47. void * arg; ///< Argument to pass to called function.
  48. bool active; ///< Set if active (in some list of events).
  49. #if XOS_OPT_TIMER_WAIT
  50. XosThreadQueue waitq; ///< Queue of threads waiting on this timer.
  51. #endif
  52. #if XOS_TIMER_DEBUG
  53. uint32_t signature;
  54. #endif
  55. } XosTimer;
  56. //-----------------------------------------------------------------------------
  57. // Extern declarations.
  58. //-----------------------------------------------------------------------------
  59. // System clock frequency in cycles per second.
  60. extern uint32_t xos_clock_freq;
  61. ///@{
  62. //-----------------------------------------------------------------------------
  63. // Functions to convert from clock cycles to time units and vice versa.
  64. //
  65. // Note that these are integer conversions so for example a cycle count of less
  66. // than one second will convert to zero seconds.
  67. //-----------------------------------------------------------------------------
  68. /// Converts CPU cycles to time in seconds.
  69. ///
  70. /// \param cycles Number of CPU cycles.
  71. ///
  72. /// \return Equivalent number of seconds (truncated to integer).
  73. static inline uint64_t
  74. xos_cycles_to_secs(uint64_t cycles)
  75. {
  76. return cycles / xos_clock_freq;
  77. }
  78. /// Converts CPU cycles to time in milliseconds.
  79. ///
  80. /// \param cycles Number of CPU cycles.
  81. ///
  82. /// \return Equivalent number of milliseconds (truncated to integer).
  83. static inline uint64_t
  84. xos_cycles_to_msecs(uint64_t cycles)
  85. {
  86. return (cycles * 1000) / xos_clock_freq;
  87. }
  88. /// Converts CPU cycles to time in microseconds.
  89. ///
  90. /// \param cycles Number of CPU cycles.
  91. ///
  92. /// \return Equivalent number of microseconds (truncated to integer).
  93. static inline uint64_t
  94. xos_cycles_to_usecs(uint64_t cycles)
  95. {
  96. return (cycles * 1000000) / xos_clock_freq;
  97. }
  98. /// Converts time in seconds to CPU cycle count.
  99. ///
  100. /// \param secs Number of seconds.
  101. ///
  102. /// \return Equivalent number of CPU cycles.
  103. static inline uint64_t
  104. xos_secs_to_cycles(uint64_t secs)
  105. {
  106. return secs * xos_clock_freq;
  107. }
  108. /// Converts time in milliseconds to CPU cycle count.
  109. ///
  110. /// \param msecs Number of milliseconds.
  111. ///
  112. /// \return Equivalent number of CPU cycles.
  113. static inline uint64_t
  114. xos_msecs_to_cycles(uint64_t msecs)
  115. {
  116. return (msecs * xos_clock_freq) / 1000;
  117. }
  118. /// Converts time in microseconds to CPU cycle count.
  119. ///
  120. /// \param usecs Number of microseconds.
  121. ///
  122. /// \return Equivalent number of CPU cycles.
  123. static inline uint64_t
  124. xos_usecs_to_cycles(uint64_t usecs)
  125. {
  126. return (usecs * xos_clock_freq) / 1000000;
  127. }
  128. ///@}
  129. //-----------------------------------------------------------------------------
  130. ///
  131. /// Set system clock frequency. This is expected to be set only once, and only
  132. /// if the clock frequency is not known at compile time.
  133. ///
  134. /// \param freq Frequency in cycles per second.
  135. ///
  136. /// \return Returns nothing.
  137. ///
  138. //-----------------------------------------------------------------------------
  139. static inline void
  140. xos_set_clock_freq(uint32_t freq)
  141. {
  142. xos_clock_freq = freq;
  143. }
  144. //-----------------------------------------------------------------------------
  145. ///
  146. /// Get current system clock frequency.
  147. ///
  148. /// \return Returns current system clock frequency in cycles per second.
  149. ///
  150. //-----------------------------------------------------------------------------
  151. static inline uint32_t
  152. xos_get_clock_freq()
  153. {
  154. return xos_clock_freq;
  155. }
  156. //-----------------------------------------------------------------------------
  157. ///
  158. /// Initialize timer support and start the system timer.
  159. /// This function must be called before calling any other timer function.
  160. ///
  161. /// NOTE: The smaller the tick period, the more precisely delays can be
  162. /// specified using timers. However, we also need to make the tick period
  163. /// large enough to allow time both to execute the tick timer interrupt handler
  164. /// and for the application to make reasonable forward progress. If tick_period
  165. /// is too small, the timer interrupt may re-trigger before the timer interrupt
  166. /// handler has returned to the application, thus keeping the processor busy in
  167. /// constantly executing the timer interrupt handler without leaving any cycles
  168. /// for the application. Or, the application might get some cycles but only a
  169. /// fraction of what is spent in the timer interrupt handler, thus severely
  170. /// impacting application performance.
  171. ///
  172. /// The exact number of cycles needed to execute the timer interrupt handler
  173. /// is not specified here. It depends on many factors (e.g. use of caches,
  174. /// various processor configuration options, etc) and can vary by orders of
  175. /// magnitude. Also note that the time to execute this handler is variable:
  176. /// when timers expire upon a given tick timer interrupt, their respective
  177. /// timer handler functions are called from within the interrupt handler.
  178. ///
  179. /// \param timer_num Which Xtensa timer to use (0..2). This timer
  180. /// must exist and be configured at level 1 or at a
  181. /// medium-priority interrupt level (<=EXCM_LEVEL).
  182. /// If 'timer_num' is -1, then this function will
  183. /// automatically choose the highest priority timer
  184. /// that is suitable for use. This value will be
  185. /// passed to xos_system_timer_select().
  186. ///
  187. /// \param tick_period Number of clock (CCOUNT) cycles between ticks.
  188. /// Must range between 0 and UINT32_MAX.
  189. /// Zero is used to specify dynamic tick (tickless)
  190. /// mode.
  191. ///
  192. /// \return Returns XOS_OK on success, else error code.
  193. ///
  194. //-----------------------------------------------------------------------------
  195. int32_t
  196. xos_start_system_timer(int32_t timer_num, uint32_t tick_period);
  197. //-----------------------------------------------------------------------------
  198. ///
  199. /// Get the timer number of the system timer. Useful mainly when XOS has been
  200. /// allowed to choose its own timer via xos_start_system_timer(). Not valid if
  201. /// called before the system timer has been started.
  202. ///
  203. /// \return Returns one of XOS_SYS_TIMER_0, XOS_SYS_TIMER_1, XOS_SYS_TIMER_2
  204. /// or XOS_SYS_TIMER_EXTERNAL, or XOS_SYS_TIMER_NONE.
  205. ///
  206. //-----------------------------------------------------------------------------
  207. int32_t
  208. xos_get_system_timer_num(void);
  209. //-----------------------------------------------------------------------------
  210. ///
  211. /// Initialize timer object.
  212. ///
  213. /// \param timer Pointer to timer event structure.
  214. ///
  215. /// \return Returns nothing.
  216. ///
  217. /// NOTE: This function should not be called on a timer object once it has
  218. /// been activated.
  219. ///
  220. //-----------------------------------------------------------------------------
  221. void xos_timer_init(XosTimer * timer);
  222. //-----------------------------------------------------------------------------
  223. // Flags for xos_timer_start().
  224. //-----------------------------------------------------------------------------
  225. #define XOS_TIMER_DELTA 0x0000
  226. #define XOS_TIMER_PERIODIC 0x0001
  227. #define XOS_TIMER_ABSOLUTE 0x0002
  228. #define XOS_TIMER_FROM_NOW 0x0000
  229. #define XOS_TIMER_FROM_LAST 0x0010
  230. //-----------------------------------------------------------------------------
  231. ///
  232. /// Start the timer, and when the timer expires, call the specified function
  233. /// (invoke (*fn)(arg)). If the timer is periodic, it will be automatically
  234. /// restarted when it expires.
  235. ///
  236. /// The specified timer event structure must have been initialized before
  237. /// first use by calling xos_timer_init().
  238. ///
  239. /// The callback function will be called in an interrupt context. Hence it is
  240. /// NOT safe to use any coprocessors in the function, including the FPU. If a
  241. /// coprocessor must be used, then its state must be saved and restored across
  242. /// its use.
  243. ///
  244. /// NOTE: If you are using the timer only to wait on (via xos_timer_wait())
  245. /// then it is not necessary to specify a callback function. You should pass
  246. /// NULL for the callback function and zero for the callback argument.
  247. ///
  248. /// \param timer Pointer to timer event structure. Must have been
  249. /// initialized. May be active or not.
  250. ///
  251. /// \param when When to call the function (see flags).
  252. ///
  253. /// \param flags Set of option flags XOS_TIMER_* \n
  254. /// The following flags are mutually exclusive:
  255. /// - XOS_TIMER_DELTA -- when is number of cycles from
  256. /// [see below] (default)
  257. /// - XOS_TIMER_PERIODIC -- when is number of cycles
  258. /// from [see below], and timer continually
  259. /// re-triggers at that interval
  260. /// - XOS_TIMER_ABSOLUTE -- when is absolute value of
  261. /// cycle count \n
  262. /// \n
  263. /// The following flags are mutually exclusive:
  264. /// - XOS_TIMER_FROM_NOW -- *DELTA and *PERIODIC are
  265. /// relative to now (default)
  266. /// - XOS_TIMER_FROM_LAST -- *DELTA and *PERIODIC are
  267. /// relative to the timer event's last specified expiry
  268. /// time (usually in the future if active, in the past
  269. /// if not, absolute 0 if was never activated).
  270. ///
  271. /// \param func Function to call (called in timer interrupt context).
  272. /// This argument is optional. Specify NULL if no function
  273. /// is to be called.
  274. ///
  275. /// \param arg Argument passed to callback function. Only relevant if
  276. /// 'func' is not NULL.
  277. ///
  278. /// \return Returns XOS_OK on success, else error code.
  279. ///
  280. //-----------------------------------------------------------------------------
  281. int32_t
  282. xos_timer_start(XosTimer * timer,
  283. uint64_t when,
  284. uint32_t flags,
  285. XosTimerFunc * func,
  286. void * arg);
  287. //-----------------------------------------------------------------------------
  288. ///
  289. /// Stop the timer and remove it from the list of active timers. Has no effect
  290. /// if the timer is not active. Any waiting threads are woken up.
  291. ///
  292. /// The timer structure must have been initialized at least once, else its
  293. /// contents are undefined and can lead to unpredictable results.
  294. ///
  295. /// \param timer Pointer to timer object.
  296. ///
  297. /// \return Returns XOS_OK on success, else error code.
  298. ///
  299. //-----------------------------------------------------------------------------
  300. int32_t
  301. xos_timer_stop(XosTimer * timer);
  302. //-----------------------------------------------------------------------------
  303. ///
  304. /// Reset and restart the timer.
  305. ///
  306. /// The timer is reset to go off at time "when" from now. If the timer was not
  307. /// active, it will be activated. If the timer was active, it will be restarted.
  308. /// If the timer is periodic, the period will be set to "when".
  309. /// The timer object must have been initialized at some point before this call.
  310. ///
  311. /// \param timer Pointer to timer object.
  312. ///
  313. /// \param when Number of cycles from now that the timer will expire.
  314. ///
  315. /// \return Returns XOS_OK on success, else error code.
  316. ///
  317. //-----------------------------------------------------------------------------
  318. int32_t
  319. xos_timer_restart(XosTimer * timer, uint64_t when);
  320. //-----------------------------------------------------------------------------
  321. ///
  322. /// Check if the timer is active. The timer is active if it has been started
  323. /// and not yet expired or canceled.
  324. ///
  325. /// \param timer Pointer to timer object.
  326. ///
  327. /// \return Returns non-zero if the timer is active, else zero.
  328. ///
  329. //-----------------------------------------------------------------------------
  330. static inline int32_t
  331. xos_timer_is_active(XosTimer * timer)
  332. {
  333. return timer ? timer->active : 0;
  334. }
  335. //-----------------------------------------------------------------------------
  336. ///
  337. /// Get the repeat period for a periodic timer. For a one-shot timer this will
  338. /// return zero. The period is reported in system clock cycles.
  339. ///
  340. /// \param timer Pointer to timer object.
  341. ///
  342. /// \return Returns period in cycles, or zero for non-periodic timers.
  343. ///
  344. //-----------------------------------------------------------------------------
  345. static inline uint64_t
  346. xos_timer_get_period(XosTimer * timer)
  347. {
  348. return timer ? timer->delta : 0;
  349. }
  350. //-----------------------------------------------------------------------------
  351. ///
  352. /// Set the repeat period for a periodic timer. The period must be specified
  353. /// in system clock cycles.
  354. ///
  355. /// If the timer is active, the change in period does not take effect until
  356. /// the timer expires at least once after this call.
  357. /// Note that setting a period of zero will effectively turn a periodic timer
  358. /// into a one-shot timer. Similarly, a one-shot timer can be turned into a
  359. /// periodic timer.
  360. ///
  361. /// \param timer Pointer to timer object.
  362. ///
  363. /// \param period Repeat period in system clock cycles.
  364. ///
  365. /// \return Returns XOS_OK on success, else error code.
  366. ///
  367. //-----------------------------------------------------------------------------
  368. int32_t
  369. xos_timer_set_period(XosTimer * timer, uint64_t period);
  370. //-----------------------------------------------------------------------------
  371. ///
  372. /// Get the current system cycle count. This accounts for the periodic rollover
  373. /// of the 32-bit CCOUNT cycle counter and returns a 64-bit value.
  374. ///
  375. /// \return Returns the current system cycle count.
  376. ///
  377. //-----------------------------------------------------------------------------
  378. static inline uint64_t
  379. xos_get_system_cycles(void)
  380. {
  381. extern uint64_t xos_system_cycles;
  382. extern uint32_t xos_last_ccount;
  383. // xos_last_ccount was updated when xos_system_cycles was last updated.
  384. // We need to add in the number of cycles elapsed since then.
  385. return xos_system_cycles + (xos_get_ccount() - xos_last_ccount);
  386. }
  387. //-----------------------------------------------------------------------------
  388. ///
  389. /// Put calling thread to sleep for at least the specified number of cycles.
  390. /// The actual number of cycles spent sleeping may be larger depending upon
  391. /// the granularity of the system timer. Once the specified time has elapsed
  392. /// the thread will be woken and made ready.
  393. ///
  394. /// \param cycles Number of system clock cycles to sleep.
  395. ///
  396. /// \return Returns XOS_OK on success, else error code.
  397. ///
  398. //-----------------------------------------------------------------------------
  399. int32_t
  400. xos_thread_sleep(uint64_t cycles);
  401. //-----------------------------------------------------------------------------
  402. ///
  403. /// Put calling thread to sleep for at least the specified number of msec.
  404. /// The actual amount of time spent sleeping may be larger depending upon
  405. /// the granularity of the system timer. Once the specified time has elapsed
  406. /// the thread will be woken and made ready.
  407. ///
  408. /// \return msecs The number of milliseconds to sleep.
  409. ///
  410. /// \return Returns XOS_OK on success, else error code.
  411. ///
  412. //-----------------------------------------------------------------------------
  413. static inline int32_t
  414. xos_thread_sleep_msec(uint64_t msecs)
  415. {
  416. return xos_thread_sleep(xos_msecs_to_cycles(msecs));
  417. }
  418. //-----------------------------------------------------------------------------
  419. ///
  420. /// Put calling thread to sleep for at least the specified number of usec.
  421. /// The actual amount of time spent sleeping may be larger depending upon
  422. /// the granularity of the system timer. Once the specified time has elapsed
  423. /// the thread will be woken and made ready.
  424. ///
  425. /// \return usecs The number of microseconds to sleep.
  426. ///
  427. /// \return Returns XOS_OK on success, else error code.
  428. ///
  429. //-----------------------------------------------------------------------------
  430. static inline int32_t
  431. xos_thread_sleep_usec(uint64_t usecs)
  432. {
  433. return xos_thread_sleep(xos_usecs_to_cycles(usecs));
  434. }
  435. //-----------------------------------------------------------------------------
  436. ///
  437. /// Wait on a timer until it expires or is cancelled. The calling thread will
  438. /// be blocked. The timer must be active.
  439. /// NOTE: This operation is only available if XOS_OPT_TIMER_WAIT is set
  440. /// to 1 in the configuration options.
  441. ///
  442. /// \param timer Pointer to timer object.
  443. ///
  444. /// \return Returns XOS_OK on normal timeout, else an error code.
  445. ///
  446. //-----------------------------------------------------------------------------
  447. int32_t
  448. xos_timer_wait(XosTimer * timer);
  449. //-----------------------------------------------------------------------------
  450. // System timer control interface.
  451. //-----------------------------------------------------------------------------
  452. //-----------------------------------------------------------------------------
  453. // Defines for system timer ID.
  454. //-----------------------------------------------------------------------------
  455. #define XOS_SYS_TIMER_0 0 ///< Internal timer 0
  456. #define XOS_SYS_TIMER_1 1 ///< Internal timer 1
  457. #define XOS_SYS_TIMER_2 2 ///< Internal timer 2
  458. #define XOS_SYS_TIMER_EXTERNAL -2 ///< External timer
  459. #define XOS_SYS_TIMER_NONE -1 ///< No system timer selected
  460. //-----------------------------------------------------------------------------
  461. ///
  462. /// This function handles XOS timer tick processing. It must be called by the
  463. /// timer interrupt handler on every timer interrupt. This function computes
  464. /// the time to the next tick and sets it up by calling xos_system_timer_set().
  465. ///
  466. //-----------------------------------------------------------------------------
  467. void
  468. xos_tick_handler(void);
  469. //-----------------------------------------------------------------------------
  470. ///
  471. /// Selects the timer to use. The selection may be one of the internal timers
  472. /// or an external timer. The default implementation selects an internal timer.
  473. /// This function can be overridden to provide custom timer processing or to
  474. /// support an external timer.
  475. ///
  476. /// \param timer_num The internal timer number to select (0-2) or
  477. /// -1 to auto-select a timer. This parameter can
  478. /// be ignored by custom implementations that use
  479. /// an external timer.
  480. ///
  481. /// \param psel Pointer to a location where the selected timer
  482. /// ID must be returned. The timer ID must be one
  483. /// of XOS_SYS_TIMER_0, XOS_SYS_TIMER_1, XOS_SYS_TIMER_2
  484. /// or XOS_SYS_TIMER_EXTERNAL.
  485. ///
  486. /// \return Returns XOS_OK on success, else error code.
  487. ///
  488. //-----------------------------------------------------------------------------
  489. int32_t
  490. xos_system_timer_select(int32_t timer_num, int32_t *psel);
  491. //-----------------------------------------------------------------------------
  492. ///
  493. /// Starts the system timer and sets up the first interrupt. This function can
  494. /// be overridden to provide custom timer processing or to support an external
  495. /// timer.
  496. ///
  497. /// \param cycles The number of CPU cycles from now when the
  498. /// first interrupt must occur.
  499. ///
  500. //-----------------------------------------------------------------------------
  501. void
  502. xos_system_timer_init(uint32_t cycles);
  503. //-----------------------------------------------------------------------------
  504. ///
  505. /// Sets the next trigger value of the system timer. The parameter 'cycles' is
  506. /// the number of CPU cycles from now when the interrupt must occur.
  507. /// This function can be overridden to provide custom timer processing or to
  508. /// support an external timer.
  509. ///
  510. /// \param cycles The number of CPU cycles from now when the
  511. /// next interrupt must occur.
  512. ///
  513. //-----------------------------------------------------------------------------
  514. void
  515. xos_system_timer_set(uint32_t cycles);
  516. #ifdef __cplusplus
  517. }
  518. #endif
  519. #endif // __XOS_TIMER_H__