rt-thread icon indicating copy to clipboard operation
rt-thread copied to clipboard

[Feature] 对 hwtimer/ktime/cputime 进行整体重构

Open BernardXiong opened this issue 3 weeks ago • 3 comments

Describe problem solved by the proposed feature

目前 hwtimer/ktime/cputime 整体非常乱,应该从整体维度上进行重构,让它有一个更好的架构:

  • 简单清晰;
  • 针对MCU场景考虑,针对MPU场景考虑;
  • 反映到实时场景下的要求;
  • 如进行更改,应对所有涉及到的bsp进行检查并进行修改,至少保证构建无错,qemu测试通过;

对于这部分的重构,应该先给出整体设计,涉及到的文件评估,完成重构,ci涉及到的每个bsp构建,qemu测试通过。

Describe your preferred solution

No response

Describe possible alternatives

No response

BernardXiong avatar Dec 04 '25 13:12 BernardXiong

RT-Thread 时间子系统(ktime / cputime / hwtimer)分析

OS 时间子系统包含的主要部分

  • 时间基准(Time Source / Clocksource):提供连续、单调递增的计数值和频率信息,支持时间戳、运行时间统计等。
  • 事件源(Clockevent / Oneshot Timer):可编程定时事件,设定相对当前计数的到期点,到期触发中断。
  • 时间换算与基准时间:把计数值换算成 ns/us/ms,并维护开机以来的单调时间(boottime)。
  • 高精度定时器调度器:在事件源之上管理多路定时器(链表/红黑树),提供睡眠、周期/一次性定时 API。
  • 兼容层与设备抽象:面向 BSP/驱动提供统一的注册与能力标识,面向上层提供稳定 API,减少重复移植。

现状情况

  • ktime

    • 组成:boottime.c(弱符号,默认用 tick 计数换算 ns/us/s)、cputimer.c(弱符号,默认用 tick;AArch64/virt64 覆写为硬件计数器)、hrtimer.c(链表管理,spinlock 保护)。
    • 关键点:rt_ktime_hrtimer_settimeout 作为硬件回调入口,不实现时退化为软定时器;_cnt_convert 做 cputimer 周期到 hrtimer 周期的换算,防止大跨度溢出;_set_next_timeout_locked 尝试“消化”已过期并立即重新编程下一个超时。
    • 优点:有自旋锁,SMP 可用;接口风格与 rt_timer 类似,易迁移。
    • 问题:cputimer/boottime 采用 weak 函数,BSP 需重复覆写;hrtimer 仍用链表,未使用更高效数据结构;缺少统一驱动抽象,硬件适配散落在 BSP。
  • cputime

    • 组成:rt_clock_cputime_ops(getres/gettime/settimeout),clock_cpu_* 工具 API,cputimer.c 实现一个基于 clock_cpu_settimeout 的定时器链表(带信号量 sleep),cputime_cortexm/riscv 提供 ops 示例。
    • 关键点:clock_cpu_settimeout 允许硬件 oneshot;rt_cputimer_start/stop 使用全局中断屏蔽保护链表;rt_cputime_sleep/ndelay/udelay/mdelay 提供高精度延时。
    • 优点:接口简单,早期 BSP 已广泛使用;提供延时 API 对标 udelay 类需求。
    • 问题:与 ktime 的 cputimer/hrtimer 职责重叠;链表保护用关中断,SMP 下抖动大;未与 hwtimer 设备类复用,硬件适配重复。
  • hwtimer

    • 组成:设备抽象 rt_hwtimer_ops/info/device,实现文件 hwtimer.c,以及典型驱动 hwtimer-arm_arch.c
    • 关键点:timeout_calc 根据 sec/usec 和 freq/maxcnt 计算合适的 cycles/reload,支持上下计数模式;rt_device_hwtimer_isr 维护 overflow/cycles,并通过 rx_indicate 通知上层;control 支持设频率/模式/获取 info。
    • 优点:完整的 device/ops 封装,已有 DM/OFW 集成案例;支持频率自适应选择(尽量 1MHz)。
    • 问题:未作为 ktime/cputime 的统一后端;overflow/cycles 逻辑与高精度定时需求高度重合但未复用。

