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