chtime.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /*
  2. ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
  3. This file is part of ChibiOS.
  4. ChibiOS is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. ChibiOS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /**
  16. * @file chtime.h
  17. * @brief Time and intervals macros and structures.
  18. *
  19. * @addtogroup time_intervals
  20. * @details This module is responsible for handling of system time and time
  21. * intervals.
  22. * @{
  23. */
  24. #ifndef CHTIME_H
  25. #define CHTIME_H
  26. /*===========================================================================*/
  27. /* Module constants. */
  28. /*===========================================================================*/
  29. /**
  30. * @name Special time constants
  31. * @{
  32. */
  33. /**
  34. * @brief Zero interval specification for some functions with a timeout
  35. * specification.
  36. * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
  37. * see the specific function documentation.
  38. */
  39. #define TIME_IMMEDIATE ((sysinterval_t)0)
  40. /**
  41. * @brief Infinite interval specification for all functions with a timeout
  42. * specification.
  43. * @note Not all functions accept @p TIME_INFINITE as timeout parameter,
  44. * see the specific function documentation.
  45. */
  46. #define TIME_INFINITE ((sysinterval_t)-1)
  47. /**
  48. * @brief Maximum interval constant usable as timeout.
  49. */
  50. #define TIME_MAX_INTERVAL ((sysinterval_t)-2)
  51. /**
  52. * @brief Maximum system of system time before it wraps.
  53. */
  54. #define TIME_MAX_SYSTIME ((systime_t)-1)
  55. /** @} */
  56. /*===========================================================================*/
  57. /* Module pre-compile time settings. */
  58. /*===========================================================================*/
  59. /*===========================================================================*/
  60. /* Derived constants and error checks. */
  61. /*===========================================================================*/
  62. #if (CH_CFG_ST_RESOLUTION != 16) && (CH_CFG_ST_RESOLUTION != 32) && \
  63. (CH_CFG_ST_RESOLUTION != 64)
  64. #error "invalid CH_CFG_ST_RESOLUTION specified, must be 16, 32 or 64"
  65. #endif
  66. #if CH_CFG_ST_FREQUENCY < 10
  67. #error "invalid CH_CFG_ST_FREQUENCY specified, must be >= 10"
  68. #endif
  69. #if (CH_CFG_INTERVALS_SIZE != 16) && (CH_CFG_INTERVALS_SIZE != 32) && \
  70. (CH_CFG_INTERVALS_SIZE != 64)
  71. #error "invalid CH_CFG_INTERVALS_SIZE specified, must be 16, 32 or 64"
  72. #endif
  73. #if (CH_CFG_TIME_TYPES_SIZE != 16) && (CH_CFG_TIME_TYPES_SIZE != 32)
  74. #error "invalid CH_CFG_TIME_TYPES_SIZE specified, must be 16 or 32"
  75. #endif
  76. #if CH_CFG_INTERVALS_SIZE < CH_CFG_ST_RESOLUTION
  77. #error "CH_CFG_INTERVALS_SIZE must be >= CH_CFG_ST_RESOLUTION"
  78. #endif
  79. /*===========================================================================*/
  80. /* Module data structures and types. */
  81. /*===========================================================================*/
  82. /**
  83. * @brief Type of system time.
  84. * @note It is selectable in configuration between 16, 32 or 64 bits.
  85. */
  86. #if (CH_CFG_ST_RESOLUTION == 64) || defined(__DOXYGEN__)
  87. typedef uint64_t systime_t;
  88. #elif CH_CFG_ST_RESOLUTION == 32
  89. typedef uint32_t systime_t;
  90. #elif CH_CFG_ST_RESOLUTION == 16
  91. typedef uint16_t systime_t;
  92. #endif
  93. /**
  94. * @brief Type of time interval.
  95. * @note It is selectable in configuration between 16, 32 or 64 bits.
  96. */
  97. #if (CH_CFG_INTERVALS_SIZE == 64) || defined(__DOXYGEN__)
  98. typedef uint64_t sysinterval_t;
  99. #elif CH_CFG_INTERVALS_SIZE == 32
  100. typedef uint32_t sysinterval_t;
  101. #elif CH_CFG_INTERVALS_SIZE == 16
  102. typedef uint16_t sysinterval_t;
  103. #endif
  104. #if (CH_CFG_TIME_TYPES_SIZE == 32) || defined(__DOXYGEN__)
  105. /**
  106. * @brief Type of seconds.
  107. * @note It is selectable in configuration between 16 or 32 bits.
  108. */
  109. typedef uint32_t time_secs_t;
  110. /**
  111. * @brief Type of milliseconds.
  112. * @note It is selectable in configuration between 16 or 32 bits.
  113. */
  114. typedef uint32_t time_msecs_t;
  115. /**
  116. * @brief Type of microseconds.
  117. * @note It is selectable in configuration between 16 or 32 bits.
  118. */
  119. typedef uint32_t time_usecs_t;
  120. /**
  121. * @brief Type of time conversion variable.
  122. * @note This type must have double width than other time types, it is
  123. * only used internally for conversions.
  124. */
  125. typedef uint64_t time_conv_t;
  126. #else
  127. typedef uint16_t time_secs_t;
  128. typedef uint16_t time_msecs_t;
  129. typedef uint16_t time_usecs_t;
  130. typedef uint32_t time_conv_t;
  131. #endif
  132. /*===========================================================================*/
  133. /* Module macros. */
  134. /*===========================================================================*/
  135. /**
  136. * @name Fast time conversion utilities
  137. * @{
  138. */
  139. /**
  140. * @brief Seconds to time interval.
  141. * @details Converts from seconds to system ticks number.
  142. * @note The result is rounded upward to the next tick boundary.
  143. * @note Use of this macro for large values is not secure because
  144. * integer overflows, make sure your value can be correctly
  145. * converted.
  146. *
  147. * @param[in] secs number of seconds
  148. * @return The number of ticks.
  149. *
  150. * @api
  151. */
  152. #define TIME_S2I(secs) \
  153. ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)CH_CFG_ST_FREQUENCY))
  154. /**
  155. * @brief Milliseconds to time interval.
  156. * @details Converts from milliseconds to system ticks number.
  157. * @note The result is rounded upward to the next tick boundary.
  158. * @note Use of this macro for large values is not secure because
  159. * integer overflows, make sure your value can be correctly
  160. * converted.
  161. *
  162. * @param[in] msecs number of milliseconds
  163. * @return The number of ticks.
  164. *
  165. * @api
  166. */
  167. #if CH_CFG_ST_FREQUENCY == 1000000
  168. #define TIME_MS2I(msecs) ((sysinterval_t)((time_conv_t)(msecs))*(time_conv_t)1000)
  169. #else
  170. #define TIME_MS2I(msecs) \
  171. ((sysinterval_t)((((time_conv_t)(msecs) * \
  172. (time_conv_t)CH_CFG_ST_FREQUENCY) + \
  173. (time_conv_t)999) / (time_conv_t)1000))
  174. #endif
  175. /**
  176. * @brief Microseconds to time interval.
  177. * @details Converts from microseconds to system ticks number.
  178. * @note The result is rounded upward to the next tick boundary.
  179. * @note Use of this macro for large values is not secure because
  180. * integer overflows, make sure your value can be correctly
  181. * converted.
  182. *
  183. * @param[in] usecs number of microseconds
  184. * @return The number of ticks.
  185. *
  186. * @api
  187. */
  188. #if CH_CFG_ST_FREQUENCY == 1000000
  189. #define TIME_US2I(usecs) ((sysinterval_t)(usecs))
  190. #else
  191. #define TIME_US2I(usecs) \
  192. ((sysinterval_t)((((time_conv_t)(usecs) * \
  193. (time_conv_t)CH_CFG_ST_FREQUENCY) + \
  194. (time_conv_t)999999) / (time_conv_t)1000000))
  195. #endif
  196. /**
  197. * @brief Time interval to seconds.
  198. * @details Converts from system ticks number to seconds.
  199. * @note The result is rounded up to the next second boundary.
  200. * @note Use of this macro for large values is not secure because
  201. * integer overflows, make sure your value can be correctly
  202. * converted.
  203. *
  204. * @param[in] interval interval in ticks
  205. * @return The number of seconds.
  206. *
  207. * @api
  208. */
  209. #define TIME_I2S(interval) \
  210. (time_secs_t)(((time_conv_t)(interval) + \
  211. (time_conv_t)CH_CFG_ST_FREQUENCY - \
  212. (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY)
  213. /**
  214. * @brief Time interval to milliseconds.
  215. * @details Converts from system ticks number to milliseconds.
  216. * @note The result is rounded up to the next millisecond boundary.
  217. * @note Use of this macro for large values is not secure because
  218. * integer overflows, make sure your value can be correctly
  219. * converted.
  220. *
  221. * @param[in] interval interval in ticks
  222. * @return The number of milliseconds.
  223. *
  224. * @api
  225. */
  226. #if CH_CFG_ST_FREQUENCY == 1000000
  227. #define TIME_I2MS(interval) \
  228. (time_msecs_t)(((time_conv_t)(interval)+999)/(time_conv_t)1000)
  229. #else
  230. #define TIME_I2MS(interval) \
  231. (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \
  232. (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
  233. (time_conv_t)CH_CFG_ST_FREQUENCY)
  234. #endif
  235. /**
  236. * @brief Time interval to microseconds.
  237. * @details Converts from system ticks number to microseconds.
  238. * @note The result is rounded up to the next microsecond boundary.
  239. * @note Use of this macro for large values is not secure because
  240. * integer overflows, make sure your value can be correctly
  241. * converted.
  242. *
  243. * @param[in] interval interval in ticks
  244. * @return The number of microseconds.
  245. *
  246. * @api
  247. */
  248. #if CH_CFG_ST_FREQUENCY == 1000000
  249. #define TIME_I2US(interval) ((time_usecs_t)(interval))
  250. #else
  251. #define TIME_I2US(interval) \
  252. (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \
  253. (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
  254. (time_conv_t)CH_CFG_ST_FREQUENCY)
  255. #endif
  256. /** @} */
  257. /*===========================================================================*/
  258. /* External declarations. */
  259. /*===========================================================================*/
  260. /*
  261. * Virtual Timers APIs.
  262. */
  263. #ifdef __cplusplus
  264. extern "C" {
  265. #endif
  266. #ifdef __cplusplus
  267. }
  268. #endif
  269. /*===========================================================================*/
  270. /* Module inline functions. */
  271. /*===========================================================================*/
  272. /**
  273. * @name Secure time conversion utilities
  274. * @{
  275. */
  276. /**
  277. * @brief Seconds to time interval.
  278. * @details Converts from seconds to system ticks number.
  279. * @note The result is rounded upward to the next tick boundary.
  280. *
  281. * @param[in] secs number of seconds
  282. * @return The number of ticks.
  283. *
  284. * @special
  285. */
  286. static inline sysinterval_t chTimeS2I(time_secs_t secs) {
  287. time_conv_t ticks;
  288. ticks = (time_conv_t)secs * (time_conv_t)CH_CFG_ST_FREQUENCY;
  289. chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
  290. "conversion overflow");
  291. return (sysinterval_t)ticks;
  292. }
  293. /**
  294. * @brief Milliseconds to time interval.
  295. * @details Converts from milliseconds to system ticks number.
  296. * @note The result is rounded upward to the next tick boundary.
  297. *
  298. * @param[in] msec number of milliseconds
  299. * @return The number of ticks.
  300. *
  301. * @special
  302. */
  303. static inline sysinterval_t chTimeMS2I(time_msecs_t msec) {
  304. time_conv_t ticks;
  305. #if CH_CFG_ST_FREQUENCY == 1000000
  306. ticks = msec*(time_conv_t)1000;
  307. #else
  308. ticks = (((time_conv_t)msec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
  309. (time_conv_t)999) / (time_conv_t)1000;
  310. #endif
  311. chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
  312. "conversion overflow");
  313. return (sysinterval_t)ticks;
  314. }
  315. /**
  316. * @brief Microseconds to time interval.
  317. * @details Converts from microseconds to system ticks number.
  318. * @note The result is rounded upward to the next tick boundary.
  319. *
  320. * @param[in] usec number of microseconds
  321. * @return The number of ticks.
  322. *
  323. * @special
  324. */
  325. static inline sysinterval_t chTimeUS2I(time_usecs_t usec) {
  326. time_conv_t ticks;
  327. #if CH_CFG_ST_FREQUENCY == 1000000
  328. ticks = usec;
  329. #else
  330. ticks = (((time_conv_t)usec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
  331. (time_conv_t)999999) / (time_conv_t)1000000;
  332. #endif
  333. chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
  334. "conversion overflow");
  335. return (sysinterval_t)ticks;
  336. }
  337. /**
  338. * @brief Time interval to seconds.
  339. * @details Converts from system interval to seconds.
  340. * @note The result is rounded up to the next second boundary.
  341. *
  342. * @param[in] interval interval in ticks
  343. * @return The number of seconds.
  344. *
  345. * @special
  346. */
  347. static inline time_secs_t chTimeI2S(sysinterval_t interval) {
  348. time_conv_t secs;
  349. secs = ((time_conv_t)interval +
  350. (time_conv_t)CH_CFG_ST_FREQUENCY -
  351. (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY;
  352. chDbgAssert(secs < (time_conv_t)((time_secs_t)-1),
  353. "conversion overflow");
  354. return (time_secs_t)secs;
  355. }
  356. /**
  357. * @brief Time interval to milliseconds.
  358. * @details Converts from system interval to milliseconds.
  359. * @note The result is rounded up to the next millisecond boundary.
  360. *
  361. * @param[in] interval interval in ticks
  362. * @return The number of milliseconds.
  363. *
  364. * @special
  365. */
  366. static inline time_msecs_t chTimeI2MS(sysinterval_t interval) {
  367. time_conv_t msecs;
  368. #if CH_CFG_ST_FREQUENCY == 1000000
  369. msecs = ((interval + (time_conv_t)999)/(time_conv_t)1000);
  370. #else
  371. msecs = (((time_conv_t)interval * (time_conv_t)1000) +
  372. (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
  373. (time_conv_t)CH_CFG_ST_FREQUENCY;
  374. #endif
  375. chDbgAssert(msecs < (time_conv_t)((time_msecs_t)-1),
  376. "conversion overflow");
  377. return (time_msecs_t)msecs;
  378. }
  379. /**
  380. * @brief Time interval to microseconds.
  381. * @details Converts from system interval to microseconds.
  382. * @note The result is rounded up to the next microsecond boundary.
  383. *
  384. * @param[in] interval interval in ticks
  385. * @return The number of microseconds.
  386. *
  387. * @special
  388. */
  389. static inline time_usecs_t chTimeI2US(sysinterval_t interval) {
  390. time_conv_t usecs;
  391. #if CH_CFG_ST_FREQUENCY == 1000000
  392. usecs = (time_conv_t)interval;
  393. #else
  394. usecs = (((time_conv_t)interval * (time_conv_t)1000000) +
  395. (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
  396. (time_conv_t)CH_CFG_ST_FREQUENCY;
  397. #endif
  398. chDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
  399. "conversion overflow");
  400. return (time_usecs_t)usecs;
  401. }
  402. /**
  403. * @brief Time interval to microseconds 64 bit if supported.
  404. * @details Converts from system interval to microseconds.
  405. * @note The result is rounded up to the next microsecond boundary.
  406. *
  407. * @param[in] interval interval in ticks
  408. * @return The number of microseconds.
  409. *
  410. * @special
  411. */
  412. static inline time_usecs_t chTimeI2US64(sysinterval_t interval) {
  413. time_conv_t usecs;
  414. #if CH_CFG_ST_FREQUENCY == 1000000
  415. usecs = (time_conv_t)interval;
  416. #else
  417. usecs = (((time_conv_t)interval * (time_conv_t)1000000) +
  418. (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
  419. (time_conv_t)CH_CFG_ST_FREQUENCY;
  420. #endif
  421. chDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
  422. "conversion overflow");
  423. return (time_conv_t)usecs;
  424. }
  425. /**
  426. * @brief Adds an interval to a system time returning a system time.
  427. *
  428. * @param[in] systime base system time
  429. * @param[in] interval interval to be added
  430. * @return The new system time.
  431. *
  432. * @xclass
  433. */
  434. static inline systime_t chTimeAddX(systime_t systime,
  435. sysinterval_t interval) {
  436. #if CH_CFG_ST_RESOLUTION != CH_CFG_INTERVALS_SIZE
  437. chDbgCheck(interval <= (sysinterval_t)((systime_t)-1));
  438. #endif
  439. return systime + (systime_t)interval;
  440. }
  441. /**
  442. * @brief Subtracts two system times returning an interval.
  443. *
  444. * @param[in] start first system time
  445. * @param[in] end second system time
  446. * @return The interval representing the time difference.
  447. *
  448. * @xclass
  449. */
  450. static inline sysinterval_t chTimeDiffX(systime_t start, systime_t end) {
  451. /*lint -save -e9033 [10.8] This cast is required by the operation, it is
  452. known that the destination type can be wider.*/
  453. return (sysinterval_t)((systime_t)(end - start));
  454. /*lint -restore*/
  455. }
  456. /**
  457. * @brief Checks if the specified time is within the specified time range.
  458. * @note When start==end then the function returns always true because the
  459. * whole time range is specified.
  460. *
  461. * @param[in] time the time to be verified
  462. * @param[in] start the start of the time window (inclusive)
  463. * @param[in] end the end of the time window (non inclusive)
  464. * @retval true current time within the specified time window.
  465. * @retval false current time not within the specified time window.
  466. *
  467. * @xclass
  468. */
  469. static inline bool chTimeIsInRangeX(systime_t time,
  470. systime_t start,
  471. systime_t end) {
  472. return (bool)((time - start) < (end - start));
  473. }
  474. /** @} */
  475. #endif /* CHTIME_H */
  476. /** @} */