总结:ktime 和 cputime 都在提供“高精度计数 + oneshot/定时”能力,但各自一套接口(weak vs ops),应该是ktime是cputime的后期期望改善版本(但改善不彻底)。hrtimer/cputimer 都是链表调度,未复用 hwtimer。

BernardXiong avatar Dec 04 '25 14:12 BernardXiong

cputime - 是一份简洁版本的cpu time功能,提供对POSIX time的支持(clock_gettime/clock_settime/clock_getres)。而其中又被塞入了一份 定时器 的实现(以链表的方式) hwtimer - 是一份提供硬件外设定时器的设备操作接口的实现; ktime - 期望是一份容纳包括 cputime / bootime,再加上 hrtimer (高分辨率定时器)的实现。但这份实现加入后,又没把之前的给移除……然后就开始堆山了。

POSIX中的clockid_t,常见的包括:(取决于实现,POSIX vs Linux 扩展):

  • CLOCK_REALTIME:可被 settimeofday 等调整的墙钟时间。
  • CLOCK_MONOTONIC:单调递增,不受手动改时影响(可能受 NTP 微调)。
  • CLOCK_MONOTONIC_RAW(Linux):硬件单调计数原始值,不做 NTP 调整。
  • CLOCK_BOOTTIME(Linux):含挂起/休眠时间的单调计数。
  • CLOCK_REALTIME_COARSE / CLOCK_MONOTONIC_COARSE(Linux):低精度、低开销版本。
  • CLOCK_PROCESS_CPUTIME_ID:当前进程占用的 CPU 时间。
  • CLOCK_THREAD_CPUTIME_ID:当前线程占用的 CPU 时间。
  • CLOCK_TAI(Linux):国际原子时基准,不受闰秒调整。
  • 其他平台可能有:CLOCK_VIRTUAL、CLOCK_PROF(部分 Unix 旧实现),以及实现自定义的专用时钟。 Availability 需查各平台的 <time.h>/man page。

BernardXiong avatar Dec 04 '25 14:12 BernardXiong

RT-Thread 时间子系统 C-OOP 设计方案

引入统一时间设备抽象

  • clock_time:作为模块目录(如 components/drivers/clock_time),聚合时间基准/事件源能力,显式表意且不与 rt_timer 冲突。
  • rt_clock_time:作为对象/接口前缀,含义是“时间基准/时钟事件的统一抽象”。
struct rt_clock_time_ops
{
    rt_uint64_t (*get_freq)(void);                  /* 计数频率 Hz */
    rt_uint64_t (*get_counter)(void);               /* 自由运行计数值 */
    rt_err_t    (*set_timeout)(rt_uint64_t delta);  /* 相对当前计数的 oneshot,0 表示取消 */
};

struct rt_clock_time_device
{
    struct rt_device parent;
    const struct rt_clock_time_ops *ops;
    rt_uint64_t res_scale; /* ns * scale / freq -> cnt, 统一精度缩放 */
    rt_uint8_t  caps;      /* bit0: clocksource 可用; bit1: clockevent 可用 */
};
rt_err_t rt_clock_time_device_register(struct rt_clock_time_device *dev, const char *name, rt_uint8_t caps);
  • 提供默认 rt_clock_time_default(由 BSP 绑定:可直接封装 hwtimer 的 oneshot + count_get,或架构计数器),作为系统时基。
  • res_scale 固定用 RT_KTIME_RESMUL,兼容当前换算逻辑。

目录与功能覆盖情况(clock_time)

  • 目录:components/drivers/clock_time,集中放置抽象、公共实现与适配器。
  • 功能:统一覆盖 cputime(高精度计数与换算)、boottime(开机单调时间)、POSIX clock_gettime/clock_settime 支撑、hrtimer(红黑树优先,极简版可链表降级),并保留定时器对象/设备化接口(可由 hwtimer/DM/OFW 实例化)。
  • 命名:对外暴露 rt_clock_time_* 前缀的对象/函数,避免与 rt_timer 冲突且表意清晰。

clock_time 引入后,移除 cputime, hwtimer, ktime,都统一收归到 clock_time 中。如原有API有引用,做兼容处理或代码调整。

BernardXiong avatar Dec 04 '25 15:12 BernardXiong