ChibiOS/RT  6.0.3
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  * @name Fast time conversion utilities
165  * @{
166  */
167 /**
168  * @brief Seconds to time interval.
169  * @details Converts from seconds to system ticks number.
170  * @note The result is rounded upward to the next tick boundary.
171  * @note Use of this macro for large values is not secure because
172  * integer overflows, make sure your value can be correctly
173  * converted.
174  *
175  * @param[in] secs number of seconds
176  * @return The number of ticks.
177  *
178  * @api
179  */
180 #define TIME_S2I(secs) \
181  ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)CH_CFG_ST_FREQUENCY))
182 
183 /**
184  * @brief Milliseconds to time interval.
185  * @details Converts from milliseconds to system ticks number.
186  * @note The result is rounded upward to the next tick boundary.
187  * @note Use of this macro for large values is not secure because
188  * integer overflows, make sure your value can be correctly
189  * converted.
190  *
191  * @param[in] msecs number of milliseconds
192  * @return The number of ticks.
193  *
194  * @api
195  */
196 #define TIME_MS2I(msecs) \
197  ((sysinterval_t)((((time_conv_t)(msecs) * \
198  (time_conv_t)CH_CFG_ST_FREQUENCY) + \
199  (time_conv_t)999) / (time_conv_t)1000))
200 
201 /**
202  * @brief Microseconds to time interval.
203  * @details Converts from microseconds to system ticks number.
204  * @note The result is rounded upward to the next tick boundary.
205  * @note Use of this macro for large values is not secure because
206  * integer overflows, make sure your value can be correctly
207  * converted.
208  *
209  * @param[in] usecs number of microseconds
210  * @return The number of ticks.
211  *
212  * @api
213  */
214 #define TIME_US2I(usecs) \
215  ((sysinterval_t)((((time_conv_t)(usecs) * \
216  (time_conv_t)CH_CFG_ST_FREQUENCY) + \
217  (time_conv_t)999999) / (time_conv_t)1000000))
218 
219 /**
220  * @brief Time interval to seconds.
221  * @details Converts from system ticks number to seconds.
222  * @note The result is rounded up to the next second boundary.
223  * @note Use of this macro for large values is not secure because
224  * integer overflows, make sure your value can be correctly
225  * converted.
226  *
227  * @param[in] interval interval in ticks
228  * @return The number of seconds.
229  *
230  * @api
231  */
232 #define TIME_I2S(interval) \
233  (time_secs_t)(((time_conv_t)(interval) + \
234  (time_conv_t)CH_CFG_ST_FREQUENCY - \
235  (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY)
236 
237 /**
238  * @brief Time interval to milliseconds.
239  * @details Converts from system ticks number to milliseconds.
240  * @note The result is rounded up to the next millisecond boundary.
241  * @note Use of this macro for large values is not secure because
242  * integer overflows, make sure your value can be correctly
243  * converted.
244  *
245  * @param[in] interval interval in ticks
246  * @return The number of milliseconds.
247  *
248  * @api
249  */
250 #define TIME_I2MS(interval) \
251  (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \
252  (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
253  (time_conv_t)CH_CFG_ST_FREQUENCY)
254 
255 /**
256  * @brief Time interval to microseconds.
257  * @details Converts from system ticks number to microseconds.
258  * @note The result is rounded up to the next microsecond boundary.
259  * @note Use of this macro for large values is not secure because
260  * integer overflows, make sure your value can be correctly
261  * converted.
262  *
263  * @param[in] interval interval in ticks
264  * @return The number of microseconds.
265  *
266  * @api
267  */
268 #define TIME_I2US(interval) \
269  (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \
270  (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
271  (time_conv_t)CH_CFG_ST_FREQUENCY)
272 /** @} */
273 
274 /*===========================================================================*/
275 /* External declarations. */
276 /*===========================================================================*/
277 
278 /*
279  * Virtual Timers APIs.
280  */
281 #ifdef __cplusplus
282 extern "C" {
283 #endif
284 
285 #ifdef __cplusplus
286 }
287 #endif
288 
289 /*===========================================================================*/
290 /* Module inline functions. */
291 /*===========================================================================*/
292 
293 /**
294  * @name Secure time conversion utilities
295  * @{
296  */
297 /**
298  * @brief Seconds to time interval.
299  * @details Converts from seconds to system ticks number.
300  * @note The result is rounded upward to the next tick boundary.
301  *
302  * @param[in] secs number of seconds
303  * @return The number of ticks.
304  *
305  * @special
306  */
307 static inline sysinterval_t chTimeS2I(time_secs_t secs) {
308  time_conv_t ticks;
309 
311 
313  "conversion overflow");
314 
315  return (sysinterval_t)ticks;
316 }
317 
318 /**
319  * @brief Milliseconds to time interval.
320  * @details Converts from milliseconds to system ticks number.
321  * @note The result is rounded upward to the next tick boundary.
322  *
323  * @param[in] msec number of milliseconds
324  * @return The number of ticks.
325  *
326  * @special
327  */
328 static inline sysinterval_t chTimeMS2I(time_msecs_t msec) {
329  time_conv_t ticks;
330 
331  ticks = (((time_conv_t)msec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
332  (time_conv_t)999) / (time_conv_t)1000;
333 
335  "conversion overflow");
336 
337  return (sysinterval_t)ticks;
338 }
339 
340 /**
341  * @brief Microseconds to time interval.
342  * @details Converts from microseconds to system ticks number.
343  * @note The result is rounded upward to the next tick boundary.
344  *
345  * @param[in] usec number of microseconds
346  * @return The number of ticks.
347  *
348  * @special
349  */
350 static inline sysinterval_t chTimeUS2I(time_usecs_t usec) {
351  time_conv_t ticks;
352 
353  ticks = (((time_conv_t)usec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
354  (time_conv_t)999999) / (time_conv_t)1000000;
355 
357  "conversion overflow");
358 
359  return (sysinterval_t)ticks;
360 }
361 
362 /**
363  * @brief Time interval to seconds.
364  * @details Converts from system interval to seconds.
365  * @note The result is rounded up to the next second boundary.
366  *
367  * @param[in] interval interval in ticks
368  * @return The number of seconds.
369  *
370  * @special
371  */
372 static inline time_secs_t chTimeI2S(sysinterval_t interval) {
373  time_conv_t secs;
374 
375  secs = ((time_conv_t)interval +
378 
379  chDbgAssert(secs < (time_conv_t)((time_secs_t)-1),
380  "conversion overflow");
381 
382  return (time_secs_t)secs;
383 }
384 
385 /**
386  * @brief Time interval to milliseconds.
387  * @details Converts from system interval to milliseconds.
388  * @note The result is rounded up to the next millisecond boundary.
389  *
390  * @param[in] interval interval in ticks
391  * @return The number of milliseconds.
392  *
393  * @special
394  */
395 static inline time_msecs_t chTimeI2MS(sysinterval_t interval) {
396  time_conv_t msecs;
397 
398  msecs = (((time_conv_t)interval * (time_conv_t)1000) +
401 
402  chDbgAssert(msecs < (time_conv_t)((time_msecs_t)-1),
403  "conversion overflow");
404 
405  return (time_msecs_t)msecs;
406 }
407 
408 /**
409  * @brief Time interval to microseconds.
410  * @details Converts from system interval to microseconds.
411  * @note The result is rounded up to the next microsecond boundary.
412  *
413  * @param[in] interval interval in ticks
414  * @return The number of microseconds.
415  *
416  * @special
417  */
418 static inline time_usecs_t chTimeI2US(sysinterval_t interval) {
419  time_conv_t usecs;
420 
421  usecs = (((time_conv_t)interval * (time_conv_t)1000000) +
424 
425  chDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
426  "conversion overflow");
427 
428  return (time_usecs_t)usecs;
429 }
430 
431 /**
432  * @brief Adds an interval to a system time returning a system time.
433  *
434  * @param[in] systime base system time
435  * @param[in] interval interval to be added
436  * @return The new system time.
437  *
438  * @xclass
439  */
440 static inline systime_t chTimeAddX(systime_t systime,
441  sysinterval_t interval) {
442 
443 #if CH_CFG_ST_RESOLUTION != CH_CFG_INTERVALS_SIZE
445 #endif
446 
447  return systime + (systime_t)interval;
448 }
449 
450 /**
451  * @brief Subtracts two system times returning an interval.
452  *
453  * @param[in] start first system time
454  * @param[in] end second system time
455  * @return The interval representing the time difference.
456  *
457  * @xclass
458  */
459 static inline sysinterval_t chTimeDiffX(systime_t start, systime_t end) {
460 
461  /*lint -save -e9033 [10.8] This cast is required by the operation, it is
462  known that the destination type can be wider.*/
463  return (sysinterval_t)((systime_t)(end - start));
464  /*lint -restore*/
465 }
466 
467 /**
468  * @brief Checks if the specified time is within the specified time range.
469  * @note When start==end then the function returns always true because the
470  * whole time range is specified.
471  *
472  * @param[in] time the time to be verified
473  * @param[in] start the start of the time window (inclusive)
474  * @param[in] end the end of the time window (non inclusive)
475  * @retval true current time within the specified time window.
476  * @retval false current time not within the specified time window.
477  *
478  * @xclass
479  */
480 static inline bool chTimeIsInRangeX(systime_t time,
481  systime_t start,
482  systime_t end) {
483 
484  return (bool)((systime_t)((systime_t)time - (systime_t)start) <
485  (systime_t)((systime_t)end - (systime_t)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:307
static sysinterval_t chTimeDiffX(systime_t start, systime_t end)
Subtracts two system times returning an interval.
Definition: chtime.h:459
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:480
#define TIME_MAX_SYSTIME
Maximum system of system time before it wraps.
Definition: chtime.h:65
static sysinterval_t chTimeUS2I(time_usecs_t usec)
Microseconds to time interval.
Definition: chtime.h:350
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:418
static time_msecs_t chTimeI2MS(sysinterval_t interval)
Time interval to milliseconds.
Definition: chtime.h:395
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:328
static time_secs_t chTimeI2S(sysinterval_t interval)
Time interval to seconds.
Definition: chtime.h:372
#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:440
#define CH_CFG_ST_FREQUENCY
System tick frequency.
Definition: chconf.h:55
#define TIME_MAX_INTERVAL
Maximum interval constant usable as timeout.
Definition: chtime.h:60