RT-Thread RTOS
An open source embedded real-time operating system
Clock Time Core

Overview

The clock_time core defines the device model and conversion helpers used by the subsystem. It manages the default clock source and clock event devices and provides fixed-point conversion between counters and nanoseconds.

Device Model

Clock Time Operations

struct rt_clock_time_ops
{
rt_uint64_t (*get_freq)(struct rt_clock_time_device *dev);
rt_uint64_t (*get_counter)(struct rt_clock_time_device *dev);
rt_err_t (*set_timeout)(struct rt_clock_time_device *dev, rt_uint64_t delta);
};

get_freq

  • Purpose: return the counter frequency in Hz.
  • Requirements:
    • Must be stable and match the source used by get_counter.
    • Should be non-zero; zero indicates the device is not ready.

get_counter

  • Purpose: return a monotonically increasing counter value.
  • Requirements:
    • Must not go backwards.
    • Wrap behavior is allowed but should be consistent with the width of the counter used by the device.

set_timeout

  • Purpose: program the next timeout relative to the current counter value.
  • Parameters: delta is in the same counter units returned by get_counter.
  • Behavior:
    • If delta is 0 and the hardware supports it, the event can be canceled.
    • Return -RT_ENOSYS when the device does not support event programming.

Clock Time Device

struct rt_clock_time_device
{
struct rt_device parent;
const struct rt_clock_time_ops *ops;
rt_uint64_t res_scale;
rt_uint8_t caps; /* RT_CLOCK_TIME_CAP_SOURCE / RT_CLOCK_TIME_CAP_EVENT */
};
Definition: rtdef.h:1367
struct rt_object parent
Definition: rtdef.h:1368
  • res_scale provides extra precision in the conversion pipeline. If set to 0, RT_CLOCK_TIME_RESMUL is used by default.
  • caps advertises whether the device can be used as a clock source, a clock event, or both.

Register and Select Devices

rt_err_t rt_clock_time_device_register(struct rt_clock_time_device *dev,
const char *name,
rt_uint8_t caps);
void rt_clock_time_set_default_source(struct rt_clock_time_device *dev);
void rt_clock_time_set_default_event(struct rt_clock_time_device *dev);
struct rt_clock_time_device *rt_clock_time_get_default_source(void);
struct rt_clock_time_device *rt_clock_time_get_default_event(void);

rt_clock_time_device_register

  • Purpose: register a clock_time device and its capabilities.
  • Parameters:
    • dev: device object with ops and res_scale initialized.
    • name: device name; if NULL, only capability registration is performed.
    • caps: RT_CLOCK_TIME_CAP_SOURCE and/or RT_CLOCK_TIME_CAP_EVENT.
  • Behavior:
    • Registers the device under RT_Device_Class_Timer when name is provided.
    • If this is the first source, it becomes the default source.
    • If this is the first event, it becomes the default event.
  • Return values:
    • RT_EOK on success.
    • Negative error code if device registration fails.

rt_clock_time_set_default_source / rt_clock_time_set_default_event

  • Purpose: explicitly select the default source or event device.
  • Behavior: overrides the auto-selected default.

rt_clock_time_get_default_source / rt_clock_time_get_default_event

  • Purpose: query the current default devices.
  • Behavior:
    • Source defaults to the internal tick-based device if none was registered.
    • Event returns NULL if no event device is available.

rt_clock_time_source_init

  • Purpose: BSP hook to register an architecture counter or board source.
  • Notes: this function is weak and may be overridden by BSP code.

Clock Time Query APIs

rt_uint64_t rt_clock_time_get_freq(void);
rt_uint64_t rt_clock_time_get_counter(void);
rt_uint64_t rt_clock_time_get_event_freq(void);
rt_uint64_t rt_clock_time_get_event_res_scaled(void);

rt_clock_time_get_freq

  • Purpose: return the frequency of the default source in Hz.
  • Return values:
    • Non-zero frequency on success.
    • 0 if no valid source is available.

rt_clock_time_get_counter

  • Purpose: return the current counter from the default source.
  • Return values:
    • Monotonic counter value on success.
    • 0 if no valid source is available.

