ChibiOS  0.0.0
chtime.h
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 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; either version 3 of the License, or
9  (at your option) any later version.
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 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__)
107 typedef uint64_t systime_t;
108 #elif CH_CFG_ST_RESOLUTION == 32
109 typedef uint32_t systime_t;
110 #elif CH_CFG_ST_RESOLUTION == 16
111 typedef 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__)
119 typedef uint64_t sysinterval_t;
120 #elif CH_CFG_INTERVALS_SIZE == 32
121 typedef uint32_t sysinterval_t;
122 #elif CH_CFG_INTERVALS_SIZE == 16
123 typedef uint16_t sysinterval_t;
124 #endif
125 
126 #if (CH_CFG_TIME_TYPES_SIZE == 32) || defined(__DOXYGEN__)
127 /**
128  * @brief Type of seconds.
129  * @note It is selectable in configuration between 16 or 32 bits.
130  */
131 typedef uint32_t time_secs_t;
132 
133 /**
134  * @brief Type of milliseconds.
135  * @note It is selectable in configuration between 16 or 32 bits.
136  */
137 typedef uint32_t time_msecs_t;
138 
139 /**
140  * @brief Type of microseconds.
141  * @note It is selectable in configuration between 16 or 32 bits.
142  */
143 typedef uint32_t time_usecs_t;
144 
145 /**
146  * @brief Type of time conversion variable.
147  * @note This type must have double width than other time types, it is
148  * only used internally for conversions.
149  */
150 typedef uint64_t time_conv_t;
151 
152 #else
153 typedef uint16_t time_secs_t;
154 typedef uint16_t time_msecs_t;
155 typedef uint16_t time_usecs_t;
156 typedef uint32_t time_conv_t;
157 #endif
158 
159 /*===========================================================================*/
160 /* Module macros. */
161 /*===========================================================================*/
162 
163 
164 /**
165  * @name Fast time conversion utilities
166  * @{
167  */
168 /**
169  * @brief Seconds to time interval.
170  * @details Converts from seconds to system ticks number.
171  * @note The result is rounded upward to the next tick boundary.
172  * @note Use of this macro for large values is not secure because
173  * integer overflows, make sure your value can be correctly
174  * converted.
175  *
176  * @param[in] secs number of seconds
177  * @return The number of ticks.
178  *
179  * @api
180  */
181 #define TIME_S2I(secs) \
182  ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)CH_CFG_ST_FREQUENCY))
183 
184 /**
185  * @brief Milliseconds to time interval.
186  * @details Converts from milliseconds to system ticks number.
187  * @note The result is rounded upward to the next tick boundary.
188  * @note Use of this macro for large values is not secure because
189  * integer overflows, make sure your value can be correctly
190  * converted.
191  *
192  * @param[in] msecs number of milliseconds
193  * @return The number of ticks.
194  *
195  * @api
196  */
197 #define TIME_MS2I(msecs) \
198  ((sysinterval_t)((((time_conv_t)(msecs) * \
199  (time_conv_t)CH_CFG_ST_FREQUENCY) + \
200  (time_conv_t)999) / (time_conv_t)1000))
201 
202 /**
203  * @brief Microseconds to time interval.
204  * @details Converts from microseconds to system ticks number.
205  * @note The result is rounded upward to the next tick boundary.
206  * @note Use of this macro for large values is not secure because
207  * integer overflows, make sure your value can be correctly
208  * converted.
209  *
210  * @param[in] usecs number of microseconds
211  * @return The number of ticks.
212  *
213  * @api
214  */
215 #define TIME_US2I(usecs) \
216  ((sysinterval_t)((((time_conv_t)(usecs) * \
217  (time_conv_t)CH_CFG_ST_FREQUENCY) + \
218  (time_conv_t)999999) / (time_conv_t)1000000))
219 
220 /**
221  * @brief Time interval to seconds.
222  * @details Converts from system ticks number to seconds.
223  * @note The result is rounded up to the next second boundary.
224  * @note Use of this macro for large values is not secure because
225  * integer overflows, make sure your value can be correctly
226  * converted.
227  *
228  * @param[in] interval interval in ticks
229  * @return The number of seconds.
230  *
231  * @api
232  */
233 #define TIME_I2S(interval) \
234  (time_secs_t)(((time_conv_t)(interval) + \
235  (time_conv_t)CH_CFG_ST_FREQUENCY - \
236  (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY)
237 
238 /**
239  * @brief Time interval to milliseconds.
240  * @details Converts from system ticks number to milliseconds.
241  * @note The result is rounded up to the next millisecond boundary.
242  * @note Use of this macro for large values is not secure because
243  * integer overflows, make sure your value can be correctly
244  * converted.
245  *
246  * @param[in] interval interval in ticks
247  * @return The number of milliseconds.
248  *
249  * @api
250  */
251 #define TIME_I2MS(interval) \
252  (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \
253  (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
254  (time_conv_t)CH_CFG_ST_FREQUENCY)
255 
256 /**
257  * @brief Time interval to microseconds.
258  * @details Converts from system ticks number to microseconds.
259  * @note The result is rounded up to the next microsecond boundary.
260  * @note Use of this macro for large values is not secure because
261  * integer overflows, make sure your value can be correctly
262  * converted.
263  *
264  * @param[in] interval interval in ticks
265  * @return The number of microseconds.
266  *
267  * @api
268  */
269 #define TIME_I2US(interval) \
270  (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \
271  (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
272  (time_conv_t)CH_CFG_ST_FREQUENCY)
273 /** @} */
274 
275 /*===========================================================================*/
276 /* External declarations. */
277 /*===========================================================================*/
278 
279 /*
280  * Virtual Timers APIs.
281  */
282 #ifdef __cplusplus
283 extern "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  */
308 static inline sysinterval_t chTimeS2I(time_secs_t secs) {
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  */
329 static inline sysinterval_t chTimeMS2I(time_msecs_t msec) {
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  */
351 static inline sysinterval_t chTimeUS2I(time_usecs_t usec) {
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  */
373 static 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  */
396 static 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  */
419 static 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  */
441 static inline systime_t chTimeAddX(systime_t systime,
442  sysinterval_t interval) {
443 
444 #if CH_CFG_ST_RESOLUTION != CH_CFG_INTERVALS_SIZE
445  chDbgCheck(interval <= (sysinterval_t)((systime_t)-1));
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  */
460 static 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 true because the
471  * whole time range is specified.
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 current time within the specified time window.
477  * @retval false current time not within the specified time window.
478  *
479  * @xclass
480  */
481 static inline bool chTimeIsInRangeX(systime_t time,
482  systime_t start,
483  systime_t end) {
484 
485  return (bool)((time - start) < (end - start));
486 }
487 
488 /** @} */
489 
490 #endif /* CHTIME_H */
491 
492 /** @} */
uint64_t systime_t
Type of system time.
Definition: chtime.h:107
uint32_t time_secs_t
Type of seconds.
Definition: chtime.h:131
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
static sysinterval_t chTimeS2I(time_secs_t secs)
Seconds to time interval.
Definition: chtime.h:308
static sysinterval_t chTimeDiffX(systime_t start, systime_t end)
Subtracts two system times returning an interval.
Definition: chtime.h:460
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:481
static sysinterval_t chTimeUS2I(time_usecs_t usec)
Microseconds to time interval.
Definition: chtime.h:351
uint64_t time_conv_t
Type of time conversion variable.
Definition: chtime.h:150
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:101
static time_usecs_t chTimeI2US(sysinterval_t interval)
Time interval to microseconds.
Definition: chtime.h:419
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:143
uint32_t time_msecs_t
Type of milliseconds.
Definition: chtime.h:137
static sysinterval_t chTimeMS2I(time_msecs_t msec)
Milliseconds to time interval.
Definition: chtime.h:329
static time_secs_t chTimeI2S(sysinterval_t interval)
Time interval to seconds.
Definition: chtime.h:373
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
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
#define CH_CFG_ST_FREQUENCY
System tick frequency.
#define TIME_MAX_INTERVAL
Maximum interval constant usable as timeout.
Definition: chtime.h:60