1.. _timeutil_api: 2 3Time Utilities 4############## 5 6Overview 7******** 8 9:ref:`kernel_timing_uptime` in Zephyr is based on the a tick counter. With 10the default :kconfig:option:`CONFIG_TICKLESS_KERNEL` this counter advances at a 11nominally constant rate from zero at the instant the system started. The POSIX 12equivalent to this counter is something like ``CLOCK_MONOTONIC`` or, in Linux, 13``CLOCK_MONOTONIC_RAW``. :c:func:`k_uptime_get()` provides a millisecond 14representation of this time. 15 16Applications often need to correlate the Zephyr internal time with external 17time scales used in daily life, such as local time or Coordinated Universal 18Time. These systems interpret time in different ways and may have 19discontinuities due to `leap seconds <https://what-if.xkcd.com/26/>`__ and 20local time offsets like daylight saving time. 21 22Because of these discontinuities, as well as significant inaccuracies in the 23clocks underlying the cycle counter, the offset between time estimated from 24the Zephyr clock and the actual time in a "real" civil time scale is not 25constant and can vary widely over the runtime of a Zephyr application. 26 27The time utilities API supports: 28 29* :ref:`converting between time representations <timeutil_repr>` 30* :ref:`synchronizing and aligning time scales <timeutil_sync>` 31 32For terminology and concepts that support these functions see 33:ref:`timeutil_concepts`. 34 35Time Utility APIs 36***************** 37 38.. _timeutil_repr: 39 40Representation Transformation 41============================= 42 43Time scale instants can be represented in multiple ways including: 44 45* Seconds since an epoch. POSIX representations of time in this form include 46 ``time_t`` and ``struct timespec``, which are generally interpreted as a 47 representation of `"UNIX Time" 48 <https://tools.ietf.org/html/rfc8536#section-2>`__. 49 50* Calendar time as a year, month, day, hour, minutes, and seconds relative to 51 an epoch. POSIX representations of time in this form include ``struct tm``. 52 53Keep in mind that these are simply time representations that must be 54interpreted relative to a time scale which may be local time, UTC, or some 55other continuous or discontinuous scale. 56 57Some necessary transformations are available in standard C library 58routines. For example, ``time_t`` measuring seconds since the POSIX EPOCH is 59converted to ``struct tm`` representing calendar time with `gmtime() 60<https://pubs.opengroup.org/onlinepubs/9699919799/functions/gmtime.html>`__. 61Sub-second timestamps like ``struct timespec`` can also use this to produce 62the calendar time representation and deal with sub-second offsets separately. 63 64The inverse transformation is not standardized: APIs like ``mktime()`` expect 65information about time zones. Zephyr provides this transformation with 66:c:func:`timeutil_timegm` and :c:func:`timeutil_timegm64`. 67 68.. doxygengroup:: timeutil_repr_apis 69 70.. _timeutil_sync: 71 72Time Scale Synchronization 73========================== 74 75There are several factors that affect synchronizing time scales: 76 77* The rate of discrete instant representation change. For example Zephyr 78 uptime is tracked in ticks which advance at events that nominally occur at 79 :kconfig:option:`CONFIG_SYS_CLOCK_TICKS_PER_SEC` Hertz, while an external time 80 source may provide data in whole or fractional seconds (e.g. microseconds). 81* The absolute offset required to align the two scales at a single instant. 82* The relative error between observable instants in each scale, required to 83 align multiple instants consistently. For example a reference clock that's 84 conditioned by a 1-pulse-per-second GPS signal will be much more accurate 85 than a Zephyr system clock driven by a RC oscillator with a +/- 250 ppm 86 error. 87 88Synchronization or alignment between time scales is done with a multi-step 89process: 90 91* An instant in a time scale is represented by an (unsigned) 64-bit integer, 92 assumed to advance at a fixed nominal rate. 93* :c:struct:`timeutil_sync_config` records the nominal rates of a reference 94 time scale/source (e.g. TAI) and a local time source 95 (e.g. :c:func:`k_uptime_ticks`). 96* :c:struct:`timeutil_sync_instant` records the representation of a single 97 instant in both the reference and local time scales. 98* :c:struct:`timeutil_sync_state` provides storage for an initial instant, a 99 recently received second observation, and a skew that can adjust for 100 relative errors in the actual rate of each time scale. 101* :c:func:`timeutil_sync_ref_from_local()` and 102 :c:func:`timeutil_sync_local_from_ref()` convert instants in one time scale 103 to another taking into account skew that can be estimated from the two 104 instances stored in the state structure by 105 :c:func:`timeutil_sync_estimate_skew`. 106 107.. doxygengroup:: timeutil_sync_apis 108 109.. _timeutil_concepts: 110 111Concepts Underlying Time Support in Zephyr 112****************************************** 113 114Terms from `ISO/TC 154/WG 5 N0038 115<https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf>`__ 116(ISO/WD 8601-1) and elsewhere: 117 118* A *time axis* is a representation of time as an ordered sequence of 119 instants. 120* A *time scale* is a way of representing an instant relative to an origin 121 that serves as the epoch. 122* A time scale is *monotonic* (increasing) if the representation of successive 123 time instants never decreases in value. 124* A time scale is *continuous* if the representation has no abrupt changes in 125 value, e.g. jumping forward or back when going between successive instants. 126* `Civil time <https://en.wikipedia.org/wiki/Civil_time>`__ generally refers 127 to time scales that legally defined by civil authorities, like local 128 governments, often to align local midnight to solar time. 129 130Relevant Time Scales 131==================== 132 133`International Atomic Time 134<https://en.wikipedia.org/wiki/International_Atomic_Time>`__ (TAI) is a time 135scale based on averaging clocks that count in SI seconds. TAI is a monotonic 136and continuous time scale. 137 138`Universal Time <https://en.wikipedia.org/wiki/Universal_Time>`__ (UT) is a 139time scale based on Earth’s rotation. UT is a discontinuous time scale as it 140requires occasional adjustments (`leap seconds 141<https://en.wikipedia.org/wiki/Leap_second>`__) to maintain alignment to 142changes in Earth’s rotation. Thus the difference between TAI and UT varies 143over time. There are several variants of UT, with `UTC 144<https://en.wikipedia.org/wiki/Coordinated_Universal_Time>`__ being the most 145common. 146 147UT times are independent of location. UT is the basis for Standard Time 148(or "local time") which is the time at a particular location. Standard 149time has a fixed offset from UT at any given instant, primarily 150influenced by longitude, but the offset may be adjusted ("daylight 151saving time") to align standard time to the local solar time. In a sense 152local time is "more discontinuous" than UT. 153 154`POSIX Time <https://tools.ietf.org/html/rfc8536#section-2>`__ is a time scale 155that counts seconds since the "POSIX epoch" at 1970-01-01T00:00:00Z (i.e. the 156start of 1970 UTC). `UNIX Time 157<https://tools.ietf.org/html/rfc8536#section-2>`__ is an extension of POSIX 158time using negative values to represent times before the POSIX epoch. Both of 159these scales assume that every day has exactly 86400 seconds. In normal use 160instants in these scales correspond to times in the UTC scale, so they inherit 161the discontinuity. 162 163The continuous analogue is `UNIX Leap Time 164<https://tools.ietf.org/html/rfc8536#section-2>`__ which is UNIX time plus all 165leap-second corrections added after the POSIX epoch (when TAI-UTC was 8 s). 166 167Example of Time Scale Differences 168--------------------------------- 169 170A positive leap second was introduced at the end of 2016, increasing the 171difference between TAI and UTC from 36 seconds to 37 seconds. There was 172no leap second introduced at the end of 1999, when the difference 173between TAI and UTC was only 32 seconds. The following table shows 174relevant civil and epoch times in several scales: 175 176==================== ========== =================== ======= ============== 177UTC Date UNIX time TAI Date TAI-UTC UNIX Leap Time 178==================== ========== =================== ======= ============== 1791970-01-01T00:00:00Z 0 1970-01-01T00:00:08 +8 0 1801999-12-31T23:59:28Z 946684768 2000-01-01T00:00:00 +32 946684792 1811999-12-31T23:59:59Z 946684799 2000-01-01T00:00:31 +32 946684823 1822000-01-01T00:00:00Z 946684800 2000-01-01T00:00:32 +32 946684824 1832016-12-31T23:59:59Z 1483228799 2017-01-01T00:00:35 +36 1483228827 1842016-12-31T23:59:60Z undefined 2017-01-01T00:00:36 +36 1483228828 1852017-01-01T00:00:00Z 1483228800 2017-01-01T00:00:37 +37 1483228829 186==================== ========== =================== ======= ============== 187 188Functional Requirements 189----------------------- 190 191The Zephyr tick counter has no concept of leap seconds or standard time 192offsets and is a continuous time scale. However it can be relatively 193inaccurate, with drifts as much as three minutes per hour (assuming an RC 194timer with 5% tolerance). 195 196There are two stages required to support conversion between Zephyr time and 197common human time scales: 198 199* Translation between the continuous but inaccurate Zephyr time scale and an 200 accurate external stable time scale; 201* Translation between the stable time scale and the (possibly discontinuous) 202 civil time scale. 203 204The API around :c:func:`timeutil_sync_state_update()` supports the first step 205of converting between continuous time scales. 206 207The second step requires external information including schedules of leap 208seconds and local time offset changes. This may be best provided by an 209external library, and is not currently part of the time utility APIs. 210 211Selecting an External Source and Time Scale 212------------------------------------------- 213 214If an application requires civil time accuracy within several seconds then UTC 215could be used as the stable time source. However, if the external source 216adjusts to a leap second there will be a discontinuity: the elapsed time 217between two observations taken at 1 Hz is not equal to the numeric difference 218between their timestamps. 219 220For precise activities a continuous scale that is independent of local and 221solar adjustments simplifies things considerably. Suitable continuous scales 222include: 223 224- GPS time: epoch of 1980-01-06T00:00:00Z, continuous following TAI with an 225 offset of TAI-GPS=19 s. 226- Bluetooth Mesh time: epoch of 2000-01-01T00:00:00Z, continuous following TAI 227 with an offset of -32. 228- UNIX Leap Time: epoch of 1970-01-01T00:00:00Z, continuous following TAI with 229 an offset of -8. 230 231Because C and Zephyr library functions support conversion between integral and 232calendar time representations using the UNIX epoch, UNIX Leap Time is an ideal 233choice for the external time scale. 234 235The mechanism used to populate synchronization points is not relevant: it may 236involve reading from a local high-precision RTC peripheral, exchanging packets 237over a network using a protocol like NTP or PTP, or processing NMEA messages 238received a GPS with or without a 1pps signal. 239