rt_clock_time_get_event_freq

  • Purpose: return the event device frequency in Hz.
  • Behavior: if no event device exists, falls back to the default source.

rt_clock_time_get_event_res_scaled

  • Purpose: return the scaled resolution for the event device.
  • Behavior: if no event device exists, falls back to the default source.

Conversion Helpers

rt_uint64_t rt_clock_time_get_res_scaled(void);
rt_uint64_t rt_clock_time_counter_to_ns(rt_uint64_t cnt);
rt_uint64_t rt_clock_time_ns_to_counter(rt_uint64_t ns);

rt_clock_time_get_res_scaled

  • Purpose: return the scaled resolution for the default source.
  • Return values:
    • Non-zero scaled resolution when the source is ready.
    • 0 when the source is missing or frequency is invalid.

rt_clock_time_counter_to_ns

  • Purpose: convert a counter value to nanoseconds based on the default source.
  • Notes: returns 0 when resolution is unavailable.

rt_clock_time_ns_to_counter

  • Purpose: convert nanoseconds to counter units for the default source.
  • Notes: returns 0 when resolution is unavailable.

Internally, the core computes a scaled resolution:

res_scaled = (1e9 * res_scale) / freq

Nanoseconds are then derived using the scale factor RT_CLOCK_TIME_RESMUL to avoid floating-point math. This keeps precision stable even when freq is not a power of ten.

Event API

rt_err_t rt_clock_time_set_timeout(rt_uint64_t delta);
void rt_clock_time_event_isr(void);

rt_clock_time_set_timeout

  • Purpose: program the next event using the default event device.
  • Parameters: delta in event counter units (same as event get_counter).
  • Return values:
    • RT_EOK on success.
    • -RT_ENOSYS if no event device exists or set_timeout is unsupported.

rt_clock_time_event_isr

  • Purpose: drive the hrtimer scheduler when an event expires.
  • Usage:
    • Call from the hardware timer ISR after acknowledging the interrupt.
    • This function processes expired hrtimers and programs the next event.

BSP Integration Example

Register a Clock Source

static rt_uint64_t demo_get_freq(struct rt_clock_time_device *dev)
{
RT_UNUSED(dev);
return 10000000ULL; /* 10 MHz */
}
static rt_uint64_t demo_get_counter(struct rt_clock_time_device *dev)
{
RT_UNUSED(dev);
return demo_hw_counter_read();
}
static const struct rt_clock_time_ops demo_src_ops =
{
demo_get_freq,
demo_get_counter,
RT_NULL,
};
static struct rt_clock_time_device demo_src_dev =
{
.ops = &demo_src_ops,
.res_scale = RT_CLOCK_TIME_RESMUL,
};
void rt_clock_time_source_init(void)
{
rt_clock_time_device_register(&demo_src_dev, "clock_time_demo_src",
RT_CLOCK_TIME_CAP_SOURCE);
rt_clock_time_set_default_source(&demo_src_dev);
}

Register a Clock Event

static rt_err_t demo_set_timeout(struct rt_clock_time_device *dev, rt_uint64_t delta)
{
RT_UNUSED(dev);
return demo_hw_timer_program(delta);
}
static const struct rt_clock_time_ops demo_evt_ops =
{
demo_get_freq,
demo_get_counter,
demo_set_timeout,
};
static struct rt_clock_time_device demo_evt_dev =
{
.ops = &demo_evt_ops,
.res_scale = RT_CLOCK_TIME_RESMUL,
};
static void demo_timer_isr(void)
{
demo_hw_timer_ack();
rt_clock_time_event_isr();
}
void demo_register_event(void)
{
rt_clock_time_device_register(&demo_evt_dev, "clock_time_demo_evt",
RT_CLOCK_TIME_CAP_EVENT);
rt_clock_time_set_default_event(&demo_evt_dev);
}

Notes

  • Event callbacks may run in interrupt context when backed by a hardware event.
  • If no event device is available, the hrtimer subsystem falls back to a software timer.