Skip to content

Commit ed41d9e

Browse files
committed
fix: make rt_tick_t 64-bit on ARCH_CPU_64BIT and improve clock time precision
Use clock source frequency instead of scaled resolution when converting between counter ticks and nanoseconds in boottime, clock_gettime, POSIX timers, and hrtimer paths. Add rt_muldiv_u64() and rt_muldiv_u32() to avoid precision loss in these conversions. On ARCH_CPU_64BIT, rt_tick_t and RT_TICK_MAX are widened to 64 bits so long-running systems do not wrap counter values used by boottime and timer APIs. Port the original ktime fixes to the clock_time API, remove rt_clock_hrtimer_getres(), and keep soft-timer fallback rounding in _hrtimer_cnt_to_tick() so sub-tick timeouts still schedule at least one OS tick.
1 parent 6fc3e18 commit ed41d9e

9 files changed

Lines changed: 296 additions & 126 deletions

File tree

‎bsp/rockchip/dm/hwtimer/clock_timer-rockchip_timer.c‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,16 +359,11 @@ static const struct rk_timer_data rk3399_timer_data =
359359

360360
#ifdef RT_USING_CLOCK_TIME
361361

362-
uint64_t rt_clock_hrtimer_getfrq(void)
362+
rt_uint64_t rt_clock_hrtimer_getfrq(void)
363363
{
364364
return OSC_HZ;
365365
}
366366

