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
{
const struct rt_clock_time_ops *ops;
rt_uint64_t res_scale;
rt_uint8_t caps;
};
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;
}
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.