ChibiOS  21.6.0
chvt.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/chvt.h
22  * @brief Time and Virtual Timers module macros and structures.
23  *
24  * @addtogroup time
25  * @{
26  */
27 
28 #ifndef CHVT_H
29 #define CHVT_H
30 
31 /*===========================================================================*/
32 /* Module constants. */
33 /*===========================================================================*/
34 
35 /*===========================================================================*/
36 /* Module pre-compile time settings. */
37 /*===========================================================================*/
38 
39 /*===========================================================================*/
40 /* Derived constants and error checks. */
41 /*===========================================================================*/
42 
43 #if (CH_CFG_ST_TIMEDELTA < 0) || (CH_CFG_ST_TIMEDELTA == 1)
44 #error "invalid CH_CFG_ST_TIMEDELTA specified, must " \
45  "be zero or greater than one"
46 #endif
47 
48 #if (CH_CFG_ST_TIMEDELTA > 0) && (CH_CFG_TIME_QUANTUM > 0)
49 #error "CH_CFG_TIME_QUANTUM not supported in tickless mode"
50 #endif
51 
52 #if (CH_CFG_ST_TIMEDELTA > 0) && (CH_DBG_THREADS_PROFILING == TRUE)
53 #error "CH_DBG_THREADS_PROFILING not supported in tickless mode"
54 #endif
55 
56 /*===========================================================================*/
57 /* Module data structures and types. */
58 /*===========================================================================*/
59 
60 /*===========================================================================*/
61 /* Module macros. */
62 /*===========================================================================*/
63 
64 /*===========================================================================*/
65 /* External declarations. */
66 /*===========================================================================*/
67 
68 /*
69  * Virtual Timers APIs.
70  */
71 #ifdef __cplusplus
72 extern "C" {
73 #endif
74  void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
75  vtfunc_t vtfunc, void *par);
77  vtfunc_t vtfunc, void *par);
78  void chVTDoResetI(virtual_timer_t *vtp);
80  void chVTDoTickI(void);
81 #if CH_CFG_USE_TIMESTAMP == TRUE
83  void chVTResetTimeStampI(void);
84 #endif
85 #ifdef __cplusplus
86 }
87 #endif
88 
89 /*===========================================================================*/
90 /* Module inline functions. */
91 /*===========================================================================*/
92 
93 /**
94  * @brief Initializes a @p virtual_timer_t object.
95  * @note Initializing a timer object is not strictly required because
96  * the function @p chVTSetI() initializes the object too. This
97  * function is only useful if you need to perform a @p chVTIsArmed()
98  * check before calling @p chVTSetI().
99  *
100  * @param[out] vtp the @p virtual_timer_t structure pointer
101  *
102  * @init
103  */
104 static inline void chVTObjectInit(virtual_timer_t *vtp) {
105 
106  vtp->dlist.next = NULL;
107 }
108 
109 /**
110  * @brief Current system time.
111  * @details Returns the number of system ticks since the @p chSysInit()
112  * invocation.
113  * @note The counter can reach its maximum and then restart from zero.
114  * @note This function can be called from any context but its atomicity
115  * is not guaranteed on architectures whose word size is less than
116  * @p systime_t size.
117  *
118  * @return The system time in ticks.
119  *
120  * @xclass
121  */
122 static inline systime_t chVTGetSystemTimeX(void) {
123 
124 #if CH_CFG_ST_TIMEDELTA == 0
125  return currcore->vtlist.systime;
126 #else /* CH_CFG_ST_TIMEDELTA > 0 */
127  return port_timer_get_time();
128 #endif /* CH_CFG_ST_TIMEDELTA > 0 */
129 }
130 
131 /**
132  * @brief Current system time.
133  * @details Returns the number of system ticks since the @p chSysInit()
134  * invocation.
135  * @note The counter can reach its maximum and then restart from zero.
136  *
137  * @return The system time in ticks.
138  *
139  * @api
140  */
141 static inline systime_t chVTGetSystemTime(void) {
142  systime_t systime;
143 
144  chSysLock();
145  systime = chVTGetSystemTimeX();
146  chSysUnlock();
147 
148  return systime;
149 }
150 
151 /**
152  * @brief Returns the elapsed time since the specified start time.
153  *
154  * @param[in] start start time
155  * @return The elapsed time.
156  *
157  * @xclass
158  */
160 
161  return chTimeDiffX(start, chVTGetSystemTimeX());
162 }
163 
164 /**
165  * @brief Checks if the current system time is within the specified time
166  * window.
167  * @note When start==end then the function returns always false because the
168  * time window has zero size.
169  *
170  * @param[in] start the start of the time window (inclusive)
171  * @param[in] end the end of the time window (non inclusive)
172  * @retval true current time within the specified time window.
173  * @retval false current time not within the specified time window.
174  *
175  * @xclass
176  */
177 static inline bool chVTIsSystemTimeWithinX(systime_t start, systime_t end) {
178 
179  return chTimeIsInRangeX(chVTGetSystemTimeX(), start, end);
180 }
181 
182 /**
183  * @brief Checks if the current system time is within the specified time
184  * window.
185  * @note When start==end then the function returns always false because the
186  * time window has zero size.
187  *
188  * @param[in] start the start of the time window (inclusive)
189  * @param[in] end the end of the time window (non inclusive)
190  * @retval true current time within the specified time window.
191  * @retval false current time not within the specified time window.
192  *
193  * @api
194  */
195 static inline bool chVTIsSystemTimeWithin(systime_t start, systime_t end) {
196 
197  return chTimeIsInRangeX(chVTGetSystemTime(), start, end);
198 }
199 
200 /**
201  * @brief Returns the time interval until the next timer event.
202  * @note The return value is not perfectly accurate and can report values
203  * in excess of @p CH_CFG_ST_TIMEDELTA ticks.
204  * @note The interval returned by this function is only meaningful if
205  * more timers are not added to the list until the returned time.
206  *
207  * @param[out] timep pointer to a variable that will contain the time
208  * interval until the next timer elapses. This pointer
209  * can be @p NULL if the information is not required.
210  * @return The time, in ticks, until next time event.
211  * @retval false if the timers list is empty.
212  * @retval true if the timers list contains at least one timer.
213  *
214  * @iclass
215  */
216 static inline bool chVTGetTimersStateI(sysinterval_t *timep) {
217  virtual_timers_list_t *vtlp = &currcore->vtlist;
218  ch_delta_list_t *dlp = &vtlp->dlist;
219 
220  chDbgCheckClassI();
221 
222  if (dlp == dlp->next) {
223  return false;
224  }
225 
226  if (timep != NULL) {
227 #if CH_CFG_ST_TIMEDELTA == 0
228  *timep = dlp->next->delta;
229 #else
230  *timep = (dlp->next->delta + (sysinterval_t)CH_CFG_ST_TIMEDELTA) -
232 #endif
233  }
234 
235  return true;
236 }
237 
238 /**
239  * @brief Returns @p true if the specified timer is armed.
240  * @pre The timer must have been initialized using @p chVTObjectInit()
241  * or @p chVTDoSetI().
242  *
243  * @param[in] vtp the @p virtual_timer_t structure pointer
244  * @return true if the timer is armed.
245  *
246  * @iclass
247  */
248 static inline bool chVTIsArmedI(const virtual_timer_t *vtp) {
249 
250  chDbgCheckClassI();
251 
252  return (bool)(vtp->dlist.next != NULL);
253 }
254 
255 /**
256  * @brief Returns @p true if the specified timer is armed.
257  * @pre The timer must have been initialized using @p chVTObjectInit()
258  * or @p chVTDoSetI().
259  *
260  * @param[in] vtp the @p virtual_timer_t structure pointer
261  * @return true if the timer is armed.
262  *
263  * @api
264  */
265 static inline bool chVTIsArmed(const virtual_timer_t *vtp) {
266  bool b;
267 
268  chSysLock();
269  b = chVTIsArmedI(vtp);
270  chSysUnlock();
271 
272  return b;
273 }
274 
275 /**
276  * @brief Disables a Virtual Timer.
277  * @note The timer is first checked and disabled only if armed.
278  * @pre The timer must have been initialized using @p chVTObjectInit()
279  * or @p chVTDoSetI().
280  *
281  * @param[in] vtp the @p virtual_timer_t structure pointer
282  *
283  * @iclass
284  */
285 static inline void chVTResetI(virtual_timer_t *vtp) {
286 
287  if (chVTIsArmedI(vtp)) {
288  chVTDoResetI(vtp);
289  }
290 }
291 
292 /**
293  * @brief Disables a Virtual Timer.
294  * @note The timer is first checked and disabled only if armed.
295  * @pre The timer must have been initialized using @p chVTObjectInit()
296  * or @p chVTDoSetI().
297  *
298  * @param[in] vtp the @p virtual_timer_t structure pointer
299  *
300  * @api
301  */
302 static inline void chVTReset(virtual_timer_t *vtp) {
303 
304  chSysLock();
305  chVTResetI(vtp);
306  chSysUnlock();
307 }
308 
309 /**
310  * @brief Enables a one-shot virtual timer.
311  * @details If the virtual timer was already enabled then it is re-enabled
312  * using the new parameters.
313  * @pre The timer must have been initialized using @p chVTObjectInit()
314  * or @p chVTDoSetI().
315  *
316  * @param[in] vtp the @p virtual_timer_t structure pointer
317  * @param[in] delay the number of ticks before the operation timeouts, the
318  * special values are handled as follow:
319  * - @a TIME_INFINITE is allowed but interpreted as a
320  * normal time specification.
321  * - @a TIME_IMMEDIATE this value is not allowed.
322  * .
323  * @param[in] vtfunc the timer callback function. After invoking the
324  * callback the timer is disabled and the structure can
325  * be disposed or reused.
326  * @param[in] par a parameter that will be passed to the callback
327  * function
328  *
329  * @iclass
330  */
331 static inline void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay,
332  vtfunc_t vtfunc, void *par) {
333 
334  chVTResetI(vtp);
335  chVTDoSetI(vtp, delay, vtfunc, par);
336 }
337 
338 /**
339  * @brief Enables a one-shot virtual timer.
340  * @details If the virtual timer was already enabled then it is re-enabled
341  * using the new parameters.
342  * @pre The timer must have been initialized using @p chVTObjectInit()
343  * or @p chVTDoSetI().
344  *
345  * @param[in] vtp the @p virtual_timer_t structure pointer
346  * @param[in] delay the number of ticks before the operation timeouts, the
347  * special values are handled as follow:
348  * - @a TIME_INFINITE is allowed but interpreted as a
349  * normal time specification.
350  * - @a TIME_IMMEDIATE this value is not allowed.
351  * .
352  * @param[in] vtfunc the timer callback function. After invoking the
353  * callback the timer is disabled and the structure can
354  * be disposed or reused.
355  * @param[in] par a parameter that will be passed to the callback
356  * function
357  *
358  * @api
359  */
360 static inline void chVTSet(virtual_timer_t *vtp, sysinterval_t delay,
361  vtfunc_t vtfunc, void *par) {
362 
363  chSysLock();
364  chVTSetI(vtp, delay, vtfunc, par);
365  chSysUnlock();
366 }
367 
368 /**
369  * @brief Enables a continuous virtual timer.
370  * @details If the virtual timer was already enabled then it is re-enabled
371  * using the new parameters.
372  * @pre The timer must have been initialized using @p chVTObjectInit()
373  * or @p chVTDoSetI().
374  *
375  * @param[in] vtp the @p virtual_timer_t structure pointer
376  * @param[in] delay the number of ticks before the operation timeouts, the
377  * special values are handled as follow:
378  * - @a TIME_INFINITE is allowed but interpreted as a
379  * normal time specification.
380  * - @a TIME_IMMEDIATE this value is not allowed.
381  * .
382  * @param[in] vtfunc the timer callback function. After invoking the
383  * callback the timer is disabled and the structure can
384  * be disposed or reused.
385  * @param[in] par a parameter that will be passed to the callback
386  * function
387  *
388  * @iclass
389  */
390 static inline void chVTSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay,
391  vtfunc_t vtfunc, void *par) {
392 
393  chVTResetI(vtp);
394  chVTDoSetContinuousI(vtp, delay, vtfunc, par);
395 }
396 
397 /**
398  * @brief Enables a continuous virtual timer.
399  * @details If the virtual timer was already enabled then it is re-enabled
400  * using the new parameters.
401  * @pre The timer must have been initialized using @p chVTObjectInit()
402  * or @p chVTDoSetI().
403  *
404  * @param[in] vtp the @p virtual_timer_t structure pointer
405  * @param[in] delay the number of ticks before the operation timeouts, the
406  * special values are handled as follow:
407  * - @a TIME_INFINITE is allowed but interpreted as a
408  * normal time specification.
409  * - @a TIME_IMMEDIATE this value is not allowed.
410  * .
411  * @param[in] vtfunc the timer callback function. After invoking the
412  * callback the timer is disabled and the structure can
413  * be disposed or reused.
414  * @param[in] par a parameter that will be passed to the callback
415  * function
416  *
417  * @api
418  */
419 static inline void chVTSetContinuous(virtual_timer_t *vtp, sysinterval_t delay,
420  vtfunc_t vtfunc, void *par) {
421 
422  chSysLock();
423  chVTSetContinuousI(vtp, delay, vtfunc, par);
424  chSysUnlock();
425 }
426 
427 /**
428  * @brief Returns the current reload value.
429  *
430  * @param[in] vtp the @p virtual_timer_t structure pointer
431  * @return The reload value.
432  *
433  * @xclass
434  */
436 
437  return vtp->reload;
438 }
439 
440 /**
441  * @brief Changes a timer reload time interval.
442  * @note This function is meant to be called from a timer callback, it
443  * does nothing in any other context.
444  * @note Calling this function from a one-shot timer callback turns it
445  * into a continuous timer.
446  *
447  * @param[in] vtp the @p virtual_timer_t structure pointer
448  * @param[in] reload the new reload value, zero means no reload
449  *
450  * @xclass
451  */
452 static inline void chVTSetReloadIntervalX(virtual_timer_t *vtp,
453  sysinterval_t reload) {
454 
455  vtp->reload = reload;
456 }
457 
458 #if (CH_CFG_USE_TIMESTAMP == TRUE) || defined(__DOXYGEN__)
459 /**
460  * @brief Generates a monotonic time stamp.
461  * @details This function generates a monotonic time stamp synchronized with
462  * the system time. The time stamp has the same resolution of
463  * system time.
464  * @note There is an assumption, this function must be called at
465  * least once before the system time wraps back to zero or
466  * synchronization is lost. You may use a periodic virtual timer with
467  * a very large interval in order to keep time stamps synchronized
468  * by calling this function.
469  *
470  * @return The time stamp.
471  *
472  * @api
473  */
474 static inline systimestamp_t chVTGetTimeStamp(void) {
475  systimestamp_t stamp;
476 
477  chSysLock();
478 
479  stamp = chVTGetTimeStampI();
480 
481  chSysUnlock();
482 
483  return stamp;
484 }
485 
486 /**
487  * @brief Resets and re-synchronizes the time stamps monotonic counter.
488  *
489  * @api
490  */
491 static inline void chVTResetTimeStamp(void) {
492 
493  chDbgCheckClassI();
494 
495  chSysLock();
496 
498 
499  chSysUnlock();
500 }
501 #endif /* CH_CFG_USE_TIMESTAMP == TRUE */
502 
503 /**
504  * @brief Virtual Timers instance initialization.
505  * @note Internal use only.
506  *
507  * @param[out] vtlp pointer to the @p virtual_timers_list_t structure
508  *
509  * @notapi
510  */
511 static inline void __vt_object_init(virtual_timers_list_t *vtlp) {
512 
513  ch_dlist_init(&vtlp->dlist);
514 #if CH_CFG_ST_TIMEDELTA == 0
515  vtlp->systime = (systime_t)0;
516 #else /* CH_CFG_ST_TIMEDELTA > 0 */
517  vtlp->lasttime = (systime_t)0;
518 #endif /* CH_CFG_ST_TIMEDELTA > 0 */
519 #if CH_CFG_USE_TIMESTAMP == TRUE
521 #endif
522 }
523 
524 #endif /* CHVT_H */
525 
526 /** @} */
chVTSetI
static void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par)
Enables a one-shot virtual timer.
Definition: chvt.h:331
chVTDoTickI
void chVTDoTickI(void)
Virtual timers ticker.
Definition: chvt.c:377
chVTResetTimeStamp
static void chVTResetTimeStamp(void)
Resets and re-synchronizes the time stamps monotonic counter.
Definition: chvt.h:491
ch_virtual_timer::dlist
ch_delta_list_t dlist
Delta list element.
Definition: chobjects.h:79
chVTGetTimeStampI
systimestamp_t chVTGetTimeStampI(void)
Generates a monotonic time stamp.
Definition: chvt.c:562
chTimeDiffX
#define chTimeDiffX(start, end)
Subtracts two system times returning an interval.
Definition: nil/include/ch.h:1307
currcore
#define currcore
Access to current core's instance structure.
Definition: chsys.h:90
chVTGetSystemTimeX
static systime_t chVTGetSystemTimeX(void)
Current system time.
Definition: chvt.h:122
chVTIsArmedI
static bool chVTIsArmedI(const virtual_timer_t *vtp)
Returns true if the specified timer is armed.
Definition: chvt.h:248
chVTObjectInit
static void chVTObjectInit(virtual_timer_t *vtp)
Initializes a virtual_timer_t object.
Definition: chvt.h:104
systime_t
uint64_t systime_t
Type of system time.
Definition: chtime.h:107
vtfunc_t
void(* vtfunc_t)(virtual_timer_t *vtp, void *p)
Type of a Virtual Timer callback function.
Definition: chobjects.h:70
chVTResetTimeStampI
void chVTResetTimeStampI(void)
Resets and re-synchronizes the time stamps monotonic counter.
Definition: chvt.c:593
chVTGetTimeStamp
static systimestamp_t chVTGetTimeStamp(void)
Generates a monotonic time stamp.
Definition: chvt.h:474
chVTGetRemainingIntervalI
sysinterval_t chVTGetRemainingIntervalI(virtual_timer_t *vtp)
Returns the remaining time interval before next timer trigger.
Definition: chvt.c:337
systimestamp_t
uint64_t systimestamp_t
Type of a time stamp.
Definition: chtime.h:129
chVTGetTimersStateI
static bool chVTGetTimersStateI(sysinterval_t *timep)
Returns the time interval until the next timer event.
Definition: chvt.h:216
chVTIsSystemTimeWithin
static bool chVTIsSystemTimeWithin(systime_t start, systime_t end)
Checks if the current system time is within the specified time window.
Definition: chvt.h:195
chVTSetReloadIntervalX
static void chVTSetReloadIntervalX(virtual_timer_t *vtp, sysinterval_t reload)
Changes a timer reload time interval.
Definition: chvt.h:452
ch_virtual_timers_list::dlist
ch_delta_list_t dlist
Delta list header.
Definition: chobjects.h:104
ch_virtual_timers_list::systime
volatile systime_t systime
System Time counter.
Definition: chobjects.h:109
ch_delta_list::delta
sysinterval_t delta
Time interval from previous.
Definition: chlists.h:103
ch_delta_list::next
ch_delta_list_t * next
Next in the delta list.
Definition: chlists.h:101
chVTSet
static void chVTSet(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par)
Enables a one-shot virtual timer.
Definition: chvt.h:360
ch_virtual_timer::reload
sysinterval_t reload
Current reload interval.
Definition: chobjects.h:91
__vt_object_init
static void __vt_object_init(virtual_timers_list_t *vtlp)
Virtual Timers instance initialization.
Definition: chvt.h:511
chVTSetContinuousI
static void chVTSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par)
Enables a continuous virtual timer.
Definition: chvt.h:390
ch_virtual_timers_list::laststamp
volatile uint64_t laststamp
Last generated time stamp.
Definition: chobjects.h:121
chVTResetI
static void chVTResetI(virtual_timer_t *vtp)
Disables a Virtual Timer.
Definition: chvt.h:285
ch_virtual_timer
Structure representing a Virtual Timer.
Definition: chobjects.h:75
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
chVTDoResetI
void chVTDoResetI(virtual_timer_t *vtp)
Disables a Virtual Timer.
Definition: chvt.c:241
chVTGetReloadIntervalX
static sysinterval_t chVTGetReloadIntervalX(virtual_timer_t *vtp)
Returns the current reload value.
Definition: chvt.h:435
ch_virtual_timers_list::lasttime
systime_t lasttime
System time of the last tick event.
Definition: chobjects.h:115
ch_virtual_timers_list
Type of virtual timers list header.
Definition: chobjects.h:100
chVTIsSystemTimeWithinX
static bool chVTIsSystemTimeWithinX(systime_t start, systime_t end)
Checks if the current system time is within the specified time window.
Definition: chvt.h:177
chVTDoSetI
void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par)
Enables a one-shot virtual timer.
Definition: chvt.c:179
chVTTimeElapsedSinceX
static sysinterval_t chVTTimeElapsedSinceX(systime_t start)
Returns the elapsed time since the specified start time.
Definition: chvt.h:159
chVTSetContinuous
static void chVTSetContinuous(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par)
Enables a continuous virtual timer.
Definition: chvt.h:419
chVTGetSystemTime
static systime_t chVTGetSystemTime(void)
Current system time.
Definition: chvt.h:141
chVTDoSetContinuousI
void chVTDoSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par)
Enables a continuous virtual timer.
Definition: chvt.c:217
chVTReset
static void chVTReset(virtual_timer_t *vtp)
Disables a Virtual Timer.
Definition: chvt.h:302
chTimeIsInRangeX
bool chTimeIsInRangeX(systime_t time, systime_t start, systime_t end)
Checks if the specified time is within the specified time range.
Definition: ch.c:743
ch_delta_list
Delta list element and header structure.
Definition: chlists.h:100
chSysUnlock
#define chSysUnlock()
Leaves the kernel lock state.
Definition: nil/include/ch.h:1053
chVTIsArmed
static bool chVTIsArmed(const virtual_timer_t *vtp)
Returns true if the specified timer is armed.
Definition: chvt.h:265
ch_dlist_init
static void ch_dlist_init(ch_delta_list_t *dlhp)
Delta list initialization.
Definition: chlists.h:426
chSysLock
#define chSysLock()
Enters the kernel lock state.
Definition: nil/include/ch.h:1043