ChibiOS/RT  6.1.4
chvt.c
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/src/chvt.c
22  * @brief Time and Virtual Timers module code.
23  *
24  * @addtogroup time
25  * @details Time and Virtual Timers related APIs and services.
26  * @{
27  */
28 
29 #include "ch.h"
30 
31 /*===========================================================================*/
32 /* Module local definitions. */
33 /*===========================================================================*/
34 
35 /*===========================================================================*/
36 /* Module exported variables. */
37 /*===========================================================================*/
38 
39 /*===========================================================================*/
40 /* Module local types. */
41 /*===========================================================================*/
42 
43 /*===========================================================================*/
44 /* Module local variables. */
45 /*===========================================================================*/
46 
47 /*===========================================================================*/
48 /* Module local functions. */
49 /*===========================================================================*/
50 
51 /**
52  * @brief Delta list initialization.
53  *
54  * @param[out] dlhp pointer to the delta list header
55  *
56  * @notapi
57  */
58 static inline void vt_init(delta_list_t *dlhp) {
59 
60  dlhp->next = dlhp;
61  dlhp->prev = dlhp;
62  dlhp->delta = (sysinterval_t)-1;
63 }
64 
65 /**
66  * @brief List empty check.
67  *
68  * @param[in] dlhp pointer to the delta list header
69  *
70  * @notapi
71  */
72 static inline bool vt_is_empty(delta_list_t *dlhp) {
73 
74  return (bool)(dlhp == dlhp->next);
75 }
76 
77 /**
78  * @brief Last timer in the list check.
79  *
80  * @param[in] dlhp pointer to the delta list header
81  * @param[in] dlp pointer to the delta list element
82  *
83  * @notapi
84  */
85 static inline bool vt_is_last(delta_list_t *dlhp, delta_list_t *dlp) {
86 
87  return (bool)(dlp->next == dlhp);
88 }
89 
90 /**
91  * @brief Fist timer in the list check.
92  *
93  * @param[in] dlhp pointer to the delta list header
94  * @param[in] dlp pointer to the delta list element
95  *
96  * @notapi
97  */
98 static inline bool vt_is_first(delta_list_t *dlhp, delta_list_t *dlp) {
99 
100  return (bool)(dlhp->next == dlp);
101 }
102 
103 /**
104  * @brief Timer check.
105  *
106  * @param[in] dlhp pointer to the delta list header
107  * @param[in] dlp pointer to the delta list element
108  *
109  * @notapi
110  */
111 static inline bool vt_is_timer(delta_list_t *dlhp, delta_list_t *dlp) {
112 
113  return (bool)(dlp != dlhp);
114 }
115 
116 /**
117  * @brief Inserts an element after another header element.
118  *
119  * @param[in] dlhp pointer to the delta list header element
120  * @param[in] dlp element to be inserted after the header element
121  * @param[in] delta delta of the element to be inserted
122  *
123  * @notapi
124  */
125 static inline void vt_insert_after(delta_list_t *dlhp,
126  delta_list_t *dlp,
127  sysinterval_t delta) {
128 
129  dlp->delta = delta;
130  dlp->prev = dlhp;
131  dlp->next = dlp->prev->next;
132  dlp->next->prev = dlp;
133  dlhp->next = dlp;
134 }
135 
136 /**
137  * @brief Inserts an element before another header element.
138  *
139  * @param[in] dlhp pointer to the delta list header element
140  * @param[in] dlp element to be inserted before the header element
141  * @param[in] delta delta of the element to be inserted
142  *
143  * @notapi
144  */
145 static inline void vt_insert_before(delta_list_t *dlhp,
146  delta_list_t *dlp,
147  sysinterval_t delta) {
148 
149  dlp->delta = delta;
150  dlp->next = dlhp;
151  dlp->prev = dlp->next->prev;
152  dlp->prev->next = dlp;
153  dlhp->prev = dlp;
154 }
155 
156 /**
157  * @brief Inserts an element in a delta list.
158  *
159  * @param[in] dlhp pointer to the delta list header element
160  * @param[in] dlep element to be inserted before the header element
161  * @param[in] delta delta of the element to be inserted
162  *
163  * @notapi
164  */
165 static inline void vt_insert(delta_list_t *dlhp,
166  delta_list_t *dlep,
167  sysinterval_t delta) {
168  delta_list_t *dlp;
169 
170  /* The delta list is scanned in order to find the correct position for
171  this element. */
172  dlp = dlhp->next;
173  while (dlp->delta < delta) {
174  /* Debug assert if the element is already in the list.*/
175  chDbgAssert(dlp != dlep, "element already in list");
176 
177  delta -= dlp->delta;
178  dlp = dlp->next;
179  }
180 
181  /* The timer is inserted in the delta list.*/
182  vt_insert_before(dlp, dlep, delta);
183 
184  /* Adjusting delta for the following element.*/
185  dlp->delta -= delta;
186 
187  /* Special case when the inserted element is in last position in the list,
188  the value in the header must be restored, just doing it is faster than
189  checking then doing.*/
190  dlhp->delta = (sysinterval_t)-1;
191 }
192 
193 /**
194  * @brief Dequeues an element from the delta list.
195  *
196  * @param[in] dlhp pointer to the delta list header
197  *
198  * @notapi
199  */
201  delta_list_t *dlp = dlhp->next;
202 
203  dlhp->next = dlp->next;
204  dlhp->next->prev = dlhp;
205 
206  return dlp;
207 }
208 
209 /**
210  * @brief Dequeues an element from the delta list.
211  *
212  * @param[in] dlp pointer to the delta list element
213  *
214  * @notapi
215  */
216 static inline delta_list_t *vt_dequeue(delta_list_t *dlp) {
217 
218  dlp->prev->next = dlp->next;
219  dlp->next->prev = dlp->prev;
220 
221  return dlp;
222 }
223 
224 #if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
225 /**
226  * @brief Alarm time setup.
227  * @note An RFCU fault is registered if the system time skips past
228  * <tt>(now + delay)</tt>, the deadline is skipped forward
229  * in order to compensate for the event.
230  *
231  * @param[in] now last known system time
232  * @param[in] delay delay over @p now
233  */
234 static void vt_set_alarm(systime_t now, sysinterval_t delay) {
235  sysinterval_t currdelta;
236 
237  /* Initial delta is what is configured statically.*/
238  currdelta = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
239 
240  if (delay < currdelta) {
241  /* We need to avoid that the system time goes past the alarm we are
242  going to set before the alarm is actually set.*/
243  delay = currdelta;
244  }
245 #if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
246  else if (delay > (sysinterval_t)TIME_MAX_SYSTIME) {
247  /* The delta could be too large for the physical timer to handle
248  this can happen when: sizeof (systime_t) < sizeof (sysinterval_t).*/
250  }
251 #endif
252 
253  /* Deadline skip detection and correction loop.*/
254  while (true) {
255  sysinterval_t nowdelta;
256  systime_t newnow;
257 
258  /* Setting up the alarm on the next deadline.*/
259  port_timer_set_alarm(chTimeAddX(now, delay));
260 
261  /* Check on current time, we need to detect the error condition where
262  current time skipped past the calculated deadline.
263  Note that the "<" condition is intentional, we want to make sure
264  that the alarm is set before the deadline is reached because the
265  comparison could happen on the transition depending on the timer
266  architecture.*/
267  newnow = chVTGetSystemTimeX();
268  nowdelta = chTimeDiffX(now, newnow);
269  if (nowdelta < delay) {
270  break;
271  }
272 
273  /* Trying again with a more relaxed minimum delta.*/
274  currdelta += (sysinterval_t)1;
275 
276  /* Current time becomes the new "base" time.*/
277  now = newnow;
278  delay = currdelta;
279  }
280 
281  chDbgAssert(currdelta <= CH_CFG_ST_TIMEDELTA, "insufficient delta");
282 }
283 
284 /**
285  * @brief Inserts a timer as first element in a delta list.
286  * @note This is the special case when the delta list is initially empty.
287  */
289  virtual_timer_t *vtp,
290  systime_t now,
291  sysinterval_t delay) {
292  sysinterval_t currdelta;
293 
294  /* The delta list is empty, the current time becomes the new
295  delta list base time, the timer is inserted.*/
296  vtlp->lasttime = now;
297  vt_insert_after(&vtlp->dlist, &vtp->dlist, delay);
298 
299  /* Initial delta is what is configured statically.*/
300  currdelta = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
301 
302  /* If the requested delay is lower than the minimum safe delta then it
303  is raised to the minimum safe value.*/
304  if (delay < currdelta) {
305  /* We need to avoid that the system time goes past the alarm we are
306  going to set before the alarm is actually set.*/
307  delay = currdelta;
308  }
309 #if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
310  else if (delay > (sysinterval_t)TIME_MAX_SYSTIME) {
311  /* The delta could be too large for the physical timer to handle
312  this can happen when: sizeof (systime_t) < sizeof (sysinterval_t).*/
314  }
315 #endif
316 
317  /* Being the first element inserted in the list the alarm timer
318  is started.*/
319  port_timer_start_alarm(chTimeAddX(vtlp->lasttime, delay));
320 
321  /* Deadline skip detection and correction loop.*/
322  while (true) {
323  systime_t newnow;
324 
325  /* Check on current time, we need to detect the error condition where
326  current time skipped past the calculated deadline.
327  Note that the "<" condition is intentional, we want to make sure
328  that the alarm is set before the deadline is reached because the
329  comparison could happen on the transition depending on the timer
330  architecture.*/
331  newnow = chVTGetSystemTimeX();
332  if (chTimeDiffX(now, newnow) < delay) {
333  break;
334  }
335 
336  /* Trying again with a more relaxed minimum delta.*/
337  currdelta += (sysinterval_t)1;
338 
339  /* Setting up the alarm on the next deadline.*/
340  port_timer_set_alarm(chTimeAddX(now, currdelta));
341  }
342 
343  chDbgAssert(currdelta <= CH_CFG_ST_TIMEDELTA, "insufficient delta");
344 }
345 #endif /* CH_CFG_ST_TIMEDELTA > 0 */
346 
347 /**
348  * @brief Enqueues a virtual timer in a virtual timers list.
349  */
351  virtual_timer_t *vtp,
352  sysinterval_t delay) {
353  sysinterval_t delta;
354 
355 #if CH_CFG_ST_TIMEDELTA > 0
356  {
357  sysinterval_t nowdelta;
359 
360  /* Special case where the timers list is empty.*/
361  if (vt_is_empty(&vtlp->dlist)) {
362 
363  vt_insert_first(vtlp, vtp, now, delay);
364 
365  return;
366  }
367 
368  /* Delay as delta from 'lasttime'. Note, it can overflow and the value
369  becomes lower than 'deltanow'.*/
370  nowdelta = chTimeDiffX(vtlp->lasttime, now);
371  delta = nowdelta + delay;
372 
373  /* Scenario where a very large delay exceeded the numeric range, the
374  delta is shortened to make it fit the numeric range, the timer
375  will be triggered "deltanow" cycles earlier.*/
376  if (delta < nowdelta) {
377  delta = delay;
378  }
379 
380  /* Checking if this timer would become the first in the delta list, this
381  requires changing the current alarm setting.*/
382  if (delta < vtlp->dlist.next->delta) {
383 
384  vt_set_alarm(now, delay);
385  }
386  }
387 #else /* CH_CFG_ST_TIMEDELTA == 0 */
388 
389  /* Delta is initially equal to the specified delay.*/
390  delta = delay;
391 #endif /* CH_CFG_ST_TIMEDELTA == 0 */
392 
393  vt_insert(&vtlp->dlist, &vtp->dlist, delta);
394 }
395 
396 /*===========================================================================*/
397 /* Module exported functions. */
398 /*===========================================================================*/
399 
400 /**
401  * @brief Virtual Timers initialization.
402  * @note Internal use only.
403  *
404  * @notapi
405  */
406 void _vt_init(void) {
407 
409 #if CH_CFG_ST_TIMEDELTA == 0
410  ch.vtlist.systime = (systime_t)0;
411 #else /* CH_CFG_ST_TIMEDELTA > 0 */
413 #endif /* CH_CFG_ST_TIMEDELTA > 0 */
414 }
415 
416 /**
417  * @brief Enables a one-shot virtual timer.
418  * @details The timer is enabled and programmed to trigger after the delay
419  * specified as parameter.
420  * @pre The timer must not be already armed before calling this function.
421  * @note The callback function is invoked from interrupt context.
422  *
423  * @param[out] vtp the @p virtual_timer_t structure pointer
424  * @param[in] delay the number of ticks before the operation timeouts, the
425  * special values are handled as follow:
426  * - @a TIME_INFINITE is allowed but interpreted as a
427  * normal time specification.
428  * - @a TIME_IMMEDIATE this value is not allowed.
429  * .
430  * @param[in] vtfunc the timer callback function. After invoking the
431  * callback the timer is disabled and the structure can
432  * be disposed or reused.
433  * @param[in] par a parameter that will be passed to the callback
434  * function
435  *
436  * @iclass
437  */
439  vtfunc_t vtfunc, void *par) {
441 
443  chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
444 
445  /* Timer initialization.*/
446  vtp->par = par;
447  vtp->func = vtfunc;
448 
449  /* Inserting the timer in the delta list.*/
450  vt_enqueue(vtlp, vtp, delay);
451 }
452 
453 /**
454  * @brief Disables a Virtual Timer.
455  * @pre The timer must be in armed state before calling this function.
456  *
457  * @param[in] vtp the @p virtual_timer_t structure pointer
458  *
459  * @iclass
460  */
463 
465  chDbgCheck(vtp != NULL);
466  chDbgAssert(chVTIsArmedI(vtp), "timer not armed");
467 
468 #if CH_CFG_ST_TIMEDELTA == 0
469 
470  /* The delta of the timer is added to the next timer.*/
471  vtp->dlist.next->delta += vtp->dlist.delta;
472 
473  /* Removing the element from the delta list, marking it as not armed.*/
474  (void) vt_dequeue(&vtp->dlist);
475  vtp->func = NULL;
476 
477  /* The above code changes the value in the header when the removed element
478  is the last of the list, restoring it.*/
479  vtlp->dlist.delta = (sysinterval_t)-1;
480 #else /* CH_CFG_ST_TIMEDELTA > 0 */
481  systime_t now;
482  sysinterval_t nowdelta, delta;
483 
484  /* If the timer is not the first of the list then it is simply unlinked
485  else the operation is more complex.*/
486  if (!vt_is_first(&vtlp->dlist, &vtp->dlist)) {
487 
488  /* Removing the element from the delta list and marking it as not armed.*/
489  (void) vt_dequeue(&vtp->dlist);
490  vtp->func = NULL;
491 
492  /* Adding delta to the next element, if it is not the last one.*/
493  vtp->dlist.next->delta += vtp->dlist.delta;
494 
495  /* Special case when the removed element from the last position in the list,
496  the value in the header must be restored, just doing it is faster than
497  checking then doing.*/
498  vtlp->dlist.delta = (sysinterval_t)-1;
499 
500  return;
501  }
502 
503  /* Removing the first timer from the list, marking it as not armed.*/
504  vt_remove_first(&vtlp->dlist);
505  vtp->func = NULL;
506 
507  /* If the list become empty then the alarm timer is stopped and done.*/
508  if (vt_is_empty(&vtlp->dlist)) {
509  port_timer_stop_alarm();
510 
511  return;
512  }
513 
514  /* The delta of the removed timer is added to the new first timer.*/
515  vtlp->dlist.next->delta += vtp->dlist.delta;
516 
517  /* Distance in ticks between the last alarm event and current time.*/
518  now = chVTGetSystemTimeX();
519  nowdelta = chTimeDiffX(vtlp->lasttime, now);
520 
521  /* If the current time surpassed the time of the next element in list
522  then the event interrupt is already pending, just return.*/
523  if (nowdelta >= vtlp->dlist.next->delta) {
524  return;
525  }
526 
527  /* Distance from the next scheduled event and now.*/
528  delta = vtlp->dlist.next->delta - nowdelta;
529 
530  /* Setting up the alarm.*/
531  vt_set_alarm(now, delta);
532 #endif /* CH_CFG_ST_TIMEDELTA > 0 */
533 }
534 
535 /**
536  * @brief Returns the remaining time interval before next timer trigger.
537  * @note This function can be called while the timer is active.
538  *
539  * @param[in] vtp the @p virtual_timer_t structure pointer
540  * @return The remaining time interval.
541  *
542  * @iclass
543  */
546  sysinterval_t delta;
547  delta_list_t *dlp;
548 
550 
551  delta = (sysinterval_t)0;
552  dlp = vtlp->dlist.next;
553  do {
554  delta += dlp->delta;
555  if (dlp == &vtp->dlist) {
556 #if CH_CFG_ST_TIMEDELTA > 0
558  sysinterval_t nowdelta = chTimeDiffX(vtlp->lasttime, now);
559  if (nowdelta > delta) {
560  return (sysinterval_t)0;
561  }
562  return delta - nowdelta;
563 #else
564  return delta;
565 #endif
566  }
567  dlp = dlp->next;
568  } while (dlp != &vtlp->dlist);
569 
570  chDbgAssert(false, "timer not in list");
571 
572  return (sysinterval_t)-1;
573 }
574 
575 /**
576  * @brief Virtual timers ticker.
577  * @note The system lock is released before entering the callback and
578  * re-acquired immediately after. It is callback's responsibility
579  * to acquire the lock if needed. This is done in order to reduce
580  * interrupts jitter when many timers are in use.
581  *
582  * @iclass
583  */
584 void chVTDoTickI(void) {
586 
588 
589 #if CH_CFG_ST_TIMEDELTA == 0
590  vtlp->systime++;
591  if (!vt_is_empty(&vtlp->dlist)) {
592  /* The list is not empty, processing elements on top.*/
593  --vtlp->dlist.next->delta;
594  while (vtlp->dlist.next->delta == (sysinterval_t)0) {
595  virtual_timer_t *vtp;
596  vtfunc_t fn;
597 
598  /* Triggered timer.*/
599  vtp = (virtual_timer_t *)vtlp->dlist.next;
600 
601  /* Removing the element from the delta list, marking it as not armed.*/
602  (void) vt_dequeue(&vtp->dlist);
603  fn = vtp->func;
604  vtp->func = NULL;
605 
606  /* The callback is invoked outside the kernel critical section, it
607  is re-entered on the callback return.*/
609  fn(vtp->par);
611  }
612  }
613 #else /* CH_CFG_ST_TIMEDELTA > 0 */
614  virtual_timer_t *vtp;
615  sysinterval_t delta, nowdelta;
616  systime_t now;
617 
618  /* Looping through timers consuming all timers with deltas lower or equal
619  than the interval between "now" and "lasttime".*/
620  while (true) {
621  vtfunc_t fn;
622 
623  /* First timer in the delta list.*/
624  vtp = (virtual_timer_t *)vtlp->dlist.next;
625 
626  /* Delta between current time and last execution time.*/
627  now = chVTGetSystemTimeX();
628  nowdelta = chTimeDiffX(vtlp->lasttime, now);
629 
630  /* Loop break condition.
631  Note that the list scan is limited by the delta list header having
632  "vtlp->dlist.delta == (sysinterval_t)-1" which is greater than all
633  deltas*/
634  if (nowdelta < vtp->dlist.delta) {
635  break;
636  }
637 
638  /* Last time deadline is updated to the next timer's time.*/
639  vtlp->lasttime = chTimeAddX(vtlp->lasttime, vtp->dlist.delta);
640 
641  /* Removing the timer from the list.*/
642  (void) vt_dequeue(&vtp->dlist);
643 
644  /* Marking the timer as not armed.*/
645  fn = vtp->func;
646  vtp->func = NULL;
647 
648  /* If the list becomes empty then the alarm is disabled.*/
649  if (vt_is_empty(&vtlp->dlist)) {
650  port_timer_stop_alarm();
651  }
652 
653  /* The callback is invoked outside the kernel critical section, it
654  is re-entered on the callback return. Note that "lasttime" can be
655  modified within the callback if some timer function is called.*/
657  fn(vtp->par);
659  }
660 
661  /* If the list is empty, nothing else to do.*/
662  if (vt_is_empty(&vtlp->dlist)) {
663  return;
664  }
665 
666  /* Calculating the delta to the next alarm time.*/
667  delta = vtp->dlist.delta - nowdelta;
668 
669  /* Update alarm time to next timer.*/
670  vt_set_alarm(now, delta);
671 #endif /* CH_CFG_ST_TIMEDELTA > 0 */
672 }
673 
674 /** @} */
chVTDoTickI
void chVTDoTickI(void)
Virtual timers ticker.
Definition: chvt.c:584
vt_remove_first
static delta_list_t * vt_remove_first(delta_list_t *dlhp)
Dequeues an element from the delta list.
Definition: chvt.c:200
chVTGetSystemTimeX
static systime_t chVTGetSystemTimeX(void)
Current system time.
Definition: chvt.h:116
vt_dequeue
static delta_list_t * vt_dequeue(delta_list_t *dlp)
Dequeues an element from the delta list.
Definition: chvt.c:216
chVTIsArmedI
static bool chVTIsArmedI(const virtual_timer_t *vtp)
Returns true if the specified timer is armed.
Definition: chvt.h:242
vt_insert_after
static void vt_insert_after(delta_list_t *dlhp, delta_list_t *dlp, sysinterval_t delta)
Inserts an element after another header element.
Definition: chvt.c:125
systime_t
uint64_t systime_t
Type of system time.
Definition: chtime.h:107
vt_insert
static void vt_insert(delta_list_t *dlhp, delta_list_t *dlep, sysinterval_t delta)
Inserts an element in a delta list.
Definition: chvt.c:165
chDbgAssert
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
vt_set_alarm
static void vt_set_alarm(systime_t now, sysinterval_t delay)
Alarm time setup.
Definition: chvt.c:234
ch_system::vtlist
virtual_timers_list_t vtlist
Virtual timers delta list header.
Definition: chschd.h:422
ch_virtual_timer::dlist
delta_list_t dlist
Delta list element.
Definition: chschd.h:322
chTimeDiffX
static sysinterval_t chTimeDiffX(systime_t start, systime_t end)
Subtracts two system times returning an interval.
Definition: chtime.h:459
chVTGetRemainingIntervalI
sysinterval_t chVTGetRemainingIntervalI(virtual_timer_t *vtp)
Returns the remaining time interval before next timer trigger.
Definition: chvt.c:544
vt_is_last
static bool vt_is_last(delta_list_t *dlhp, delta_list_t *dlp)
Last timer in the list check.
Definition: chvt.c:85
ch_virtual_timer::func
vtfunc_t func
Timer callback function pointer.
Definition: chschd.h:323
chDbgCheck
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:101
TIME_IMMEDIATE
#define TIME_IMMEDIATE
Zero interval specification for some functions with a timeout specification.
Definition: chtime.h:47
chTimeAddX
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
_vt_init
void _vt_init(void)
Virtual Timers initialization.
Definition: chvt.c:406
ch_virtual_timers_list::systime
volatile systime_t systime
System Time counter.
Definition: chschd.h:338
ch_delta_list::delta
sysinterval_t delta
Time delta before timeout.
Definition: chschd.h:315
ch_delta_list::prev
delta_list_t * prev
Previous timer in the list.
Definition: chschd.h:314
vt_init
static void vt_init(delta_list_t *dlhp)
Delta list initialization.
Definition: chvt.c:58
chSysLockFromISR
static void chSysLockFromISR(void)
Enters the kernel lock state from within an interrupt handler.
Definition: chsys.h:395
ch_virtual_timers_list::dlist
delta_list_t dlist
Delta list header.
Definition: chschd.h:336
vt_enqueue
static void vt_enqueue(virtual_timers_list_t *vtlp, virtual_timer_t *vtp, sysinterval_t delay)
Enqueues a virtual timer in a virtual timers list.
Definition: chvt.c:350
chDbgCheckClassI
void chDbgCheckClassI(void)
I-class functions context check.
Definition: chdebug.c:233
ch_virtual_timer
Structure representing a Virtual Timer.
Definition: chschd.h:321
ch
ch_system_t ch
System data structures.
Definition: chschd.c:42
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
TIME_MAX_SYSTIME
#define TIME_MAX_SYSTIME
Maximum system of system time before it wraps.
Definition: chtime.h:65
chVTDoResetI
void chVTDoResetI(virtual_timer_t *vtp)
Disables a Virtual Timer.
Definition: chvt.c:461
ch_virtual_timers_list::lasttime
systime_t lasttime
System time of the last tick event.
Definition: chschd.h:344
ch_virtual_timers_list
Structure representing a virtual timers list header.
Definition: chschd.h:335
ch.h
ChibiOS/RT main include file.
vt_insert_first
static void vt_insert_first(virtual_timers_list_t *vtlp, virtual_timer_t *vtp, systime_t now, sysinterval_t delay)
Inserts a timer as first element in a delta list.
Definition: chvt.c:288
chVTDoSetI
void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par)
Enables a one-shot virtual timer.
Definition: chvt.c:438
vt_is_timer
static bool vt_is_timer(delta_list_t *dlhp, delta_list_t *dlp)
Timer check.
Definition: chvt.c:111
vt_insert_before
static void vt_insert_before(delta_list_t *dlhp, delta_list_t *dlp, sysinterval_t delta)
Inserts an element before another header element.
Definition: chvt.c:145
vtfunc_t
void(* vtfunc_t)(void *p)
Type of a Virtual Timer callback function.
Definition: chsystypes.h:81
CH_CFG_ST_TIMEDELTA
#define CH_CFG_ST_TIMEDELTA
Time delta constant for the tick-less mode.
Definition: chconf.h:83
vt_is_empty
static bool vt_is_empty(delta_list_t *dlhp)
List empty check.
Definition: chvt.c:72
ch_virtual_timer::par
void * par
Timer callback function parameter.
Definition: chschd.h:325
ch_delta_list::next
delta_list_t * next
Next timer in the list.
Definition: chschd.h:313
vt_is_first
static bool vt_is_first(delta_list_t *dlhp, delta_list_t *dlp)
Fist timer in the list check.
Definition: chvt.c:98
ch_delta_list
Virtual Timer delta list element and header structure.
Definition: chschd.h:312
chSysUnlockFromISR
static void chSysUnlockFromISR(void)
Leaves the kernel lock state from within an interrupt handler.
Definition: chsys.h:415