Skip to content

Commit 55a9dc5

Browse files
committed
[clock_time] Fix hrtimer wrap handling
1 parent a301a3f commit 55a9dc5

1 file changed

Lines changed: 60 additions & 7 deletions

File tree

components/drivers/clock_time/clock_hrtimer.c

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define DBG_LEVEL DBG_INFO
1919
#include <rtdbg.h>
2020

21+
#define CLOCK_TIME_NSEC_PER_SEC (1000000000ULL)
22+
2123
#ifdef ARCH_CPU_64BIT
2224
#define _HRTIMER_MAX_CNT UINT64_MAX
2325
#else
@@ -37,6 +39,16 @@ static unsigned long _clock_time_get_cnt(void)
3739
return rt_clock_time_get_counter();
3840
}
3941

42+
static rt_inline rt_bool_t _cnt_before(unsigned long a, unsigned long b)
43+
{
44+
return ((rt_base_t)(a - b)) < 0;
45+
}
46+
47+
static rt_inline rt_bool_t _cnt_after(unsigned long a, unsigned long b)
48+
{
49+
return _cnt_before(b, a);
50+
}
51+
4052
rt_weak rt_uint64_t rt_clock_hrtimer_getres(void)
4153
{
4254
return rt_clock_time_get_event_res_scaled();
@@ -47,10 +59,36 @@ rt_weak unsigned long rt_clock_hrtimer_getfrq(void)
4759
return (unsigned long)rt_clock_time_get_event_freq();
4860
}
4961

62+
static rt_tick_t _hrtimer_cnt_to_tick(unsigned long cnt)
63+
{
64+
rt_uint64_t res = rt_clock_hrtimer_getres();
65+
rt_uint64_t ns;
66+
67+
if (res == 0)
68+
{
69+
return 0;
70+
}
71+
72+
ns = ((rt_uint64_t)cnt * res) / RT_CLOCK_TIME_RESMUL;
73+
if (ns == 0)
74+
{
75+
return 1;
76+
}
77+
78+
ns = (ns * RT_TICK_PER_SECOND + CLOCK_TIME_NSEC_PER_SEC - 1) / CLOCK_TIME_NSEC_PER_SEC;
79+
if (ns == 0)
80+
{
81+
return 1;
82+
}
83+
84+
return (rt_tick_t)ns;
85+
}
86+
5087
rt_weak rt_err_t rt_clock_hrtimer_settimeout(unsigned long cnt)
5188
{
5289
static rt_timer_t timer = RT_NULL;
5390
static struct rt_timer _sh_rtimer;
91+
rt_tick_t tick;
5492

5593
RT_ASSERT(cnt > 0);
5694

@@ -59,15 +97,20 @@ rt_weak rt_err_t rt_clock_hrtimer_settimeout(unsigned long cnt)
5997
return RT_EOK;
6098
}
6199

100+
tick = _hrtimer_cnt_to_tick(cnt);
101+
if (tick == 0)
102+
{
103+
return -RT_ERROR;
104+
}
105+
62106
if (timer == RT_NULL)
63107
{
64108
timer = &_sh_rtimer;
65109
rt_timer_init(timer, "shrtimer", (void (*)(void *))rt_clock_hrtimer_process, RT_NULL,
66-
cnt, RT_TIMER_FLAG_ONE_SHOT);
110+
tick, RT_TIMER_FLAG_ONE_SHOT);
67111
}
68112
else
69113
{
70-
rt_tick_t tick = cnt;
71114
rt_timer_control(timer, RT_TIMER_CTRL_SET_TIME, &tick);
72115
rt_timer_control(timer, RT_TIMER_CTRL_SET_PARM, RT_NULL);
73116
}
@@ -118,7 +161,7 @@ static void _insert_timer_to_list_locked(rt_clock_hrtimer_t timer)
118161

119162
rt_list_for_each_entry(iter, &_timer_list, node)
120163
{
121-
if (iter->timeout_cnt > timer->timeout_cnt)
164+
if (_cnt_before(timer->timeout_cnt, iter->timeout_cnt))
122165
{
123166
break;
124167
}
@@ -132,12 +175,15 @@ static void _hrtimer_process_locked(void)
132175
{
133176
rt_clock_hrtimer_t timer;
134177

135-
for (timer = _first_hrtimer();
136-
(timer != RT_NULL) && (timer->timeout_cnt <= _clock_time_get_cnt());
137-
timer = _first_hrtimer())
178+
while ((timer = _first_hrtimer()) != RT_NULL)
138179
{
139180
unsigned long now = _clock_time_get_cnt();
140181

182+
if (_cnt_before(now, timer->timeout_cnt))
183+
{
184+
break;
185+
}
186+
141187
rt_list_remove(&(timer->node));
142188

143189
if (timer->flag & RT_TIMER_FLAG_PERIODIC)
@@ -303,7 +349,14 @@ rt_err_t rt_clock_hrtimer_control(rt_clock_hrtimer_t timer, int cmd, void *arg)
303349
*(unsigned long *)arg = timer->timeout_cnt;
304350
break;
305351
case RT_TIMER_CTRL_GET_FUNC:
306-
arg = (void *)timer->timeout_func;
352+
if (arg == RT_NULL)
353+
{
354+
result = -RT_EEMPTY;
355+
}
356+
else
357+
{
358+
*(void **)arg = (void *)timer->timeout_func;
359+
}
307360
break;
308361

309362
case RT_TIMER_CTRL_SET_FUNC:

0 commit comments

Comments
 (0)