Skip to content

[RFC] Abstract Clock Subsystem Architecture #19030

Closed
@pabigot

Description

@pabigot

This RFC was closed in favor of a full summary in #76335

Based on discussion in #17162 the following describes a proposed API extension that is enabled by #17155 given a few minor API changes.

Proposed Zephyr Clocks

I would like the end goal to be support for the following clocks:

  • K_CLOCK_HARDWARE corresponds to the Zephyr hardware clock. It is provided by k_cycle_get(). This is a monotonic non-decreasing non-wrapping 64-bit source with zero at the instant the system hardware clock is initialized. A duration of 1 corresponds to a Zephyr cycle. The rate Z_HZ_cyc is a constant number of nominal cycles per second, but the actual rate may vary, and may not be a compile-time constant.
  • K_CLOCK_SYSTEM corresponds to the the system clock. This is a monotonic non-decreasing non-wrapping 64-bit source with a zero at the instant of the zero of K_CLOCK_HARDWARE. A duration of 1 corresponds to a Zephyr tick. The rate Z_HZ_ticks is a compile-time constant, but the criteria for advancing the clock depends on CONFIG_TICKLESS_KERNEL. For a tickless kernel this source is a linear transformation scaling K_CLOCK_HARDWARE by Z_HZ_ticks / Z_HZ_cyc.
  • K_CLOCK_MONOTONIC is the documented clock used for the timeout API defined in New timeout API #17155. It should be an alias for K_CLOCK_SYSTEM.
  • (TBD) K_CLOCK_UPTIME corresponds to k_uptime_get(). This is a linear transformation using K_CLOCK_MONOTONIC nominal tick rate to convert to a time scale where a duration of 1 corresponds to one millisecond. This probably isn't necessary, though it might be convenient.
  • (TBD) K_CLOCK_REALTIME would correspond to something that tracks civil time a la NTP. This is very TBD.

Let k_clock_id_t denote the type of the above K_CLOCK_FOO constants. Additional clock sources are possible by a Kconfig option to enable them for specific devices. This would extend the device API with functions provide frequency, gettime, and alarm capabilities for the provider. For example:

k_clock_id_t hires = counter_get_clock(dev);

would provide a clock id for timeouts that use that counter to control their duration, assuming the counter identified by dev was configured to support use as a clock source. Other non-counter providers may exist as well. Any clock id could be used in the following generic API:

u64_t k_clock_get(k_clock_id_t id);
u32_t k_clock_frequency(k_clock_id_t id);
k_timeout_t k_clock_convert(k_timeout_t t, k_clock_id id);

We then have:

  • k_clock_get(K_CLOCK_HARDWARE) == k_cycle_get()
  • k_clock_get(K_CLOCK_UPTIME) == k_uptime_get()
  • k_clock_get(K_CLOCK_SYSTEM) returns the tick counter (curr_tick)

Currently the opaque k_ticks_t value encodes a count in ticks that is either relative or absolute. In the future it should also encode the id of the clock to which it applies, so we should be able to use z_add_timeout and have that record on the queue for the corresponding clock.

We will also need API extensions:

  • Every K_TIMEOUT_suffix(args...) will have a corresponding K_CLOCK_TIMEOUT_suffix(id, args...) which implements it for clocks other than K_CLOCK_MONOTONIC.
  • All k_?s_to_ticks_suffix(args...) will have a corresponding k_?s_to_clock_ticks_suffix(id, args...) which implements the conversion between time and clock values/durations using the rate for a specific clock.
  • A new k_delay(k_timeout_t t) that extends the capability of k_sleep() to other clock sources.

Metadata

Metadata

Assignees

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions