1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
|
# 时钟时间设备
## 简介
`clock_time` 子系统为 RT-Thread 提供了统一的时间管理框架,将原有的 `hwtimer`、`ktime` 和 `cputime` 子系统的功能整合到一个一致的 API 中。
### 主要特性
- **时钟源(Clocksource)**:用于计时和时间戳的自由运行计数器
- **时钟事件(Clockevent)**:可编程超时事件,用于高精度定时
- **高分辨率定时器(hrtimer)**:采用链表调度的高效定时器管理
- **POSIX 时钟支持**:与标准 POSIX 时钟 API 兼容
- **启动时间追踪**:记录系统启动以来的单调时间
- **向后兼容**:为旧 API 提供兼容层
### 设计理念
clock_time 子系统遵循 RT-Thread 的 C-OOP(C 语言中的面向对象编程)设计模式:
1. **统一设备抽象**:`rt_clock_time_device` 封装硬件定时器能力
2. **操作结构**:`rt_clock_time_ops` 定义硬件特定操作
3. **能力标志**:明确指示时钟源和时钟事件支持
4. **灵活集成**:同时适用于 MCU 和 MPU 平台
## 架构
```
┌─────────────────────────────────────────────────────────┐
│ 应用层 │
│ (POSIX API、延时、计时、高分辨率定时器) │
└──────────────────┬──────────────────────────────────────┘
│
┌──────────────────▼──────────────────────────────────────┐
│ clock_time 子系统 │
│ ┌─────────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ 时钟源 │ │ 启动时间 │ │ 高分辨率定时器 │ │
│ └─────────────┘ └──────────┘ └──────────────────┘ │
│ ┌─────────────┐ ┌──────────────────────────────┐ │
│ │ 时钟事件 │ │ 兼容层 │ │
│ └─────────────┘ └──────────────────────────────┘ │
└──────────────────┬──────────────────────────────────────┘
│
┌──────────────────▼──────────────────────────────────────┐
│ 硬件定时器抽象 │
│ (rt_clock_time_device + ops) │
└──────────────────┬──────────────────────────────────────┘
│
┌──────────────────▼──────────────────────────────────────┐
│ BSP 定时器驱动 │
│ (SysTick、ARM 架构定时器、RISC-V 定时器等) │
└─────────────────────────────────────────────────────────┘
```
## 使用方法
### 注册时钟时间设备
BSP 驱动应实现 `rt_clock_time_ops` 并注册设备:
```c
#include <rtdevice.h>
static rt_uint64_t my_timer_get_freq(void)
{
return 1000000; /* 1MHz 定时器 */
}
static rt_uint64_t my_timer_get_counter(void)
{
return MY_TIMER->CNT; /* 读取硬件计数器 */
}
static rt_err_t my_timer_set_timeout(rt_uint64_t delta)
{
if (delta == 0)
{
/* 取消超时 */
MY_TIMER->CR &= ~TIMER_ENABLE;
return RT_EOK;
}
MY_TIMER->CMP = MY_TIMER->CNT + delta;
MY_TIMER->CR |= TIMER_ENABLE | TIMER_INT_ENABLE;
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_clock_device;
int my_timer_init(void)
{
/* 初始化硬件定时器 */
my_clock_device.ops = &my_timer_ops;
/* 注册设备,同时支持时钟源和时钟事件能力 */
rt_clock_time_device_register(&my_clock_device,
"hw_timer",
RT_CLOCK_TIME_CAP_CLOCKSOURCE |
RT_CLOCK_TIME_CAP_CLOCKEVENT);
return 0;
}
INIT_DEVICE_EXPORT(my_timer_init);
/* 定时器中断服务程序应调用 rt_clock_hrtimer_process() */
void MY_TIMER_IRQHandler(void)
{
/* 清除中断标志 */
MY_TIMER->SR = 0;
/* 处理 hrtimer 超时 */
rt_clock_hrtimer_process();
}
```
### 使用时钟源 API
#### 获取时间信息
```c
/* 获取时钟分辨率(以纳秒为单位,按 RT_CLOCK_TIME_RESMUL 缩放)*/
rt_uint64_t res = rt_clock_time_getres();
/* 获取时钟频率(Hz)*/
rt_uint64_t freq = rt_clock_time_getfreq();
/* 获取当前计数器值 */
rt_uint64_t cnt = rt_clock_time_getcnt();
```
#### 获取启动时间
```c
struct timespec ts;
rt_clock_time_boottime_ns(&ts);
rt_kprintf("启动时间: %d.%09d 秒\n", ts.tv_sec, ts.tv_nsec);
struct timeval tv;
rt_clock_time_boottime_us(&tv);
time_t t;
rt_clock_time_boottime_s(&t);
```
#### 时间转换
```c
rt_uint64_t cnt = 1000000; /* 计数器滴答 */
/* 转换为时间单位 */
rt_uint64_t ns = rt_clock_time_cnt_to_ns(cnt);
rt_uint64_t us = rt_clock_time_cnt_to_us(cnt);
rt_uint64_t ms = rt_clock_time_cnt_to_ms(cnt);
/* 从时间单位转换 */
cnt = rt_clock_time_ns_to_cnt(1000000); /* 1ms(纳秒)*/
cnt = rt_clock_time_us_to_cnt(1000); /* 1ms(微秒)*/
cnt = rt_clock_time_ms_to_cnt(1); /* 1ms */
```
### 使用高分辨率定时器
#### 创建并启动定时器
```c
#include <rtdevice.h>
static void timeout_callback(void *param)
{
rt_kprintf("定时器超时!\n");
}
void hrtimer_example(void)
{
struct rt_clock_hrtimer timer;
/* 初始化定时器 */
rt_clock_hrtimer_init(&timer, "my_timer",
RT_TIMER_FLAG_ONE_SHOT,
timeout_callback,
RT_NULL);
/* 以 1ms 延迟启动定时器 */
rt_uint64_t delay_cnt = rt_clock_time_ms_to_cnt(1);
rt_clock_hrtimer_start(&timer, delay_cnt);
/* ... */
/* 如果需要可以停止定时器 */
rt_clock_hrtimer_stop(&timer);
/* 清理 */
rt_clock_hrtimer_detach(&timer);
}
```
#### 周期定时器
```c
static void periodic_callback(void *param)
{
rt_kprintf("周期滴答\n");
}
void periodic_timer_example(void)
{
struct rt_clock_hrtimer timer;
rt_clock_hrtimer_init(&timer, "periodic",
RT_TIMER_FLAG_PERIODIC,
periodic_callback,
RT_NULL);
/* 以 100ms 周期启动 */
rt_uint64_t period_cnt = rt_clock_time_ms_to_cnt(100);
rt_clock_hrtimer_start(&timer, period_cnt);
}
```
### 高精度延时
```c
/* 纳秒延时 */
rt_clock_ndelay(1000); /* 1 微秒 */
/* 微秒延时 */
rt_clock_udelay(1000); /* 1 毫秒 */
/* 毫秒延时 */
rt_clock_mdelay(100); /* 100 毫秒 */
/* 使用自定义定时器进行延时 */
struct rt_clock_hrtimer timer;
rt_clock_hrtimer_mdelay(&timer, 50); /* 50ms 延时 */
```
## 迁移指南
### 从 ktime 迁移
当启用 `RT_CLOCK_TIME_COMPAT_KTIME` 时,clock_time 子系统提供直接的 API 兼容性:
| 旧 ktime API | 新 clock_time API |
|--------------|-------------------|
| `rt_ktime_boottime_get_ns()` | `rt_clock_time_boottime_ns()` |
| `rt_ktime_cputimer_getres()` | `rt_clock_time_getres()` |
| `rt_ktime_cputimer_getcnt()` | `rt_clock_time_getcnt()` |
| `rt_ktime_hrtimer_init()` | `rt_clock_hrtimer_init()` |
| `rt_ktime_hrtimer_start()` | `rt_clock_hrtimer_start()` |
### 从 cputime 迁移
当启用 `RT_CLOCK_TIME_COMPAT_CPUTIME` 时:
| 旧 cputime API | 新 clock_time API |
|----------------|-------------------|
| `clock_cpu_gettime()` | `rt_clock_time_getcnt()` |
| `clock_cpu_getres()` | `rt_clock_time_getres()` |
| `rt_cputime_sleep()` | `rt_clock_mdelay()` 或使用 hrtimer |
| `rt_cputime_udelay()` | `rt_clock_udelay()` |
### 从 hwtimer 迁移
硬件定时器设备应迁移到新的 clock_time 设备模型:
**旧 hwtimer 方式:**
```c
static const struct rt_hwtimer_ops my_ops = { ... };
static struct rt_hwtimer_device my_device;
my_device.ops = &my_ops;
rt_device_hwtimer_register(&my_device, "timer0", RT_NULL);
```
**新 clock_time 方式:**
```c
static const struct rt_clock_time_ops my_ops = { ... };
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);
```
## 配置
### Kconfig 选项
```
RT_USING_CLOCK_TIME - 启用 clock_time 子系统
RT_CLOCK_TIME_COMPAT_KTIME - 启用 ktime 兼容层
RT_CLOCK_TIME_COMPAT_CPUTIME - 启用 cputime 兼容层
RT_CLOCK_TIME_COMPAT_HWTIMER - 启用 hwtimer 兼容层
```
### 典型配置
对于新项目:
```
CONFIG_RT_USING_CLOCK_TIME=y
# 不需要兼容层
```
对于迁移项目:
```
CONFIG_RT_USING_CLOCK_TIME=y
CONFIG_RT_CLOCK_TIME_COMPAT_KTIME=y
CONFIG_RT_CLOCK_TIME_COMPAT_CPUTIME=y
CONFIG_RT_CLOCK_TIME_COMPAT_HWTIMER=y
```
## 最佳实践
### MCU 场景
1. **使用 SysTick 或类似定时器**:对于基本计时,SysTick 提供足够的分辨率
2. **硬件定时器提供精度**:使用专用硬件定时器实现微秒级精度
3. **考虑功耗**:在低功耗应用中最小化定时器唤醒
### MPU 场景
1. **架构定时器**:使用 ARM 通用定时器或 RISC-V 定时器以获得最佳性能
2. **SMP 安全**:hrtimer 实现使用自旋锁支持 SMP 系统
3. **高频率源**:MPU 可以处理更高频率的定时器(MHz 范围)
### 通用准则
1. **单一默认设备**:注册一个主要的 clock_time 设备作为系统默认
2. **中断服务程序效率**:在 ISR 中保持 `rt_clock_hrtimer_process()` 调用简短
3. **分辨率与开销**:更高分辨率的定时器有更高的开销
4. **回退支持**:基于滴答的回退确保即使没有硬件定时器也能正常工作
## API 参考
完整的 API 文档请参阅 `/components/drivers/include/drivers/clock_time.h`。
## 示例
完整示例可在以下位置找到:
- `/examples/clock_time/` - 基本使用示例
- BSP 定时器驱动实现供参考
## 故障排除
### 定时器不触发
- 验证硬件定时器配置正确
- 检查 ISR 是否调用 `rt_clock_hrtimer_process()`
- 确保定时器中断已启用
### 精度差
- 验证定时器频率适合您的用例
- 检查中断延迟问题
- 考虑使用更高频率的定时器
### 兼容性问题
- 在 Kconfig 中启用适当的兼容层
- 检查迁移中的 API 签名更改
- 验证 BSP 特定的定时器实现
## 另请参阅
- [定时器管理](timer.md)
- [实时时钟(RTC)](rtc.md)
- [设备驱动框架](framework.md)
|