367-
uint64_t rt_clock_hrtimer_getres(void)
368-
{
369-
return ((1000UL * 1000 * 1000) * RT_CLOCK_TIME_RESMUL) / OSC_HZ;
370-
}
371-
372367
/**
373368
* @brief set the timeout function for hrtimer framework
374369
*
@@ -377,7 +372,7 @@ uint64_t rt_clock_hrtimer_getres(void)
377372
* @param cnt the count of timer dealy
378373
* @return rt_err_t 0 forever
379374
*/
380-
rt_err_t rt_clock_hrtimer_settimeout(unsigned long cnt)
375+
rt_err_t rt_clock_hrtimer_settimeout(rt_uint64_t cnt)
381376
{
382377
struct hrt_timer *timer = &_timer0;
383378
struct rk_timer *time = timer->timer;

‎components/drivers/clock_time/clock_boottime.c‎

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,70 +9,63 @@
99
*/
1010

1111
#include <drivers/clock_time.h>
12+
#include <sys/time.h>
1213

1314
rt_err_t rt_clock_boottime_get_us(struct timeval *tv)
1415
{
15-
rt_uint64_t cnt;
16-
rt_uint64_t res;
17-
rt_uint64_t ns;
16+
rt_tick_t cnt;
17+
rt_uint32_t freq;
1818

1919
RT_ASSERT(tv != RT_NULL);
2020

21-
cnt = rt_clock_time_get_counter();
22-
res = rt_clock_time_get_res_scaled();
23-
if (res == 0)
21+
cnt = (rt_tick_t)rt_clock_time_get_counter();
22+
freq = (rt_uint32_t)rt_clock_time_get_freq();
23+
if (freq == 0)
2424
{
2525
return -RT_ERROR;
2626
}
2727

28-
ns = (cnt * res) / RT_CLOCK_TIME_RESMUL;
29-
30-
tv->tv_sec = ns / (1000ULL * 1000 * 1000);
31-
tv->tv_usec = (ns % (1000ULL * 1000 * 1000)) / 1000;
28+
tv->tv_sec = (time_t)(cnt / freq);
29+
tv->tv_usec = rt_muldiv_u32((rt_uint32_t)(cnt % freq), MICROSECOND_PER_SECOND, freq, NULL);
3230

3331
return RT_EOK;
3432
}
3533

3634
rt_err_t rt_clock_boottime_get_s(time_t *t)
3735
{
38-
rt_uint64_t cnt;
39-
rt_uint64_t res;
40-
rt_uint64_t ns;
36+
rt_tick_t cnt;
37+
rt_uint32_t freq;
4138

4239
RT_ASSERT(t != RT_NULL);
4340

44-
cnt = rt_clock_time_get_counter();
45-
res = rt_clock_time_get_res_scaled();
46-
if (res == 0)
41+
cnt = (rt_tick_t)rt_clock_time_get_counter();
42+
freq = (rt_uint32_t)rt_clock_time_get_freq();
43+
if (freq == 0)
4744
{
4845
return -RT_ERROR;
4946
}
5047

51-
ns = (cnt * res) / RT_CLOCK_TIME_RESMUL;
52-
*t = ns / (1000ULL * 1000 * 1000);
48+
*t = (time_t)(cnt / freq);
5349

5450
return RT_EOK;
5551
}
5652

5753
rt_err_t rt_clock_boottime_get_ns(struct timespec *ts)
5854
{
59-
rt_uint64_t cnt;
60-
rt_uint64_t res;
61-
rt_uint64_t ns;
55+
rt_tick_t cnt;
56+
rt_uint32_t freq;
6257

6358
RT_ASSERT(ts != RT_NULL);
6459

65-
cnt = rt_clock_time_get_counter();
66-
res = rt_clock_time_get_res_scaled();
67-
if (res == 0)
60+
cnt = (rt_tick_t)rt_clock_time_get_counter();
61+
freq = (rt_uint32_t)rt_clock_time_get_freq();
62+
if (freq == 0)
6863
{
6964
return -RT_ERROR;
7065
}
7166

72-
ns = (cnt * res) / RT_CLOCK_TIME_RESMUL;
73-
74-
ts->tv_sec = ns / (1000ULL * 1000 * 1000);
75-
ts->tv_nsec = ns % (1000ULL * 1000 * 1000);
67+
ts->tv_sec = (time_t)(cnt / freq);
68+
ts->tv_nsec = rt_muldiv_u32((rt_uint32_t)(cnt % freq), NANOSECOND_PER_SECOND, freq, NULL);
7669

7770
return RT_EOK;
7871
}

‎components/drivers/clock_time/clock_hrtimer.c‎

Lines changed: 40 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <rtdevice.h>
1212
#include <rthw.h>
1313
#include <rtthread.h>
14+
#include <sys/time.h>
1415

1516
#include <drivers/clock_time.h>
1617

@@ -20,12 +21,6 @@
2021

2122
#define CLOCK_TIME_NSEC_PER_SEC (1000000000ULL)
2223

23-
#ifdef ARCH_CPU_64BIT
24-
#define _HRTIMER_MAX_CNT UINT64_MAX
25-
#else
26-
#define _HRTIMER_MAX_CNT UINT32_MAX
27-
#endif
28-
2924
static rt_list_t _timer_list = RT_LIST_OBJECT_INIT(_timer_list);
3025
static RT_DEFINE_SPINLOCK(_spinlock);
3126

@@ -34,57 +29,51 @@ rt_inline rt_clock_hrtimer_t _first_hrtimer(void)
3429
return rt_list_isempty(&_timer_list) ? RT_NULL : rt_list_first_entry(&_timer_list, struct rt_clock_hrtimer, node);
3530
}
3631

37-
rt_inline unsigned long _clock_time_get_cnt(void)
32+
rt_inline rt_tick_t _clock_time_get_cnt(void)
3833
{
39-
return rt_clock_time_get_counter();
34+
return (rt_tick_t)rt_clock_time_get_counter();
4035
}
4136

42-
rt_inline rt_bool_t _cnt_before(unsigned long a, unsigned long b)
37+
rt_inline rt_bool_t _cnt_before(rt_tick_t a, rt_tick_t b)
4338
{
4439
return ((rt_base_t)(a - b)) < 0;
4540
}
4641

47-
rt_inline rt_bool_t _cnt_after(unsigned long a, unsigned long b)
42+
rt_inline rt_bool_t _cnt_after(rt_tick_t a, rt_tick_t b)
4843
{
4944
return _cnt_before(b, a);
5045
}
5146

52-
rt_weak rt_uint64_t rt_clock_hrtimer_getres(void)
53-
{
54-
return rt_clock_time_get_event_res_scaled();
55-
}
56-
57-
rt_weak unsigned long rt_clock_hrtimer_getfrq(void)
47+
rt_weak rt_uint64_t rt_clock_hrtimer_getfrq(void)
5848
{
59-
return (unsigned long)rt_clock_time_get_event_freq();
49+
return rt_clock_time_get_event_freq();
6050
}
6151

