Skip to content

Commit 32587a3

Browse files
CopilotBernardXiong
andcommitted
[clock_time] Add unified clock_time subsystem with documentation
- Created new clock_time subsystem consolidating hwtimer/ktime/cputime - Implemented clock_time device abstraction with ops structure - Added high-resolution timer (hrtimer) implementation - Created compatibility layers for legacy APIs - Added comprehensive English and Chinese documentation - Updated Kconfig to mark old subsystems as deprecated Co-authored-by: BernardXiong <[email protected]>
1 parent 105820c commit 32587a3

File tree

14 files changed

+1976
-3
lines changed

14 files changed

+1976
-3
lines changed

components/drivers/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ rsource "ipc/Kconfig"
55

66
rsource "serial/Kconfig"
77
rsource "can/Kconfig"
8+
rsource "clock_time/Kconfig"
89
rsource "cputime/Kconfig"
910
rsource "i2c/Kconfig"
1011
rsource "phy/Kconfig"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
menuconfig RT_USING_CLOCK_TIME
2+
bool "Using unified clock_time subsystem"
3+
default n
4+
help
5+
Enable the unified clock_time subsystem which consolidates
6+
hwtimer, ktime, and cputime into a single coherent framework.
7+
8+
This subsystem provides:
9+
- Clocksource: Free-running counter for timekeeping
10+
- Clockevent: Programmable timeout events
11+
- High-resolution timers (hrtimer)
12+
- POSIX clock support
13+
- Boottime tracking
14+
15+
if RT_USING_CLOCK_TIME
16+
config RT_CLOCK_TIME_COMPAT_KTIME
17+
bool "Enable compatibility layer for ktime APIs"
18+
default y
19+
help
20+
Provides backward compatibility wrappers for legacy ktime APIs.
21+
Enable this if existing code uses rt_ktime_* functions.
22+
23+
config RT_CLOCK_TIME_COMPAT_CPUTIME
24+
bool "Enable compatibility layer for cputime APIs"
25+
default y
26+
help
27+
Provides backward compatibility wrappers for legacy cputime APIs.
28+
Enable this if existing code uses clock_cpu_* or rt_cputimer_* functions.
29+
30+
config RT_CLOCK_TIME_COMPAT_HWTIMER
31+
bool "Enable compatibility layer for hwtimer device APIs"
32+
default y
33+
help
34+
Provides backward compatibility for legacy hwtimer device APIs.
35+
Enable this if BSP drivers use rt_device_hwtimer_* functions.
36+
endif
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from building import *
2+
3+
cwd = GetCurrentDir()
4+
5+
src = Split('''
6+
src/clock_time.c
7+
src/hrtimer.c
8+
src/clock_time_tick.c
9+
''')
10+
11+
if GetDepend('RT_CLOCK_TIME_COMPAT_KTIME'):
12+
src += ['src/ktime_compat.c']
13+
14+
if GetDepend('RT_CLOCK_TIME_COMPAT_CPUTIME'):
15+
src += ['src/cputime_compat.c']
16+
17+
CPPPATH = [cwd + '/include', cwd + '/../include']
18+
19+
LOCAL_CCFLAGS = ''
20+
if rtconfig.PLATFORM in ['gcc', 'armclang']:
21+
LOCAL_CCFLAGS += ' -std=gnu99'
22+
elif rtconfig.PLATFORM in ['armcc']:
23+
LOCAL_CCFLAGS += ' --c99 --gnu'
24+
25+
group = DefineGroup('DeviceDrivers', src, depend=['RT_USING_CLOCK_TIME'],
26+
CPPPATH=CPPPATH, LOCAL_CCFLAGS=LOCAL_CCFLAGS)
27+
28+
Return('group')
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copyright (c) 2006-2024, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2024-12-04 RT-Thread Unified clock_time subsystem - core implementation
9+
*/
10+
11+
#include <rtdevice.h>
12+
#include <rthw.h>
13+
14+
#define DBG_TAG "clock_time"
15+
#define DBG_LVL DBG_INFO
16+
#include <rtdbg.h>
17+
18+
static struct rt_clock_time_device *_default_clock_time = RT_NULL;
19+
20+
rt_err_t rt_clock_time_device_register(struct rt_clock_time_device *dev,
21+
const char *name,
22+
rt_uint8_t caps)
23+
{
24+
RT_ASSERT(dev != RT_NULL);
25+
RT_ASSERT(dev->ops != RT_NULL);
26+
RT_ASSERT(name != RT_NULL);
27+
28+
/* Validate capability requirements */
29+
if (caps & RT_CLOCK_TIME_CAP_CLOCKSOURCE)
30+
{
31+
RT_ASSERT(dev->ops->get_freq != RT_NULL);
32+
RT_ASSERT(dev->ops->get_counter != RT_NULL);
33+
}
34+
35+
if (caps & RT_CLOCK_TIME_CAP_CLOCKEVENT)
36+
{
37+
RT_ASSERT(dev->ops->set_timeout != RT_NULL);
38+
}
39+
40+
dev->caps = caps;
41+
dev->parent.type = RT_Device_Class_Timer;
42+
dev->parent.rx_indicate = RT_NULL;
43+
dev->parent.tx_complete = RT_NULL;
44+
dev->parent.user_data = RT_NULL;
45+
46+
/* Calculate resolution scale factor */
47+
if (dev->ops->get_freq)
48+
{
49+
rt_uint64_t freq = dev->ops->get_freq();
50+
/* res_scale = RT_CLOCK_TIME_RESMUL for nanosecond precision */
51+
dev->res_scale = RT_CLOCK_TIME_RESMUL;
52+
}
53+
54+
/* Register as a device */
55+
rt_err_t result = rt_device_register(&dev->parent, name,
56+
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
57+
58+
if (result == RT_EOK)
59+
{
60+
LOG_I("Clock time device '%s' registered (caps: 0x%02x)", name, caps);
61+
62+
/* Set as default if none exists */
63+
if (_default_clock_time == RT_NULL)
64+
{
65+
_default_clock_time = dev;
66+
LOG_I("Set '%s' as default clock time device", name);
67+
}
68+
}
69+
70+
return result;
71+
}
72+
73+
rt_err_t rt_clock_time_set_default(struct rt_clock_time_device *dev)
74+
{
75+
RT_ASSERT(dev != RT_NULL);
76+
77+
_default_clock_time = dev;
78+
LOG_I("Default clock time device set to '%s'", dev->parent.parent.name);
79+
80+
return RT_EOK;
81+
}
82+
83+
struct rt_clock_time_device *rt_clock_time_get_default(void)
84+
{
85+
return _default_clock_time;
86+
}
87+
88+
/* Clocksource APIs */
89+
90+
rt_uint64_t rt_clock_time_getres(void)
91+
{
92+
if (_default_clock_time == RT_NULL ||
93+
!(_default_clock_time->caps & RT_CLOCK_TIME_CAP_CLOCKSOURCE))
94+
{
95+
/* Fallback to tick-based resolution */
96+
return ((1000ULL * 1000 * 1000) * RT_CLOCK_TIME_RESMUL) / RT_TICK_PER_SECOND;
97+
}
98+
99+
rt_uint64_t freq = _default_clock_time->ops->get_freq();
100+
return ((1000ULL * 1000 * 1000) * RT_CLOCK_TIME_RESMUL) / freq;
101+
}
102+
103+
rt_uint64_t rt_clock_time_getfreq(void)
104+
{
105+
if (_default_clock_time == RT_NULL ||
106+
!(_default_clock_time->caps & RT_CLOCK_TIME_CAP_CLOCKSOURCE))
107+
{
108+
/* Fallback to tick frequency */
109+
return RT_TICK_PER_SECOND;
110+
}
111+
112+
return _default_clock_time->ops->get_freq();
113+
}
114+
115+
rt_uint64_t rt_clock_time_getcnt(void)
116+
{
117+
if (_default_clock_time == RT_NULL ||
118+
!(_default_clock_time->caps & RT_CLOCK_TIME_CAP_CLOCKSOURCE))
119+
{
120+
/* Fallback to tick counter */
121+
return rt_tick_get();
122+
}
123+
124+
return _default_clock_time->ops->get_counter();
125+
}
126+
127+
rt_err_t rt_clock_time_boottime_ns(struct timespec *ts)
128+
{
129+
RT_ASSERT(ts != RT_NULL);
130+
131+
rt_uint64_t cnt = rt_clock_time_getcnt();
132+
rt_uint64_t res = rt_clock_time_getres();
133+
rt_uint64_t ns = (cnt * res) / RT_CLOCK_TIME_RESMUL;
134+
135+
ts->tv_sec = ns / (1000ULL * 1000 * 1000);
136+
ts->tv_nsec = ns % (1000ULL * 1000 * 1000);
137+
138+
return RT_EOK;
139+
}
140+
141+
rt_err_t rt_clock_time_boottime_us(struct timeval *tv)
142+
{
143+
RT_ASSERT(tv != RT_NULL);
144+
145+
rt_uint64_t cnt = rt_clock_time_getcnt();
146+
rt_uint64_t res = rt_clock_time_getres();
147+
rt_uint64_t ns = (cnt * res) / RT_CLOCK_TIME_RESMUL;
148+
149+
tv->tv_sec = ns / (1000ULL * 1000 * 1000);
150+
tv->tv_usec = (ns % (1000ULL * 1000 * 1000)) / 1000;
151+
152+
return RT_EOK;
153+
}
154+
155+
rt_err_t rt_clock_time_boottime_s(time_t *t)
156+
{
157+
RT_ASSERT(t != RT_NULL);
158+
159+
rt_uint64_t cnt = rt_clock_time_getcnt();
160+
rt_uint64_t res = rt_clock_time_getres();
161+
rt_uint64_t ns = (cnt * res) / RT_CLOCK_TIME_RESMUL;
162+
163+
*t = ns / (1000ULL * 1000 * 1000);
164+
165+
return RT_EOK;
166+
}
167+
168+
/* Time conversion functions */
169+
170+
rt_uint64_t rt_clock_time_cnt_to_ns(rt_uint64_t cnt)
171+
{
172+
rt_uint64_t res = rt_clock_time_getres();
173+
return (cnt * res) / RT_CLOCK_TIME_RESMUL;
174+
}
175+
176+
rt_uint64_t rt_clock_time_cnt_to_us(rt_uint64_t cnt)
177+
{
178+
return rt_clock_time_cnt_to_ns(cnt) / 1000;
179+
}
180+
181+
rt_uint64_t rt_clock_time_cnt_to_ms(rt_uint64_t cnt)
182+
{
183+
return rt_clock_time_cnt_to_ns(cnt) / (1000 * 1000);
184+
}
185+
186+
rt_uint64_t rt_clock_time_ns_to_cnt(rt_uint64_t ns)
187+
{
188+
rt_uint64_t freq = rt_clock_time_getfreq();
189+
return (ns * freq) / (1000ULL * 1000 * 1000);
190+
}
191+
192+
rt_uint64_t rt_clock_time_us_to_cnt(rt_uint64_t us)
193+
{
194+
return rt_clock_time_ns_to_cnt(us * 1000);
195+
}
196+
197+
rt_uint64_t rt_clock_time_ms_to_cnt(rt_uint64_t ms)
198+
{
199+
return rt_clock_time_ns_to_cnt(ms * 1000 * 1000);
200+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2006-2024, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2024-12-04 RT-Thread Tick-based clock_time adapter (fallback)
9+
*/
10+
11+
#include <rtdevice.h>
12+
13+
/**
14+
* @brief Tick-based fallback clock_time implementation
15+
*
16+
* This provides a basic clock_time implementation using RT-Thread's
17+
* tick counter. It should be overridden by BSP-specific implementations
18+
* that provide higher resolution hardware timers.
19+
*/
20+
21+
static rt_uint64_t _tick_get_freq(void)
22+
{
23+
return RT_TICK_PER_SECOND;
24+
}
25+
26+
static rt_uint64_t _tick_get_counter(void)
27+
{
28+
return rt_tick_get();
29+
}
30+
31+
static const struct rt_clock_time_ops _tick_clock_ops =
32+
{
33+
.get_freq = _tick_get_freq,
34+
.get_counter = _tick_get_counter,
35+
.set_timeout = RT_NULL, /* No hardware timeout support */
36+
};
37+
38+
static struct rt_clock_time_device _tick_clock_device;
39+
40+
/**
41+
* @brief Initialize tick-based clock_time device
42+
*
43+
* This is automatically called if no other clock_time device is registered.
44+
*/
45+
int rt_clock_time_tick_init(void)
46+
{
47+
_tick_clock_device.ops = &_tick_clock_ops;
48+
49+
return rt_clock_time_device_register(&_tick_clock_device,
50+
"tick_clock",
51+
RT_CLOCK_TIME_CAP_CLOCKSOURCE);
52+
}
53+
INIT_DEVICE_EXPORT(rt_clock_time_tick_init);

0 commit comments

Comments
 (0)