@ -28,6 +28,7 @@ The time utilities API supports:
* :ref: `converting between time representations <timeutil_repr>`
* :ref: `converting between time representations <timeutil_repr>`
* :ref: `synchronizing and aligning time scales <timeutil_sync>`
* :ref: `synchronizing and aligning time scales <timeutil_sync>`
* :ref: `comparing, adding, and subtracting representations <timeutil_manip>`
For terminology and concepts that support these functions see
For terminology and concepts that support these functions see
:ref: `timeutil_concepts` .
:ref: `timeutil_concepts` .
@ -65,6 +66,20 @@ The inverse transformation is not standardized: APIs like ``mktime()`` expect
information about time zones. Zephyr provides this transformation with
information about time zones. Zephyr provides this transformation with
:c:func: `timeutil_timegm` and :c:func: `timeutil_timegm64` .
:c:func: `timeutil_timegm` and :c:func: `timeutil_timegm64` .
To convert between `` struct timespec `` and `` k_timeout_t `` durations,
use :c:func: `timespec_to_timeout` and :c:func: `timespec_from_timeout` .
.. code-block :: c
k_timeout_t to;
struct timespec ts;
timespec_from_timeout(K_FOREVER, &ts);
to = timespec_to_timeout(&ts); /* to == K_FOREVER * /
timespec_from_timeout(K_MSEC(100), &ts);
to = timespec_to_timeout(&ts); /* to == K_MSEC(100) * /
.. doxygengroup :: timeutil_repr_apis
.. doxygengroup :: timeutil_repr_apis
.. _timeutil_sync:
.. _timeutil_sync:
@ -106,6 +121,90 @@ process:
.. doxygengroup :: timeutil_sync_apis
.. doxygengroup :: timeutil_sync_apis
.. _timeutil_manip:
`` timespec `` Manipulation
=========================
Checking the validity of a `` timespec `` can be done with :c:func: `timespec_is_valid` .
.. code-block :: c
struct timespec ts = {
.tv_sec = 0,
.tv_nsec = -1, /* out of range! * /
};
if (!timespec_is_valid(&ts)) {
/* error-handing code * /
}
In some cases, invalid `` timespec `` objects may be re-normalized using
:c:func: `timespec_normalize` .
.. code-block :: c
if (!timespec_normalize(&ts)) {
/* error-handling code * /
}
/* ts should be normalized * /
__ASSERT(timespec_is_valid(&ts) == true, "expected normalized timespec");
It is possible to compare two `` timespec `` objects for equality using :c:func: `timespec_equal` .
.. code-block :: c
if (timespec_equal(then, now)) {
/* time is up! * /
}
It is possible to compare and fully order (valid) `` timespec `` objects using
:c:func: `timespec_compare` .
.. code-block :: c
int cmp = timespec_compare(a, b);
switch (cmp) {
case 0:
/* a == b * /
break;
case -1:
/* a < b * /
break;
case +1:
/* a > b * /
break;
}
It is possible to add, subtract, and negate `` timespec `` objects using
:c:func: `timespec_add` , :c:func: `timespec_sub` , and :c:func: `timespec_negate` ,
respectively. Like :c:func: `timespec_normalize` , these functions will output
a normalized `` timespec `` when doing so would not result in overflow.
On success, these functions return `` true `` . If overflow would occur, the
functions return `` false `` .
.. code-block :: c
/* a += b * /
if (!timespec_add(&a, &b)) {
/* overflow * /
}
/* a -= b * /
if (!timespec_sub(&a, &b)) {
/* overflow * /
}
/* a = -a * /
if (!timespec_negate(&a)) {
/* overflow * /
}
.. doxygengroup :: timeutil_timespec_apis
.. _timeutil_concepts:
.. _timeutil_concepts:
Concepts Underlying Time Support in Zephyr
Concepts Underlying Time Support in Zephyr
@ -236,3 +335,29 @@ The mechanism used to populate synchronization points is not relevant: it may
involve reading from a local high-precision RTC peripheral, exchanging packets
involve reading from a local high-precision RTC peripheral, exchanging packets
over a network using a protocol like NTP or PTP, or processing NMEA messages
over a network using a protocol like NTP or PTP, or processing NMEA messages
received a GPS with or without a 1pps signal.
received a GPS with or without a 1pps signal.
`` timespec `` Concepts
=====================
Originally from POSIX, `` struct timespec `` has been a part of the C standard
since C11. The definition of `` struct timespec `` is as shown below.
.. code-block :: c
struct timespec {
time_t tv_sec; /* seconds * /
long tv_nsec; /* nanoseconds * /
};
.. _note:
The C standard does not define the size of `` time_t `` . However, Zephyr
uses 64-bits for `` time_t `` . The `` long `` type is required to be at least
32-bits, but usually matches the word size of the architecture. Both
elements of `` struct timespec `` are signed integers. `` time_t `` is defined
to be 64-bits both for historical reasons and to be robust enough to
represent times in the future.
The `` tv_nsec `` field is only valid with values in the range `` [0, 999999999] `` . The
`` tv_sec `` field is the number of seconds since the epoch. If `` struct timespec `` is
used to express a difference, the `` tv_sec `` field may fall into a negative range.