62-
static rt_tick_t _hrtimer_cnt_to_tick(unsigned long cnt)
52+
static rt_tick_t _hrtimer_cnt_to_tick(rt_uint64_t cnt)
6353
{
64-
rt_uint64_t res = rt_clock_hrtimer_getres();
65-
rt_uint64_t ns;
54+
rt_uint64_t freq = rt_clock_hrtimer_getfrq();
55+
rt_uint64_t rem = 0;
56+
rt_uint64_t tick;
6657

67-
if (res == 0)
58+
if (freq == 0)
6859
{
6960
return 0;
7061
}
7162

72-
ns = ((rt_uint64_t)cnt * res) / RT_CLOCK_TIME_RESMUL;
73-
if (ns == 0)
63+
tick = rt_muldiv_u64(cnt, RT_TICK_PER_SECOND, freq, &rem);
64+
if (rem != 0)
7465
{
75-
return 1;
66+
tick += 1; /* round up so a non-zero cnt never collapses to a 0-tick timeout */
7667
}
77-
78-
ns = (ns * RT_TICK_PER_SECOND + CLOCK_TIME_NSEC_PER_SEC - 1) / CLOCK_TIME_NSEC_PER_SEC;
79-
if (ns == 0)
68+
if (tick == 0)
8069
{
81-
return 1;
70+
tick = 1; /* at least one tick */
8271
}
8372

84-
return (rt_tick_t)ns;
73+
return (rt_tick_t)tick;
8574
}
8675

87-
rt_weak rt_err_t rt_clock_hrtimer_settimeout(unsigned long cnt)
76+
rt_weak rt_err_t rt_clock_hrtimer_settimeout(rt_uint64_t cnt)
8877
{
8978
static rt_timer_t timer = RT_NULL;
9079
static struct rt_timer _sh_rtimer;
@@ -124,29 +113,18 @@ rt_weak rt_err_t rt_clock_hrtimer_settimeout(unsigned long cnt)
124113
return RT_EOK;
125114
}
126115

127-
static unsigned long _cnt_convert(unsigned long cnt)
116+
static rt_uint64_t _cnt_convert(rt_tick_t cnt)
128117
{
129-
unsigned long count;
130-
rt_uint64_t src_res;
131-
rt_uint64_t event_res;
132-
rt_uint64_t result;
133-
134-
count = cnt - _clock_time_get_cnt();
135-
if (count > (_HRTIMER_MAX_CNT / 2))
136-
{
137-
return 0;
138-
}
118+
rt_uint64_t rtn = 0;
119+
rt_tick_t count = cnt - _clock_time_get_cnt();
139120

140-
src_res = rt_clock_time_get_res_scaled();
141-
event_res = rt_clock_hrtimer_getres();
142-
if (src_res == 0 || event_res == 0)
121+
if (count > (RT_TICK_MAX / 2))
143122
{
144123
return 0;
145124
}
146125

147-
result = ((rt_uint64_t)count * src_res) / event_res;
148-
149-
return result == 0 ? 1 : (unsigned long)result;
126+
rtn = rt_muldiv_u64(count, rt_clock_hrtimer_getfrq(), rt_clock_time_get_freq(), NULL);
127+
return rtn == 0 ? 1 : rtn;
150128
}
151129

152130
static void _sleep_timeout(void *parameter)
@@ -177,7 +155,7 @@ static void _hrtimer_process_locked(void)
177155

