- Added comprehensive README for clock_time subsystem - Created ARM Generic Timer adapter example - Created SysTick/DWT adapter example for Cortex-M - Added adapter development guide with best practices Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
8.0 KiB
Clock Time Subsystem
Overview
The clock_time subsystem is a unified framework for time management in RT-Thread, replacing the legacy hwtimer, ktime, and cputime subsystems with a single, coherent API.
Background
Previously, RT-Thread had three separate time-related subsystems:
- hwtimer: Device abstraction for hardware timers with read/write interfaces
- cputime: CPU time tracking with ops structure for high-resolution counters
- ktime: Kernel time with boottime tracking and high-resolution timers (hrtimer)
These subsystems had overlapping functionality, inconsistent APIs, and no clear separation of concerns, leading to:
- Confusion about which subsystem to use
- Duplicated code in BSP drivers
- Difficulty maintaining compatibility
- Scattered documentation
Design Goals
The clock_time subsystem addresses these issues by:
- Unification: Single device abstraction (
rt_clock_time_device) for all timer hardware - Clarity: Clear separation between clocksource (counter) and clockevent (timeout) capabilities
- Compatibility: Backward compatibility layers for all legacy APIs
- Simplicity: Fewer concepts to learn, easier BSP integration
- Flexibility: Works with both MCU (tick-based fallback) and MPU (high-res timers) platforms
Architecture
┌─────────────────────────────────────────────┐
│ Application / POSIX APIs │
└───────────────────┬─────────────────────────┘
│
┌───────────────────▼─────────────────────────┐
│ Unified clock_time API │
│ - Clocksource (counter, boottime) │
│ - Clockevent (timeout, hrtimer) │
│ - Time conversion utilities │
└───────────────────┬─────────────────────────┘
│
┌───────────────────▼─────────────────────────┐
│ rt_clock_time_device + ops │
│ Capability flags: CLOCKSOURCE | CLOCKEVENT │
└───────────────────┬─────────────────────────┘
│
┌───────────────────▼─────────────────────────┐
│ BSP Hardware Timer Driver │
│ (SysTick, ARM Timer, RISC-V Timer, etc.) │
└─────────────────────────────────────────────┘
Key Components
1. Clock Time Device
The rt_clock_time_device structure encapsulates a hardware timer with:
- ops: Operations structure (
rt_clock_time_ops) - caps: Capability flags indicating supported features
- res_scale: Resolution scaling factor
2. Operations Structure
struct rt_clock_time_ops
{
rt_uint64_t (*get_freq)(void); /* Get frequency in Hz */
rt_uint64_t (*get_counter)(void); /* Get current counter */
rt_err_t (*set_timeout)(rt_uint64_t delta); /* Set timeout, 0 to cancel */
};
3. Capabilities
RT_CLOCK_TIME_CAP_CLOCKSOURCE: Provides free-running counter for timekeepingRT_CLOCK_TIME_CAP_CLOCKEVENT: Supports programmable timeout events
4. High-Resolution Timers
The rt_clock_hrtimer provides:
- One-shot and periodic timers
- Sorted linked-list scheduling
- SMP-safe spinlock protection
- Fallback to software timers when hardware timeout is unavailable
Migration Guide
For BSP Developers
Old hwtimer approach:
static const struct rt_hwtimer_ops my_ops = { ... };
static struct rt_hwtimer_device my_device;
rt_device_hwtimer_register(&my_device, "timer0", RT_NULL);
New clock_time approach:
static const struct rt_clock_time_ops my_ops = {
.get_freq = my_get_freq,
.get_counter = my_get_counter,
.set_timeout = my_set_timeout,
};
static struct rt_clock_time_device my_device;
my_device.ops = &my_ops;
rt_clock_time_device_register(&my_device, "timer0",
RT_CLOCK_TIME_CAP_CLOCKSOURCE | RT_CLOCK_TIME_CAP_CLOCKEVENT);
For Application Developers
Old cputime/ktime APIs still work when compatibility layers are enabled:
clock_cpu_gettime()→rt_clock_time_getcnt()rt_ktime_boottime_get_ns()→rt_clock_time_boottime_ns()rt_ktime_hrtimer_start()→rt_clock_hrtimer_start()
Recommended new APIs:
/* Get time information */
rt_uint64_t freq = rt_clock_time_getfreq();
rt_uint64_t cnt = rt_clock_time_getcnt();
/* High-precision delays */
rt_clock_udelay(100); /* 100 microseconds */
rt_clock_mdelay(10); /* 10 milliseconds */
/* High-resolution timers */
struct rt_clock_hrtimer timer;
rt_clock_hrtimer_init(&timer, "my_timer", RT_TIMER_FLAG_ONE_SHOT,
callback, param);
rt_clock_hrtimer_start(&timer, delay_cnt);
Compatibility Layers
Three compatibility layers are provided via Kconfig:
- RT_CLOCK_TIME_COMPAT_KTIME: Enables ktime API compatibility
- RT_CLOCK_TIME_COMPAT_CPUTIME: Enables cputime API compatibility
- RT_CLOCK_TIME_COMPAT_HWTIMER: Enables hwtimer device API compatibility
These allow gradual migration without breaking existing code.
File Structure
components/drivers/clock_time/
├── Kconfig # Configuration options
├── SConscript # Build script
├── src/
│ ├── clock_time.c # Core device management
│ ├── hrtimer.c # High-resolution timer implementation
│ ├── clock_time_tick.c # Tick-based fallback adapter
│ ├── ktime_compat.c # ktime compatibility layer
│ └── cputime_compat.c # cputime compatibility layer
└── include/drivers/
└── clock_time.h # Public API header
Testing Status
- Basic compilation verified
- BSP integration examples created
- QEMU runtime testing
- CI build verification
- Performance benchmarking
Known Limitations
-
Type width:
unsigned longis used for counter values to maintain ktime compatibility. On 32-bit systems, this limits maximum counter values. For very high-frequency timers (>4GHz), consider using 64-bit platforms or prescaling. -
Fallback mode: When no hardware clockevent is available, the system falls back to software timers (tick-based). This provides lower precision but ensures functionality.
-
Migration timeline: The old subsystems are marked as deprecated but not removed to allow time for migration.
Future Work
- Architecture-specific optimizations: Add optimized adapters for common architectures (ARM Generic Timer, RISC-V timer, etc.)
- Power management integration: Better support for low-power modes with clock gating
- Advanced scheduling: Consider red-black tree for timer scheduling in scenarios with many concurrent timers
- Complete migration: Remove deprecated subsystems after all BSPs migrate
Documentation
Contributing
When contributing to clock_time:
- Maintain backward compatibility with existing APIs
- Add tests for new functionality
- Update documentation
- Follow RT-Thread coding style
- Consider both MCU and MPU use cases
References
- Issue: [Feature] 对 hwtimer/ktime/cputime 进行整体重构
- Design discussion in issue comments
- POSIX clock APIs: clock_gettime(2), clock_settime(2)
- Linux clocksource/clockevent framework