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