Virtual Timers are an unique ChibiOS/RT feature. It is a software system able to provide an “unlimited” number of one-shot timers with the same resolution of the system tick. Virtual timers are also used internally in order to implement the timeout feature present in many API functions.
Virtual timers are one-shot timers that can be started, stopped prematurely or trigger a callback after their programmed time is expired. The timers state machine is:
Timers callbacks are always invoked from ISR context, this means that the API that can be utilized from a timer callback is subject to the same restrictions applicable to ISRs. By re-arming a virtual timer from the callback it is possible to implement periodic or aperiodic timers as well.
Common RTOS kernels are triggered by a periodic interrupt, called system tick, driving the internal timings-relate mechanisms. In ChibiOS/RT the system tick is handled efficiently however it can still limits the system in several ways:
ChibiOS/RT implements a unique tickless mode in its virtual timers subsystem. When the tickless mode is activated the system timer is no more generating periodic interrupts but is programmed to generate an interrupt only when the system has some scheduled activity to execute, usually a virtual timer expiration. This approach has several positive aspects:
There are some things to consider:
The system can use both modes without impacts for applications so the mode can be changed without problems, in order to make comparisons for example.
virtual_timer_t | Type of a virtual timer object. |
chVTObjectInit() | Initializes a virtual timer object virtual_timer_t. |
chVTSet() | Starts or restarts a virtual timer. |
chVTSetI() | Starts or restarts a virtual timer (I-Class variant). |
chVTReset() | Stops, if active, a virtual timer. |
chVTResetI() | Stops, if active, a virtual timer (I-Class variant). |
chVTIsArmedI() | Returns true if the timer is armed. |
chVTDoSetI() | Starts a virtual timer, the timer must not be already armed. Slightly faster than chVTSetI() . |
chVTDoResetI() | Stops a virtual timer, the timer must be already armed. Slightly faster than chVTResetI() . |
A function blinks a LED one time for a fixed period, if called repeatedly the LED stays on.
static virtual_timer_t led_vt; /* * LED timer callback. */ static void led_cb(void *arg) { LED_off(); } /* * Monostable blinker function. */ void blink(void) { LED_on(); chVTSet(&led_vt, TIME_MS2I(500), led_cb, NULL); } /* * Application main function. */ void main(void) { /* * System initializations. * - Kernel initialization, the main() function becomes a thread and the * RTOS is active. Interrupts are enabled on chSysInit() exit. */ chSysInit(); /* LED timer initialization.*/ chVTObjectInit(&led_vt); /* Blinking the LED when the key is pressed.*/ while (true) { if (key_pressed()) blink(); chThdSleepMilliseconds(50); } }
A virtual timer is used a dedicated LED blinker. The blinker can be started and stopped with a single command.
static virtual_timer_t led_vt; /* * LED timer callback. */ static void led_cb(void *arg) { LED_toggle(); chSysLockFromISR(); chVTSetI(&led_vt, TIME_MS2I(500), led_cb, NULL); chSysUnlockFromISR(); } /* * Application main function. */ void main(void) { /* * System initializations. * - Kernel initialization, the main() function becomes a thread and the * RTOS is active. Interrupts are enabled on chSysInit() exit. */ chSysInit(); /* LED timer initialization.*/ chVTObjectInit(&led_vt); /* Starting blinker.*/ chVTSet(&led_vt, TIME_MS2I(500), led_cb, NULL); ...; /* Stopping blinker.*/ chVTReset(&led_vt); LED_off(); }