Table of Contents
Time, Intervals, Stamps and Virtual Timers
This article will provide information about how time is managed in ChibiOS (both RT and NIL), time is what an RTOS is about so it is important to understand some basic concept and terminology.
System Time
The system time is a monotonic counter increased at a fixed system tick rate CH_CFG_ST_FREQUENCY
. This counter can be 16 or 32 bits wide and it is meant to wrap back to zero when it reaches its maximum value, this is not a problem, the API is designed to cope with this. The type of System Time variables is systime_t
, do not assume a specific size for this type.
There are two possible implementations of system time that depend on the setting CH_CFG_ST_TIMEDELTA
:
Classic ticked mode
When CH_CFG_ST_TIMEDELTA
is set to zero then system time is implemented as a normal variable increased by a periodic interrupt: the System Tick. The maximum frequency is limited by the capability of the CPU to serve high frequency interrupts. Rates of 1000Hz are usually used for CH_CFG_ST_FREQUENCY
in this mode, higher frequencies, while still possible, are not recommended.
Tick-less mode
When CH_CFG_ST_TIMEDELTA
is greater than zero then the “tick-less” mode is activated. In this mode the system time is implemented using a physical counter increased by an HW clock. There are no practical limits for CH_CFG_ST_FREQUENCY
in this mode so very high resolutions are achievable, frequencies in the order of tens MHz are possible. Of course higher frequencies mean that the counter would wrap back to zero more often.
Time Intervals
Intervals are a measure of distance between 2 instants in time, the type of intervals is sysinterval_t
and it can be 16 or 32 bits wide. The difference of two system times is an interval and can be calculated using the function:
sysinterval_t chTimeDiffX(systime_t start, systime_t end)
Note that the type of intervals can be larger than the type of system time, because of this it is possible to use delays larger than what the system time would allow, all functions with delays take a sysinterval_t
as delay specification, for example:
chThdSleep(sysinterval_t delay)
It is possible to add an interval to a system time and obtain another system time using:
systime_t chTimeAddX(systime_t time, sysinterval_t delay)
Note that time overflows are possible if intervals are larger than system times, this condition is caught by an assertion.
Time Stamps
Time stamps are system time values extended to 64 bits, the type is systimestamp_t
. Stamps can be obtained using the function systimestamp_t chVTGetTimeStamp(void)
. Also for time stamps are available calculation functions:
systimestamp_t chTimeStampAddX(systimestamp_t stamp, sysinterval_t interval)
sysinterval_t chTimeStampDiffX(systimestamp_t start, systimestamp_t end)
bool chTimeStampIsInRangeX(systimestamp_t stamp, systimestamp_t start, systimestamp_t end)
Time stamps are only available in RT.
Virtual Timers
Virtual Timers are asynchronous timers implemented in SW on top of system time and intervals:
- Virtual Timers have the same resolution of system time
CH_CFG_ST_FREQUENCY
. - Virtual Timers are started and notify the reaching of their deadline using a callback called from ISR context.
- Virtual Timers can be started in one shot mode or in continuous mode.
- It is possible to stop a Virtual Timer before it reaches its deadline.
- Tick-less mode allows to have an high number of active timers with a very low number of IRQ generated, an IRQ is triggered only when a timer reaches its deadline, if more timers reach their deadline in a very narrow time window then just a single IRQ is generated for all of them.
VTs in tick-less mode
Virtual Timers have the same resolution of the system time which can be very high, however serving timers in SW takes time and the system time is advancing while callbacks are being invoked, this makes the handling very complex and can add some inaccuracy.
This inaccuracy, in number of ticks, is expressed by the parameter CH_CFG_ST_TIMEDELTA
. The deadline of a timer can be delayed of up CH_CFG_ST_TIMEDELTA
ticks, because of this is very important to:
- Keep
CH_CFG_ST_TIMEDELTA
as low as possible, minimum is 2. - Keep
CH_CFG_ST_TIMEDELTA
high enough for the OS to be able to process timers, this is dependent on a variety of factors:- CPU frequency.
- Time spent in timer callbacks.
- Time spent in ISRs at priority higher that the system timer ISR.
- Compiler optimizations.
The optimal value has to be experimentally searched. A value too low results in an assertion in the timers subsystem so it is easily detected, if assertions are disabled then an event is collected in RFCU (Runtime Faults Collection Unit) and can be detected at runtime.
For reference a system tick at 10kHz requires a CH_CFG_ST_TIMEDELTA
at 2 under any condition, a system tick at 20MHz can have a CH_CFG_ST_TIMEDELTA
at 15 on an STM32G474 running at 170MHz. Values have been tested using our “VT-Storm” stress test application.
Basically CH_CFG_ST_TIMEDELTA
represent the intrinsic jitter of the Virtual Timers subsystem, it is not a negative thing, it is a clear assessment of worst case realtime conditions for VTs.
Virtual Timers are only available in RT.