1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-10-30 ChuShicheng first version
9 */
10
11 #include "drv_hwtimer.h"
12 #include "board.h"
13
14 #ifdef BSP_USING_HWTIMER
15
16 #define DBG_LEVEL DBG_LOG
17 #include <rtdbg.h>
18 #define LOG_TAG "DRV.HWTIMER"
19
20 typedef struct _timer
21 {
22 char *name;
23 struct repeating_timer repeat_timer;
24 alarm_id_t alarm_id;
25 rt_hwtimer_t timer;
26 }_timer_t;
27
28 static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state);
29 static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode);
30 static void _hwtimer_stop(rt_hwtimer_t *timer);
31 static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer);
32 static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
33 static int64_t _hwtmr_isr(alarm_id_t id, void *user_data);
34
35 static const struct rt_hwtimer_ops _hwtimer_ops = {
36 .init = _hwtimer_init,
37 .start = _hwtimer_start,
38 .stop = _hwtimer_stop,
39 .count_get = _hwtimer_count_get,
40 .control = _hwtimer_control
41 };
42
43 static const struct rt_hwtimer_info _hwtimer_info = {
44 .maxfreq = 1000000UL,
45 .minfreq = 1000000UL,
46 .maxcnt = 0xFFFF,
47 .cntmode = HWTIMER_MODE_PERIOD
48 };
49
50 #ifdef BSP_USING_TIMER0
51 static _timer_t timer0 = {.name = "timer0"};
52 #endif /* BSP_USING_TIMER0 */
53 #ifdef BSP_USING_TIMER1
54 static _timer_t timer1 = {.name = "timer1" };
55 #endif /* BSP_USING_TIMER1 */
56 #ifdef BSP_USING_TIMER2
57 static _timer_t timer2 = {.name = "timer2"};
58 #endif /* BSP_USING_TIMER2 */
59 #ifdef BSP_USING_TIMER3
60 static _timer_t timer3 = {.name = "timer3" };
61 #endif /* BSP_USING_TIMER3 */
62
63 static _timer_t *_timer_obj[] = {
64 #ifdef BSP_USING_TIMER0
65 &timer0,
66 #endif /* BSP_USING_TIMER0 */
67 #ifdef BSP_USING_TIMER1
68 &timer1,
69 #endif /* BSP_USING_TIMER1 */
70 #ifdef BSP_USING_TIMER2
71 &timer2,
72 #endif /* BSP_USING_TIMER2 */
73 #ifdef BSP_USING_TIMER3
74 &timer3,
75 #endif /* BSP_USING_TIMER3 */
76 };
77
_hwtmr_isr(alarm_id_t id,void * user_data)78 static int64_t _hwtmr_isr(alarm_id_t id, void *user_data)
79 {
80 _timer_t *_tmr = rt_container_of(id, _timer_t, alarm_id);
81 rt_device_hwtimer_isr(&_tmr->timer);
82 return RT_TRUE;
83 }
84
_repeat_timer_isr(struct repeating_timer * t)85 static bool _repeat_timer_isr(struct repeating_timer *t)
86 {
87 _timer_t *_tmr = rt_container_of(t, _timer_t, repeat_timer);
88 rt_device_hwtimer_isr(&_tmr->timer);
89 return RT_TRUE;
90 }
91
_hwtimer_init(rt_hwtimer_t * timer,rt_uint32_t state)92 static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
93 {
94 }
95
_hwtimer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)96 static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
97 {
98 _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
99
100 if(mode == HWTIMER_MODE_ONESHOT)
101 _tmr->alarm_id = add_alarm_in_us(cnt, _hwtmr_isr, RT_NULL, RT_TRUE);
102 else
103 add_repeating_timer_us(cnt, _repeat_timer_isr, RT_NULL, &_tmr->repeat_timer);
104
105 return RT_EOK;
106 }
107
_hwtimer_stop(rt_hwtimer_t * timer)108 static void _hwtimer_stop(rt_hwtimer_t *timer)
109 {
110 _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
111 if(timer->mode == HWTIMER_MODE_ONESHOT)
112 cancel_alarm(_tmr->alarm_id);
113 else
114 cancel_repeating_timer(&_tmr->repeat_timer);
115 }
116
_hwtimer_count_get(rt_hwtimer_t * timer)117 static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer)
118 {
119 _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
120
121 return timer_hw->alarm[_tmr->alarm_id];
122 }
123
_hwtimer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)124 static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
125 {
126 rt_err_t err = RT_EOK;
127 _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
128
129 switch (cmd)
130 {
131 case HWTIMER_CTRL_FREQ_SET:
132 err = -RT_ERROR;
133 break;
134 case HWTIMER_CTRL_INFO_GET:
135 *(rt_hwtimer_t*)args = _tmr->timer;
136 break;
137 case HWTIMER_CTRL_MODE_SET:
138 _tmr->timer.mode = *(rt_uint32_t*)args;
139 break;
140 case HWTIMER_CTRL_STOP:
141 _hwtimer_stop(timer);
142 break;
143 }
144
145 return err;
146 }
147
rt_hw_hwtimer_init(void)148 int rt_hw_hwtimer_init(void)
149 {
150 int ret = RT_EOK;
151
152 for (uint32_t i = 0; i < sizeof(_timer_obj) / sizeof(_timer_obj[0]); i++)
153 {
154 _timer_obj[i]->timer.info = &_hwtimer_info;
155 _timer_obj[i]->timer.ops = &_hwtimer_ops;
156 ret = rt_device_hwtimer_register(&_timer_obj[i]->timer, _timer_obj[i]->name, _timer_obj[i]);
157 if (ret != RT_EOK)
158 {
159 LOG_E("%s register failed", _timer_obj[i]->name);
160 }
161 }
162
163 return ret;
164 }
165
166 INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
167 #endif /* BSP_USING_HWTIMER */
168