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