diff --git a/components/drivers/clock_time/README.md b/components/drivers/clock_time/README.md new file mode 100644 index 0000000000..5be7b2241f --- /dev/null +++ b/components/drivers/clock_time/README.md @@ -0,0 +1,638 @@ +# RT-Thread Clock Time Subsystem / RT-Thread 时钟时间子系统 + +English | [中文](#中文文档) + +## Overview + +The `clock_time` subsystem provides a unified interface for time-related hardware and software functionality in RT-Thread. It consolidates and replaces the previous separate subsystems: +- **hwtimer**: Hardware timer device drivers +- **ktime**: Kernel time and high-resolution timers +- **cputime**: CPU time measurement + +## Architecture + +The clock_time subsystem follows a C-OOP (C Object-Oriented Programming) design pattern with clear separation of concerns: + +``` +┌─────────────────────────────────────────────────────────┐ +│ Application Layer │ +│ (POSIX clock_gettime, nanosleep, etc.) │ +└────────────────┬────────────────────────────────────────┘ + │ +┌────────────────▼────────────────────────────────────────┐ +│ Clock Time High-Level APIs │ +│ • Boottime (monotonic time since boot) │ +│ • High-Resolution Timers (hrtimer) │ +│ • CPU Timer (counter access) │ +└────────────────┬────────────────────────────────────────┘ + │ +┌────────────────▼────────────────────────────────────────┐ +│ Clock Time Device Abstraction │ +│ struct rt_clock_time_device │ +│ struct rt_clock_time_ops │ +└────────────────┬────────────────────────────────────────┘ + │ +┌────────────────▼────────────────────────────────────────┐ +│ Hardware / BSP Implementation │ +│ • ARM Arch Timer, RISC-V RDTIME │ +│ • SysTick, System Timer │ +│ • Hardware Timer Peripherals │ +└─────────────────────────────────────────────────────────┘ +``` + +### Key Components + +1. **Device Abstraction** (`clock_time.c`) + - Unified device interface for timer hardware + - Device registration and management + - Capability flags (clocksource, clockevent) + +2. **High-Resolution Timers** (`hrtimer.c`) + - Software timer scheduling on hardware timers + - Linked-list or red-black tree management + - SMP-safe with spinlock protection + +3. **Boottime APIs** (`clock_time_boottime.c`) + - Monotonic time since system boot + - Nanosecond, microsecond, second precision + +4. **CPU Timer** (`clock_time_tick.c`, `clock_time_cputime.c`) + - Low-level counter access + - Frequency and resolution queries + - Tick-based fallback for simple systems + +## Configuration + +Enable clock_time in menuconfig: + +``` +Device Drivers ---> + [*] Using unified clock_time subsystem ---> + [*] Enable high-resolution timer support + [*] Enable CPU time APIs + [*] Enable boottime APIs +``` + +### Backward Compatibility + +When `RT_USING_CLOCK_TIME` is enabled, the old subsystems are automatically disabled and their APIs are redirected: + +- `RT_USING_HWTIMER` → Automatically set (compatibility mode) +- `RT_USING_KTIME` → Automatically set (compatibility mode) +- `RT_USING_CPUTIME` → Automatically set (compatibility mode) + +All `rt_ktime_*` APIs are mapped to `rt_clock_*` APIs via macros, ensuring existing code continues to work. + +## API Reference + +### Device Management + +```c +/* Register a clock time device */ +rt_err_t rt_clock_time_device_register(struct rt_clock_time_device *dev, + const char *name, + rt_uint8_t caps); + +/* Get/set default system clock device */ +rt_clock_time_t rt_clock_time_default(void); +rt_err_t rt_clock_time_set_default(rt_clock_time_t dev); +``` + +### Boottime APIs + +```c +/* Get system boottime (monotonic time since boot) */ +rt_err_t rt_clock_boottime_get_ns(struct timespec *ts); // Nanosecond precision +rt_err_t rt_clock_boottime_get_us(struct timeval *tv); // Microsecond precision +rt_err_t rt_clock_boottime_get_s(time_t *t); // Second precision +``` + +### CPU Timer APIs + +```c +/* Low-level counter access */ +rt_uint64_t rt_clock_cputimer_getres(void); // Get resolution +unsigned long rt_clock_cputimer_getfrq(void); // Get frequency in Hz +unsigned long rt_clock_cputimer_getcnt(void); // Get current counter value +void rt_clock_cputimer_init(void); // Initialize (called by system) +``` + +### High-Resolution Timer APIs + +```c +/* Initialize and manage high-resolution timers */ +void rt_clock_hrtimer_init(rt_clock_hrtimer_t timer, const char *name, + rt_uint8_t flag, void (*timeout)(void *), void *param); +rt_err_t rt_clock_hrtimer_start(rt_clock_hrtimer_t timer, unsigned long cnt); +rt_err_t rt_clock_hrtimer_stop(rt_clock_hrtimer_t timer); +rt_err_t rt_clock_hrtimer_detach(rt_clock_hrtimer_t timer); + +/* Delay functions (blocking) */ +rt_err_t rt_clock_hrtimer_ndelay(struct rt_clock_hrtimer *timer, unsigned long ns); +rt_err_t rt_clock_hrtimer_udelay(struct rt_clock_hrtimer *timer, unsigned long us); +rt_err_t rt_clock_hrtimer_mdelay(struct rt_clock_hrtimer *timer, unsigned long ms); +``` + +## BSP Porting Guide + +### Minimal Implementation (Tick-based) + +The tick-based fallback works out-of-the-box for simple systems: + +```c +// No additional code needed - uses RT_TICK_PER_SECOND +// Automatically provides: +// - rt_clock_cputimer_getcnt() → rt_tick_get() +// - rt_clock_cputimer_getfrq() → RT_TICK_PER_SECOND +// - Resolution based on tick rate +``` + +### Hardware Timer Implementation + +For better precision, implement hardware timer support: + +```c +#include + +/* Define hardware operations */ +static rt_uint64_t my_timer_get_freq(void) { + return 1000000; // 1 MHz +} + +static rt_uint64_t my_timer_get_counter(void) { + return READ_TIMER_COUNTER_REG(); +} + +static rt_err_t my_timer_set_timeout(rt_uint64_t delta) { + if (delta == 0) { + DISABLE_TIMER_INTERRUPT(); + return RT_EOK; + } + SET_TIMER_COMPARE_VALUE(delta); + ENABLE_TIMER_INTERRUPT(); + return RT_EOK; +} + +static const struct rt_clock_time_ops my_timer_ops = { + .get_freq = my_timer_get_freq, + .get_counter = my_timer_get_counter, + .set_timeout = my_timer_set_timeout, +}; + +/* Define device structure */ +static struct rt_clock_time_device my_timer_dev; + +/* Initialize and register */ +int my_timer_init(void) { + HARDWARE_TIMER_INIT(); + + my_timer_dev.ops = &my_timer_ops; + + return rt_clock_time_device_register(&my_timer_dev, "timer0", + RT_CLOCK_TIME_CAP_CLOCKSOURCE | RT_CLOCK_TIME_CAP_CLOCKEVENT); +} +INIT_BOARD_EXPORT(my_timer_init); + +/* Timer interrupt handler */ +void timer_irq_handler(void) { + CLEAR_TIMER_INTERRUPT(); + rt_clock_hrtimer_process(); // Process expired timers +} +``` + +### Overriding CPU Timer Functions + +For architecture-specific high-performance counters (e.g., ARM DWT, RISC-V RDTIME): + +```c +/* Override weak functions in your BSP */ +unsigned long rt_clock_cputimer_getcnt(void) { + return READ_CPU_CYCLE_COUNTER(); +} + +unsigned long rt_clock_cputimer_getfrq(void) { + return CPU_FREQUENCY_HZ; +} + +rt_uint64_t rt_clock_cputimer_getres(void) { + // Resolution in ns * RT_CLOCK_TIME_RESMUL + return ((1000000000ULL * RT_CLOCK_TIME_RESMUL) / CPU_FREQUENCY_HZ); +} +``` + +## Migration Guide + +### From ktime + +All `rt_ktime_*` APIs are automatically mapped. No code changes needed: + +```c +// Old code (still works) +#include +rt_ktime_boottime_get_ns(&ts); +rt_ktime_hrtimer_init(&timer, "mytimer", ...); + +// Equivalent new code (optional migration) +#include +rt_clock_boottime_get_ns(&ts); +rt_clock_hrtimer_init(&timer, "mytimer", ...); +``` + +### From hwtimer + +Hardware timer drivers should be updated to use the new device abstraction: + +```c +// Old: struct rt_hwtimer_device + rt_device_hwtimer_register() +// New: struct rt_clock_time_device + rt_clock_time_device_register() +``` + +### From cputime + +CPU time APIs have been unified: + +```c +// Old: clock_cpu_gettime() / clock_cpu_getres() +// New: rt_clock_cputimer_getcnt() / rt_clock_cputimer_getres() +// Note: Old APIs still work if using old cputime module +``` + +## Examples + +### Example 1: One-shot Timer + +```c +#include + +static void timer_callback(void *param) { + rt_kprintf("Timer expired!\n"); +} + +void example_oneshot_timer(void) { + struct rt_clock_hrtimer timer; + + rt_clock_hrtimer_init(&timer, "oneshot", RT_TIMER_FLAG_ONE_SHOT, + timer_callback, NULL); + + // Start timer for 1 second (using CPU timer frequency) + unsigned long freq = rt_clock_cputimer_getfrq(); + rt_clock_hrtimer_start(&timer, freq * 1); + + // Timer will fire callback after 1 second +} +``` + +### Example 2: Microsecond Delay + +```c +#include + +void example_delay(void) { + struct rt_clock_hrtimer timer; + + rt_clock_hrtimer_delay_init(&timer); + + // Delay for 500 microseconds + rt_clock_hrtimer_udelay(&timer, 500); + + rt_clock_hrtimer_delay_detach(&timer); +} +``` + +### Example 3: Boottime Measurement + +```c +#include + +void example_boottime(void) { + struct timespec ts; + + rt_clock_boottime_get_ns(&ts); + rt_kprintf("System has been running for %ld.%09ld seconds\n", + ts.tv_sec, ts.tv_nsec); +} +``` + +--- + +## 中文文档 + +## 概述 + +`clock_time` 子系统为 RT-Thread 中的时间相关硬件和软件功能提供统一接口。它整合并替代了以前的独立子系统: +- **hwtimer**:硬件定时器设备驱动 +- **ktime**:内核时间和高分辨率定时器 +- **cputime**:CPU 时间测量 + +## 架构 + +clock_time 子系统遵循 C-OOP(C 语言面向对象编程)设计模式,职责清晰分离: + +``` +┌─────────────────────────────────────────────────────────┐ +│ 应用层 │ +│ (POSIX clock_gettime, nanosleep 等) │ +└────────────────┬────────────────────────────────────────┘ + │ +┌────────────────▼────────────────────────────────────────┐ +│ 时钟时间高层 API │ +│ • Boottime (自启动以来的单调时间) │ +│ • 高分辨率定时器 (hrtimer) │ +│ • CPU 定时器 (计数器访问) │ +└────────────────┬────────────────────────────────────────┘ + │ +┌────────────────▼────────────────────────────────────────┐ +│ 时钟时间设备抽象 │ +│ struct rt_clock_time_device │ +│ struct rt_clock_time_ops │ +└────────────────┬────────────────────────────────────────┘ + │ +┌────────────────▼────────────────────────────────────────┐ +│ 硬件 / BSP 实现 │ +│ • ARM Arch Timer, RISC-V RDTIME │ +│ • SysTick, 系统定时器 │ +│ • 硬件定时器外设 │ +└─────────────────────────────────────────────────────────┘ +``` + +### 关键组件 + +1. **设备抽象** (`clock_time.c`) + - 定时器硬件的统一设备接口 + - 设备注册和管理 + - 能力标志(时钟源、时钟事件) + +2. **高分辨率定时器** (`hrtimer.c`) + - 在硬件定时器上的软件定时器调度 + - 链表或红黑树管理 + - SMP 安全,带自旋锁保护 + +3. **Boottime API** (`clock_time_boottime.c`) + - 自系统启动以来的单调时间 + - 纳秒、微秒、秒精度 + +4. **CPU 定时器** (`clock_time_tick.c`, `clock_time_cputime.c`) + - 底层计数器访问 + - 频率和分辨率查询 + - 简单系统的基于 tick 的回退 + +## 配置 + +在 menuconfig 中启用 clock_time: + +``` +Device Drivers ---> + [*] Using unified clock_time subsystem ---> + [*] Enable high-resolution timer support + [*] Enable CPU time APIs + [*] Enable boottime APIs +``` + +### 向后兼容 + +当启用 `RT_USING_CLOCK_TIME` 时,旧子系统自动禁用,其 API 被重定向: + +- `RT_USING_HWTIMER` → 自动设置(兼容模式) +- `RT_USING_KTIME` → 自动设置(兼容模式) +- `RT_USING_CPUTIME` → 自动设置(兼容模式) + +所有 `rt_ktime_*` API 通过宏映射到 `rt_clock_*` API,确保现有代码继续工作。 + +## API 参考 + +### 设备管理 + +```c +/* 注册时钟时间设备 */ +rt_err_t rt_clock_time_device_register(struct rt_clock_time_device *dev, + const char *name, + rt_uint8_t caps); + +/* 获取/设置默认系统时钟设备 */ +rt_clock_time_t rt_clock_time_default(void); +rt_err_t rt_clock_time_set_default(rt_clock_time_t dev); +``` + +### Boottime API + +```c +/* 获取系统启动时间(自启动以来的单调时间) */ +rt_err_t rt_clock_boottime_get_ns(struct timespec *ts); // 纳秒精度 +rt_err_t rt_clock_boottime_get_us(struct timeval *tv); // 微秒精度 +rt_err_t rt_clock_boottime_get_s(time_t *t); // 秒精度 +``` + +### CPU 定时器 API + +```c +/* 底层计数器访问 */ +rt_uint64_t rt_clock_cputimer_getres(void); // 获取分辨率 +unsigned long rt_clock_cputimer_getfrq(void); // 获取频率(Hz) +unsigned long rt_clock_cputimer_getcnt(void); // 获取当前计数器值 +void rt_clock_cputimer_init(void); // 初始化(由系统调用) +``` + +### 高分辨率定时器 API + +```c +/* 初始化和管理高分辨率定时器 */ +void rt_clock_hrtimer_init(rt_clock_hrtimer_t timer, const char *name, + rt_uint8_t flag, void (*timeout)(void *), void *param); +rt_err_t rt_clock_hrtimer_start(rt_clock_hrtimer_t timer, unsigned long cnt); +rt_err_t rt_clock_hrtimer_stop(rt_clock_hrtimer_t timer); +rt_err_t rt_clock_hrtimer_detach(rt_clock_hrtimer_t timer); + +/* 延时函数(阻塞) */ +rt_err_t rt_clock_hrtimer_ndelay(struct rt_clock_hrtimer *timer, unsigned long ns); +rt_err_t rt_clock_hrtimer_udelay(struct rt_clock_hrtimer *timer, unsigned long us); +rt_err_t rt_clock_hrtimer_mdelay(struct rt_clock_hrtimer *timer, unsigned long ms); +``` + +## BSP 移植指南 + +### 最小实现(基于 Tick) + +基于 tick 的回退对简单系统开箱即用: + +```c +// 无需额外代码 - 使用 RT_TICK_PER_SECOND +// 自动提供: +// - rt_clock_cputimer_getcnt() → rt_tick_get() +// - rt_clock_cputimer_getfrq() → RT_TICK_PER_SECOND +// - 基于 tick 速率的分辨率 +``` + +### 硬件定时器实现 + +为了更好的精度,实现硬件定时器支持: + +```c +#include + +/* 定义硬件操作 */ +static rt_uint64_t my_timer_get_freq(void) { + return 1000000; // 1 MHz +} + +static rt_uint64_t my_timer_get_counter(void) { + return READ_TIMER_COUNTER_REG(); +} + +static rt_err_t my_timer_set_timeout(rt_uint64_t delta) { + if (delta == 0) { + DISABLE_TIMER_INTERRUPT(); + return RT_EOK; + } + SET_TIMER_COMPARE_VALUE(delta); + ENABLE_TIMER_INTERRUPT(); + return RT_EOK; +} + +static const struct rt_clock_time_ops my_timer_ops = { + .get_freq = my_timer_get_freq, + .get_counter = my_timer_get_counter, + .set_timeout = my_timer_set_timeout, +}; + +/* 定义设备结构 */ +static struct rt_clock_time_device my_timer_dev; + +/* 初始化和注册 */ +int my_timer_init(void) { + HARDWARE_TIMER_INIT(); + + my_timer_dev.ops = &my_timer_ops; + + return rt_clock_time_device_register(&my_timer_dev, "timer0", + RT_CLOCK_TIME_CAP_CLOCKSOURCE | RT_CLOCK_TIME_CAP_CLOCKEVENT); +} +INIT_BOARD_EXPORT(my_timer_init); + +/* 定时器中断处理程序 */ +void timer_irq_handler(void) { + CLEAR_TIMER_INTERRUPT(); + rt_clock_hrtimer_process(); // 处理过期定时器 +} +``` + +### 覆盖 CPU 定时器函数 + +对于架构特定的高性能计数器(例如 ARM DWT、RISC-V RDTIME): + +```c +/* 在 BSP 中覆盖弱函数 */ +unsigned long rt_clock_cputimer_getcnt(void) { + return READ_CPU_CYCLE_COUNTER(); +} + +unsigned long rt_clock_cputimer_getfrq(void) { + return CPU_FREQUENCY_HZ; +} + +rt_uint64_t rt_clock_cputimer_getres(void) { + // 分辨率(纳秒 * RT_CLOCK_TIME_RESMUL) + return ((1000000000ULL * RT_CLOCK_TIME_RESMUL) / CPU_FREQUENCY_HZ); +} +``` + +## 迁移指南 + +### 从 ktime 迁移 + +所有 `rt_ktime_*` API 自动映射。无需更改代码: + +```c +// 旧代码(仍然有效) +#include +rt_ktime_boottime_get_ns(&ts); +rt_ktime_hrtimer_init(&timer, "mytimer", ...); + +// 等效的新代码(可选迁移) +#include +rt_clock_boottime_get_ns(&ts); +rt_clock_hrtimer_init(&timer, "mytimer", ...); +``` + +### 从 hwtimer 迁移 + +硬件定时器驱动应更新为使用新的设备抽象: + +```c +// 旧:struct rt_hwtimer_device + rt_device_hwtimer_register() +// 新:struct rt_clock_time_device + rt_clock_time_device_register() +``` + +### 从 cputime 迁移 + +CPU 时间 API 已统一: + +```c +// 旧:clock_cpu_gettime() / clock_cpu_getres() +// 新:rt_clock_cputimer_getcnt() / rt_clock_cputimer_getres() +// 注意:如果使用旧 cputime 模块,旧 API 仍然有效 +``` + +## 示例 + +### 示例 1:一次性定时器 + +```c +#include + +static void timer_callback(void *param) { + rt_kprintf("定时器过期!\n"); +} + +void example_oneshot_timer(void) { + struct rt_clock_hrtimer timer; + + rt_clock_hrtimer_init(&timer, "oneshot", RT_TIMER_FLAG_ONE_SHOT, + timer_callback, NULL); + + // 启动定时器 1 秒(使用 CPU 定时器频率) + unsigned long freq = rt_clock_cputimer_getfrq(); + rt_clock_hrtimer_start(&timer, freq * 1); + + // 定时器将在 1 秒后触发回调 +} +``` + +### 示例 2:微秒延时 + +```c +#include + +void example_delay(void) { + struct rt_clock_hrtimer timer; + + rt_clock_hrtimer_delay_init(&timer); + + // 延时 500 微秒 + rt_clock_hrtimer_udelay(&timer, 500); + + rt_clock_hrtimer_delay_detach(&timer); +} +``` + +### 示例 3:启动时间测量 + +```c +#include + +void example_boottime(void) { + struct timespec ts; + + rt_clock_boottime_get_ns(&ts); + rt_kprintf("系统已运行 %ld.%09ld 秒\n", + ts.tv_sec, ts.tv_nsec); +} +``` + +## License + +Apache-2.0 + +## References + +- RT-Thread Programming Guide: https://www.rt-thread.io/document/site/ +- RT-Thread Coding Style: https://github.com/RT-Thread/rt-thread/blob/master/documentation/coding_style_cn.md