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