|
| 1 | +# Clock Time Subsystem |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +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. |
| 6 | + |
| 7 | +## Background |
| 8 | + |
| 9 | +Previously, RT-Thread had three separate time-related subsystems: |
| 10 | + |
| 11 | +1. **hwtimer**: Device abstraction for hardware timers with read/write interfaces |
| 12 | +2. **cputime**: CPU time tracking with ops structure for high-resolution counters |
| 13 | +3. **ktime**: Kernel time with boottime tracking and high-resolution timers (hrtimer) |
| 14 | + |
| 15 | +These subsystems had overlapping functionality, inconsistent APIs, and no clear separation of concerns, leading to: |
| 16 | +- Confusion about which subsystem to use |
| 17 | +- Duplicated code in BSP drivers |
| 18 | +- Difficulty maintaining compatibility |
| 19 | +- Scattered documentation |
| 20 | + |
| 21 | +## Design Goals |
| 22 | + |
| 23 | +The `clock_time` subsystem addresses these issues by: |
| 24 | + |
| 25 | +1. **Unification**: Single device abstraction (`rt_clock_time_device`) for all timer hardware |
| 26 | +2. **Clarity**: Clear separation between clocksource (counter) and clockevent (timeout) capabilities |
| 27 | +3. **Compatibility**: Backward compatibility layers for all legacy APIs |
| 28 | +4. **Simplicity**: Fewer concepts to learn, easier BSP integration |
| 29 | +5. **Flexibility**: Works with both MCU (tick-based fallback) and MPU (high-res timers) platforms |
| 30 | + |
| 31 | +## Architecture |
| 32 | + |
| 33 | +``` |
| 34 | +┌─────────────────────────────────────────────┐ |
| 35 | +│ Application / POSIX APIs │ |
| 36 | +└───────────────────┬─────────────────────────┘ |
| 37 | + │ |
| 38 | +┌───────────────────▼─────────────────────────┐ |
| 39 | +│ Unified clock_time API │ |
| 40 | +│ - Clocksource (counter, boottime) │ |
| 41 | +│ - Clockevent (timeout, hrtimer) │ |
| 42 | +│ - Time conversion utilities │ |
| 43 | +└───────────────────┬─────────────────────────┘ |
| 44 | + │ |
| 45 | +┌───────────────────▼─────────────────────────┐ |
| 46 | +│ rt_clock_time_device + ops │ |
| 47 | +│ Capability flags: CLOCKSOURCE | CLOCKEVENT │ |
| 48 | +└───────────────────┬─────────────────────────┘ |
| 49 | + │ |
| 50 | +┌───────────────────▼─────────────────────────┐ |
| 51 | +│ BSP Hardware Timer Driver │ |
| 52 | +│ (SysTick, ARM Timer, RISC-V Timer, etc.) │ |
| 53 | +└─────────────────────────────────────────────┘ |
| 54 | +``` |
| 55 | + |
| 56 | +## Key Components |
| 57 | + |
| 58 | +### 1. Clock Time Device |
| 59 | + |
| 60 | +The `rt_clock_time_device` structure encapsulates a hardware timer with: |
| 61 | +- **ops**: Operations structure (`rt_clock_time_ops`) |
| 62 | +- **caps**: Capability flags indicating supported features |
| 63 | +- **res_scale**: Resolution scaling factor |
| 64 | + |
| 65 | +### 2. Operations Structure |
| 66 | + |
| 67 | +```c |
| 68 | +struct rt_clock_time_ops |
| 69 | +{ |
| 70 | + rt_uint64_t (*get_freq)(void); /* Get frequency in Hz */ |
| 71 | + rt_uint64_t (*get_counter)(void); /* Get current counter */ |
| 72 | + rt_err_t (*set_timeout)(rt_uint64_t delta); /* Set timeout, 0 to cancel */ |
| 73 | +}; |
| 74 | +``` |
| 75 | + |
| 76 | +### 3. Capabilities |
| 77 | + |
| 78 | +- `RT_CLOCK_TIME_CAP_CLOCKSOURCE`: Provides free-running counter for timekeeping |
| 79 | +- `RT_CLOCK_TIME_CAP_CLOCKEVENT`: Supports programmable timeout events |
| 80 | + |
| 81 | +### 4. High-Resolution Timers |
| 82 | + |
| 83 | +The `rt_clock_hrtimer` provides: |
| 84 | +- One-shot and periodic timers |
| 85 | +- Sorted linked-list scheduling |
| 86 | +- SMP-safe spinlock protection |
| 87 | +- Fallback to software timers when hardware timeout is unavailable |
| 88 | + |
| 89 | +## Migration Guide |
| 90 | + |
| 91 | +### For BSP Developers |
| 92 | + |
| 93 | +**Old hwtimer approach:** |
| 94 | +```c |
| 95 | +static const struct rt_hwtimer_ops my_ops = { ... }; |
| 96 | +static struct rt_hwtimer_device my_device; |
| 97 | +rt_device_hwtimer_register(&my_device, "timer0", RT_NULL); |
| 98 | +``` |
| 99 | +
|
| 100 | +**New clock_time approach:** |
| 101 | +```c |
| 102 | +static const struct rt_clock_time_ops my_ops = { |
| 103 | + .get_freq = my_get_freq, |
| 104 | + .get_counter = my_get_counter, |
| 105 | + .set_timeout = my_set_timeout, |
| 106 | +}; |
| 107 | +static struct rt_clock_time_device my_device; |
| 108 | +my_device.ops = &my_ops; |
| 109 | +rt_clock_time_device_register(&my_device, "timer0", |
| 110 | + RT_CLOCK_TIME_CAP_CLOCKSOURCE | RT_CLOCK_TIME_CAP_CLOCKEVENT); |
| 111 | +``` |
| 112 | + |
| 113 | +### For Application Developers |
| 114 | + |
| 115 | +**Old cputime/ktime APIs** still work when compatibility layers are enabled: |
| 116 | +- `clock_cpu_gettime()` → `rt_clock_time_getcnt()` |
| 117 | +- `rt_ktime_boottime_get_ns()` → `rt_clock_time_boottime_ns()` |
| 118 | +- `rt_ktime_hrtimer_start()` → `rt_clock_hrtimer_start()` |
| 119 | + |
| 120 | +**Recommended new APIs:** |
| 121 | +```c |
| 122 | +/* Get time information */ |
| 123 | +rt_uint64_t freq = rt_clock_time_getfreq(); |
| 124 | +rt_uint64_t cnt = rt_clock_time_getcnt(); |
| 125 | + |
| 126 | +/* High-precision delays */ |
| 127 | +rt_clock_udelay(100); /* 100 microseconds */ |
| 128 | +rt_clock_mdelay(10); /* 10 milliseconds */ |
| 129 | + |
| 130 | +/* High-resolution timers */ |
| 131 | +struct rt_clock_hrtimer timer; |
| 132 | +rt_clock_hrtimer_init(&timer, "my_timer", RT_TIMER_FLAG_ONE_SHOT, |
| 133 | + callback, param); |
| 134 | +rt_clock_hrtimer_start(&timer, delay_cnt); |
| 135 | +``` |
| 136 | +
|
| 137 | +## Compatibility Layers |
| 138 | +
|
| 139 | +Three compatibility layers are provided via Kconfig: |
| 140 | +
|
| 141 | +1. **RT_CLOCK_TIME_COMPAT_KTIME**: Enables ktime API compatibility |
| 142 | +2. **RT_CLOCK_TIME_COMPAT_CPUTIME**: Enables cputime API compatibility |
| 143 | +3. **RT_CLOCK_TIME_COMPAT_HWTIMER**: Enables hwtimer device API compatibility |
| 144 | +
|
| 145 | +These allow gradual migration without breaking existing code. |
| 146 | +
|
| 147 | +## File Structure |
| 148 | +
|
| 149 | +``` |
| 150 | +components/drivers/clock_time/ |
| 151 | +├── Kconfig # Configuration options |
| 152 | +├── SConscript # Build script |
| 153 | +├── src/ |
| 154 | +│ ├── clock_time.c # Core device management |
| 155 | +│ ├── hrtimer.c # High-resolution timer implementation |
| 156 | +│ ├── clock_time_tick.c # Tick-based fallback adapter |
| 157 | +│ ├── ktime_compat.c # ktime compatibility layer |
| 158 | +│ └── cputime_compat.c # cputime compatibility layer |
| 159 | +└── include/drivers/ |
| 160 | + └── clock_time.h # Public API header |
| 161 | +``` |
| 162 | +
|
| 163 | +## Testing Status |
| 164 | +
|
| 165 | +- [x] Basic compilation verified |
| 166 | +- [ ] BSP integration examples created |
| 167 | +- [ ] QEMU runtime testing |
| 168 | +- [ ] CI build verification |
| 169 | +- [ ] Performance benchmarking |
| 170 | +
|
| 171 | +## Known Limitations |
| 172 | +
|
| 173 | +1. **Type width**: `unsigned long` is 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. |
| 174 | +
|
| 175 | +2. **Fallback mode**: When no hardware clockevent is available, the system falls back to software timers (tick-based). This provides lower precision but ensures functionality. |
| 176 | +
|
| 177 | +3. **Migration timeline**: The old subsystems are marked as deprecated but not removed to allow time for migration. |
| 178 | +
|
| 179 | +## Future Work |
| 180 | +
|
| 181 | +1. **Architecture-specific optimizations**: Add optimized adapters for common architectures (ARM Generic Timer, RISC-V timer, etc.) |
| 182 | +2. **Power management integration**: Better support for low-power modes with clock gating |
| 183 | +3. **Advanced scheduling**: Consider red-black tree for timer scheduling in scenarios with many concurrent timers |
| 184 | +4. **Complete migration**: Remove deprecated subsystems after all BSPs migrate |
| 185 | +
|
| 186 | +## Documentation |
| 187 | +
|
| 188 | +- [English Documentation](../../documentation/6.components/device-driver/clock_time.md) |
| 189 | +- [Chinese Documentation](../../documentation/6.components/device-driver/clock_time_zh.md) |
| 190 | +
|
| 191 | +## Contributing |
| 192 | +
|
| 193 | +When contributing to clock_time: |
| 194 | +
|
| 195 | +1. Maintain backward compatibility with existing APIs |
| 196 | +2. Add tests for new functionality |
| 197 | +3. Update documentation |
| 198 | +4. Follow RT-Thread coding style |
| 199 | +5. Consider both MCU and MPU use cases |
| 200 | +
|
| 201 | +## References |
| 202 | +
|
| 203 | +- Issue: [Feature] 对 hwtimer/ktime/cputime 进行整体重构 |
| 204 | +- Design discussion in issue comments |
| 205 | +- POSIX clock APIs: clock_gettime(2), clock_settime(2) |
| 206 | +- Linux clocksource/clockevent framework |
0 commit comments