178156
while ((timer = _first_hrtimer()) != RT_NULL)
179157
{
180-
unsigned long now = _clock_time_get_cnt();
158+
rt_tick_t now = _clock_time_get_cnt();
181159

182160
if (_cnt_before(now, timer->timeout_cnt))
183161
{
@@ -206,7 +184,7 @@ static void _hrtimer_process_locked(void)
206184
static void _set_next_timeout_locked(void)
207185
{
208186
rt_clock_hrtimer_t timer;
209-
rt_ubase_t next_timeout_cnt;
187+
rt_uint64_t next_timeout_cnt;
210188
rt_bool_t find_next;
211189

212190
do
@@ -258,12 +236,12 @@ void rt_clock_hrtimer_init(rt_clock_hrtimer_t timer,
258236
rt_completion_init(&timer->completion);
259237
}
260238

261-
rt_err_t rt_clock_hrtimer_start(rt_clock_hrtimer_t timer, unsigned long delay_cnt)
239+
rt_err_t rt_clock_hrtimer_start(rt_clock_hrtimer_t timer, rt_tick_t delay_cnt)
262240
{
263241
rt_base_t level;
264242

265243
RT_ASSERT(timer != RT_NULL);
266-
RT_ASSERT(delay_cnt < (_HRTIMER_MAX_CNT / 2));
244+
RT_ASSERT(delay_cnt < (RT_TICK_MAX / 2));
267245

268246
timer->delay_cnt = delay_cnt;
269247
timer->timeout_cnt = timer->delay_cnt + _clock_time_get_cnt();
@@ -317,13 +295,13 @@ rt_err_t rt_clock_hrtimer_control(rt_clock_hrtimer_t timer, int cmd, void *arg)
317295
switch (cmd)
318296
{
319297
case RT_TIMER_CTRL_GET_TIME:
320-
*(unsigned long *)arg = timer->delay_cnt;
298+
*(rt_tick_t *)arg = timer->delay_cnt;
321299
break;
322300

323301
case RT_TIMER_CTRL_SET_TIME:
324-
RT_ASSERT((*(unsigned long *)arg) < (_HRTIMER_MAX_CNT / 2));
325-
timer->delay_cnt = *(unsigned long *)arg;
326-
timer->timeout_cnt = *(unsigned long *)arg + _clock_time_get_cnt();
302+
RT_ASSERT((*(rt_tick_t *)arg) < (RT_TICK_MAX / 2));
303+
timer->delay_cnt = *(rt_tick_t *)arg;
304+
timer->timeout_cnt = *(rt_tick_t *)arg + _clock_time_get_cnt();
327305
break;
328306

329307
case RT_TIMER_CTRL_SET_ONESHOT:
@@ -346,7 +324,7 @@ rt_err_t rt_clock_hrtimer_control(rt_clock_hrtimer_t timer, int cmd, void *arg)
346324
break;
347325

348326
case RT_TIMER_CTRL_GET_REMAIN_TIME:
349-
*(unsigned long *)arg = timer->timeout_cnt;
327+
*(rt_tick_t *)arg = timer->timeout_cnt;
350328
break;
351329
case RT_TIMER_CTRL_GET_FUNC:
352330
if (arg != RT_NULL)
@@ -408,7 +386,7 @@ void rt_clock_hrtimer_delay_detach(struct rt_clock_hrtimer *timer)
408386
rt_clock_hrtimer_detach(timer);
409387
}
410388

411-
rt_err_t rt_clock_hrtimer_sleep(struct rt_clock_hrtimer *timer, unsigned long cnt)
389+
rt_err_t rt_clock_hrtimer_sleep(struct rt_clock_hrtimer *timer, rt_tick_t cnt)
412390
{
413391
rt_err_t err;
414392

@@ -430,23 +408,19 @@ rt_err_t rt_clock_hrtimer_sleep(struct rt_clock_hrtimer *timer, unsigned long cn
430408
return err;
431409
}
432410

433-
rt_err_t rt_clock_hrtimer_ndelay(struct rt_clock_hrtimer *timer, unsigned long ns)
411+
rt_err_t rt_clock_hrtimer_ndelay(struct rt_clock_hrtimer *timer, rt_uint64_t ns)
434412
{
435-
rt_uint64_t res = rt_clock_time_get_res_scaled();
436-
if (res == 0)
437-
{
438-
return -RT_ERROR;
439-
}
413+
rt_tick_t cputimer_tick = (rt_tick_t)rt_muldiv_u64(ns, rt_clock_time_get_freq(), NANOSECOND_PER_SECOND, NULL);
440414

441-
return rt_clock_hrtimer_sleep(timer, (ns * RT_CLOCK_TIME_RESMUL) / res);
415+
return rt_clock_hrtimer_sleep(timer, cputimer_tick);
442416
}
443417

444-
rt_err_t rt_clock_hrtimer_udelay(struct rt_clock_hrtimer *timer, unsigned long us)
418+
rt_err_t rt_clock_hrtimer_udelay(struct rt_clock_hrtimer *timer, rt_uint64_t us)
445419
{
446420
return rt_clock_hrtimer_ndelay(timer, us * 1000);
447421
}
448422

449-
rt_err_t rt_clock_hrtimer_mdelay(struct rt_clock_hrtimer *timer, unsigned long ms)
423+
rt_err_t rt_clock_hrtimer_mdelay(struct rt_clock_hrtimer *timer, rt_uint64_t ms)
450424
{
451425
return rt_clock_hrtimer_ndelay(timer, ms * 1000000);
452426
}

‎components/drivers/include/drivers/clock_time.h‎

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ struct rt_clock_hrtimer
112112
char name[RT_NAME_MAX];
113113
rt_list_t node;
114114
void *parameter;
115-
unsigned long delay_cnt;
116-
unsigned long timeout_cnt;
115+
rt_tick_t delay_cnt;
116+
rt_tick_t timeout_cnt;
117117
rt_err_t error;
118118
struct rt_completion completion;
119119
void (*timeout_func)(void *parameter);
@@ -145,17 +145,16 @@ rt_err_t rt_clock_boottime_get_us(struct timeval *tv);
145145
rt_err_t rt_clock_boottime_get_s(time_t *t);
146146
rt_err_t rt_clock_boottime_get_ns(struct timespec *ts);
147147

148-
rt_uint64_t rt_clock_hrtimer_getres(void);
149-
unsigned long rt_clock_hrtimer_getfrq(void);
150-
rt_err_t rt_clock_hrtimer_settimeout(unsigned long cnt);
148+
rt_uint64_t rt_clock_hrtimer_getfrq(void);
149+
rt_err_t rt_clock_hrtimer_settimeout(rt_uint64_t cnt);
151150
void rt_clock_hrtimer_process(void);
152151

153152
void rt_clock_hrtimer_init(rt_clock_hrtimer_t timer,
154153
const char *name,
155154
rt_uint8_t flag,
156155
void (*timeout)(void *parameter),
157156
void *parameter);
158-
rt_err_t rt_clock_hrtimer_start(rt_clock_hrtimer_t timer, unsigned long cnt);
157+
rt_err_t rt_clock_hrtimer_start(rt_clock_hrtimer_t timer, rt_tick_t cnt);
159158
rt_err_t rt_clock_hrtimer_stop(rt_clock_hrtimer_t timer);
160159
rt_err_t rt_clock_hrtimer_control(rt_clock_hrtimer_t timer, int cmd, void *arg);
161160
rt_err_t rt_clock_hrtimer_detach(rt_clock_hrtimer_t timer);
@@ -172,10 +171,10 @@ void rt_clock_hrtimer_delay_init(struct rt_clock_hrtimer *timer);
172171
void rt_clock_hrtimer_delay_detach(struct rt_clock_hrtimer *timer);
173172
void rt_clock_hrtimer_process(void);
174173

175-
rt_err_t rt_clock_hrtimer_sleep(struct rt_clock_hrtimer *timer, unsigned long cnt);
176-
rt_err_t rt_clock_hrtimer_ndelay(struct rt_clock_hrtimer *timer, unsigned long ns);
177-
rt_err_t rt_clock_hrtimer_udelay(struct rt_clock_hrtimer *timer, unsigned long us);
178-
rt_err_t rt_clock_hrtimer_mdelay(struct rt_clock_hrtimer *timer, unsigned long ms);
174+
rt_err_t rt_clock_hrtimer_sleep(struct rt_clock_hrtimer *timer, rt_tick_t cnt);
175+
rt_err_t rt_clock_hrtimer_ndelay(struct rt_clock_hrtimer *timer, rt_uint64_t ns);
176+
rt_err_t rt_clock_hrtimer_udelay(struct rt_clock_hrtimer *timer, rt_uint64_t us);
177+
rt_err_t rt_clock_hrtimer_mdelay(struct rt_clock_hrtimer *timer, rt_uint64_t ms);
179178

180179
#ifdef __cplusplus
181180
}

0 commit comments

Comments
 (0)