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