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* :ref:`comparing, adding, and subtracting representations <timeutil_manip>` 32 33For terminology and concepts that support these functions see 34:ref:`timeutil_concepts`. 35 36Time Utility APIs 37***************** 38 39.. _timeutil_repr: 40 41Representation Transformation 42============================= 43 44Time scale instants can be represented in multiple ways including: 45 46* Seconds since an epoch. POSIX representations of time in this form include 47 ``time_t`` and ``struct timespec``, which are generally interpreted as a 48 representation of `"UNIX Time" 49 <https://tools.ietf.org/html/rfc8536#section-2>`__. 50 51* Calendar time as a year, month, day, hour, minutes, and seconds relative to 52 an epoch. POSIX representations of time in this form include ``struct tm``. 53 54Keep in mind that these are simply time representations that must be 55interpreted relative to a time scale which may be local time, UTC, or some 56other continuous or discontinuous scale. 57 58Some necessary transformations are available in standard C library 59routines. For example, ``time_t`` measuring seconds since the POSIX EPOCH is 60converted to ``struct tm`` representing calendar time with `gmtime() 61<https://pubs.opengroup.org/onlinepubs/9699919799/functions/gmtime.html>`__. 62Sub-second timestamps like ``struct timespec`` can also use this to produce 63the calendar time representation and deal with sub-second offsets separately. 64 65The inverse transformation is not standardized: APIs like ``mktime()`` expect 66information about time zones. Zephyr provides this transformation with 67:c:func:`timeutil_timegm` and :c:func:`timeutil_timegm64`. 68 69To convert between ``struct timespec`` and ``k_timeout_t`` durations, 70use :c:func:`timespec_to_timeout` and :c:func:`timespec_from_timeout`. 71 72.. code-block:: c 73 74 k_timeout_t to; 75 struct timespec ts; 76 77 timespec_from_timeout(K_FOREVER, &ts); 78 to = timespec_to_timeout(&ts); /* to == K_FOREVER */ 79 80 timespec_from_timeout(K_MSEC(100), &ts); 81 to = timespec_to_timeout(&ts); /* to == K_MSEC(100) */ 82 83.. doxygengroup:: timeutil_repr_apis 84 85.. _timeutil_sync: 86 87Time Scale Synchronization 88========================== 89 90There are several factors that affect synchronizing time scales: 91 92* The rate of discrete instant representation change. For example Zephyr 93 uptime is tracked in ticks which advance at events that nominally occur at 94 :kconfig:option:`CONFIG_SYS_CLOCK_TICKS_PER_SEC` Hertz, while an external time 95 source may provide data in whole or fractional seconds (e.g. microseconds). 96* The absolute offset required to align the two scales at a single instant. 97* The relative error between observable instants in each scale, required to 98 align multiple instants consistently. For example a reference clock that's 99 conditioned by a 1-pulse-per-second GPS signal will be much more accurate 100 than a Zephyr system clock driven by a RC oscillator with a +/- 250 ppm 101 error. 102 103Synchronization or alignment between time scales is done with a multi-step 104process: 105 106* An instant in a time scale is represented by an (unsigned) 64-bit integer, 107 assumed to advance at a fixed nominal rate. 108* :c:struct:`timeutil_sync_config` records the nominal rates of a reference 109 time scale/source (e.g. TAI) and a local time source 110 (e.g. :c:func:`k_uptime_ticks`). 111* :c:struct:`timeutil_sync_instant` records the representation of a single 112 instant in both the reference and local time scales. 113* :c:struct:`timeutil_sync_state` provides storage for an initial instant, a 114 recently received second observation, and a skew that can adjust for 115 relative errors in the actual rate of each time scale. 116* :c:func:`timeutil_sync_ref_from_local()` and 117 :c:func:`timeutil_sync_local_from_ref()` convert instants in one time scale 118 to another taking into account skew that can be estimated from the two 119 instances stored in the state structure by 120 :c:func:`timeutil_sync_estimate_skew`. 121 122.. doxygengroup:: timeutil_sync_apis 123 124.. _timeutil_manip: 125 126``timespec`` Manipulation 127========================= 128 129Checking the validity of a ``timespec`` can be done with :c:func:`timespec_is_valid`. 130 131.. code-block:: c 132 133 struct timespec ts = { 134 .tv_sec = 0, 135 .tv_nsec = -1, /* out of range! */ 136 }; 137 138 if (!timespec_is_valid(&ts)) { 139 /* error-handing code */ 140 } 141 142In some cases, invalid ``timespec`` objects may be re-normalized using 143:c:func:`timespec_normalize`. 144 145.. code-block:: c 146 147 if (!timespec_normalize(&ts)) { 148 /* error-handling code */ 149 } 150 151 /* ts should be normalized */ 152 __ASSERT(timespec_is_valid(&ts) == true, "expected normalized timespec"); 153 154It is possible to compare two ``timespec`` objects for equality using :c:func:`timespec_equal`. 155 156.. code-block:: c 157 158 if (timespec_equal(then, now)) { 159 /* time is up! */ 160 } 161 162It is possible to compare and fully order (valid) ``timespec`` objects using 163:c:func:`timespec_compare`. 164 165.. code-block:: c 166 167 int cmp = timespec_compare(a, b); 168 169 switch (cmp) { 170 case 0: 171 /* a == b */ 172 break; 173 case -1: 174 /* a < b */ 175 break; 176 case +1: 177 /* a > b */ 178 break; 179 } 180 181It is possible to add, subtract, and negate ``timespec`` objects using 182:c:func:`timespec_add`, :c:func:`timespec_sub`, and :c:func:`timespec_negate`, 183respectively. Like :c:func:`timespec_normalize`, these functions will output 184a normalized ``timespec`` when doing so would not result in overflow. 185On success, these functions return ``true``. If overflow would occur, the 186functions return ``false``. 187 188.. code-block:: c 189 190 /* a += b */ 191 if (!timespec_add(&a, &b)) { 192 /* overflow */ 193 } 194 195 /* a -= b */ 196 if (!timespec_sub(&a, &b)) { 197 /* overflow */ 198 } 199 200 /* a = -a */ 201 if (!timespec_negate(&a)) { 202 /* overflow */ 203 } 204 205.. doxygengroup:: timeutil_timespec_apis 206 207 208.. _timeutil_concepts: 209 210Concepts Underlying Time Support in Zephyr 211****************************************** 212 213Terms from `ISO/TC 154/WG 5 N0038 214<https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf>`__ 215(ISO/WD 8601-1) and elsewhere: 216 217* A *time axis* is a representation of time as an ordered sequence of 218 instants. 219* A *time scale* is a way of representing an instant relative to an origin 220 that serves as the epoch. 221* A time scale is *monotonic* (increasing) if the representation of successive 222 time instants never decreases in value. 223* A time scale is *continuous* if the representation has no abrupt changes in 224 value, e.g. jumping forward or back when going between successive instants. 225* `Civil time <https://en.wikipedia.org/wiki/Civil_time>`__ generally refers 226 to time scales that legally defined by civil authorities, like local 227 governments, often to align local midnight to solar time. 228 229Relevant Time Scales 230==================== 231 232`International Atomic Time 233<https://en.wikipedia.org/wiki/International_Atomic_Time>`__ (TAI) is a time 234scale based on averaging clocks that count in SI seconds. TAI is a monotonic 235and continuous time scale. 236 237`Universal Time <https://en.wikipedia.org/wiki/Universal_Time>`__ (UT) is a 238time scale based on Earth’s rotation. UT is a discontinuous time scale as it 239requires occasional adjustments (`leap seconds 240<https://en.wikipedia.org/wiki/Leap_second>`__) to maintain alignment to 241changes in Earth’s rotation. Thus the difference between TAI and UT varies 242over time. There are several variants of UT, with `UTC 243<https://en.wikipedia.org/wiki/Coordinated_Universal_Time>`__ being the most 244common. 245 246UT times are independent of location. UT is the basis for Standard Time 247(or "local time") which is the time at a particular location. Standard 248time has a fixed offset from UT at any given instant, primarily 249influenced by longitude, but the offset may be adjusted ("daylight 250saving time") to align standard time to the local solar time. In a sense 251local time is "more discontinuous" than UT. 252 253`POSIX Time <https://tools.ietf.org/html/rfc8536#section-2>`__ is a time scale 254that counts seconds since the "POSIX epoch" at 1970-01-01T00:00:00Z (i.e. the 255start of 1970 UTC). `UNIX Time 256<https://tools.ietf.org/html/rfc8536#section-2>`__ is an extension of POSIX 257time using negative values to represent times before the POSIX epoch. Both of 258these scales assume that every day has exactly 86400 seconds. In normal use 259instants in these scales correspond to times in the UTC scale, so they inherit 260the discontinuity. 261 262The continuous analogue is `UNIX Leap Time 263<https://tools.ietf.org/html/rfc8536#section-2>`__ which is UNIX time plus all 264leap-second corrections added after the POSIX epoch (when TAI-UTC was 8 s). 265 266Example of Time Scale Differences 267--------------------------------- 268 269A positive leap second was introduced at the end of 2016, increasing the 270difference between TAI and UTC from 36 seconds to 37 seconds. There was 271no leap second introduced at the end of 1999, when the difference 272between TAI and UTC was only 32 seconds. The following table shows 273relevant civil and epoch times in several scales: 274 275==================== ========== =================== ======= ============== 276UTC Date UNIX time TAI Date TAI-UTC UNIX Leap Time 277==================== ========== =================== ======= ============== 2781970-01-01T00:00:00Z 0 1970-01-01T00:00:08 +8 0 2791999-12-31T23:59:28Z 946684768 2000-01-01T00:00:00 +32 946684792 2801999-12-31T23:59:59Z 946684799 2000-01-01T00:00:31 +32 946684823 2812000-01-01T00:00:00Z 946684800 2000-01-01T00:00:32 +32 946684824 2822016-12-31T23:59:59Z 1483228799 2017-01-01T00:00:35 +36 1483228827 2832016-12-31T23:59:60Z undefined 2017-01-01T00:00:36 +36 1483228828 2842017-01-01T00:00:00Z 1483228800 2017-01-01T00:00:37 +37 1483228829 285==================== ========== =================== ======= ============== 286 287Functional Requirements 288----------------------- 289 290The Zephyr tick counter has no concept of leap seconds or standard time 291offsets and is a continuous time scale. However it can be relatively 292inaccurate, with drifts as much as three minutes per hour (assuming an RC 293timer with 5% tolerance). 294 295There are two stages required to support conversion between Zephyr time and 296common human time scales: 297 298* Translation between the continuous but inaccurate Zephyr time scale and an 299 accurate external stable time scale; 300* Translation between the stable time scale and the (possibly discontinuous) 301 civil time scale. 302 303The API around :c:func:`timeutil_sync_state_update()` supports the first step 304of converting between continuous time scales. 305 306The second step requires external information including schedules of leap 307seconds and local time offset changes. This may be best provided by an 308external library, and is not currently part of the time utility APIs. 309 310Selecting an External Source and Time Scale 311------------------------------------------- 312 313If an application requires civil time accuracy within several seconds then UTC 314could be used as the stable time source. However, if the external source 315adjusts to a leap second there will be a discontinuity: the elapsed time 316between two observations taken at 1 Hz is not equal to the numeric difference 317between their timestamps. 318 319For precise activities a continuous scale that is independent of local and 320solar adjustments simplifies things considerably. Suitable continuous scales 321include: 322 323- GPS time: epoch of 1980-01-06T00:00:00Z, continuous following TAI with an 324 offset of TAI-GPS=19 s. 325- Bluetooth Mesh time: epoch of 2000-01-01T00:00:00Z, continuous following TAI 326 with an offset of -32. 327- UNIX Leap Time: epoch of 1970-01-01T00:00:00Z, continuous following TAI with 328 an offset of -8. 329 330Because C and Zephyr library functions support conversion between integral and 331calendar time representations using the UNIX epoch, UNIX Leap Time is an ideal 332choice for the external time scale. 333 334The mechanism used to populate synchronization points is not relevant: it may 335involve reading from a local high-precision RTC peripheral, exchanging packets 336over a network using a protocol like NTP or PTP, or processing NMEA messages 337received a GPS with or without a 1pps signal. 338 339``timespec`` Concepts 340===================== 341 342Originally from POSIX, ``struct timespec`` has been a part of the C standard 343since C11. The definition of ``struct timespec`` is as shown below. 344 345.. code-block:: c 346 347 struct timespec { 348 time_t tv_sec; /* seconds */ 349 long tv_nsec; /* nanoseconds */ 350 }; 351 352.. _note: 353 354 The C standard does not define the size of ``time_t``. However, Zephyr 355 uses 64-bits for ``time_t``. The ``long`` type is required to be at least 356 32-bits, but usually matches the word size of the architecture. Both 357 elements of ``struct timespec`` are signed integers. ``time_t`` is defined 358 to be 64-bits both for historical reasons and to be robust enough to 359 represent times in the future. 360 361The ``tv_nsec`` field is only valid with values in the range ``[0, 999999999]``. The 362``tv_sec`` field is the number of seconds since the epoch. If ``struct timespec`` is 363used to express a difference, the ``tv_sec`` field may fall into a negative range. 364