1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-05-12 hqfang first version
9 */
10
11 #include "drv_hwtimer.h"
12
13 #ifdef BSP_USING_HWTIMER
14
15 #if !defined(BSP_USING_HWTIMER0) && !defined(BSP_USING_HWTIMER1) && !defined(BSP_USING_HWTIMER2) \
16 && !defined(BSP_USING_HWTIMER3) && !defined(BSP_USING_HWTIMER4)
17 #error "Please define at least one BSP_USING_HWTIMERx"
18 /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable HWTIMER */
19 #endif
20
21 static struct gd32_hwtimer_config hwtimer_config[] =
22 {
23 #ifdef BSP_USING_HWTIMER0
24 {
25 "timer0",
26 TIMER0,
27 TIMER0_UP_IRQn,
28 },
29 #endif
30 #ifdef BSP_USING_HWTIMER1
31 {
32 "timer1",
33 TIMER1,
34 TIMER1_IRQn,
35 },
36 #endif
37 #ifdef BSP_USING_HWTIMER2
38 {
39 "timer2",
40 TIMER2,
41 TIMER2_IRQn,
42 },
43 #endif
44 #ifdef BSP_USING_HWTIMER3
45 {
46 "timer3",
47 TIMER3,
48 TIMER3_IRQn,
49 },
50 #endif
51 #ifdef BSP_USING_HWTIMER4
52 {
53 "timer4",
54 TIMER4,
55 TIMER4_IRQn,
56 },
57 #endif
58 #ifdef BSP_USING_HWTIMER5
59 {
60 "timer5",
61 TIMER5,
62 TIMER5_IRQn,
63 },
64 #endif
65 #ifdef BSP_USING_HWTIMER6
66 {
67 "timer6",
68 TIMER6,
69 TIMER6_IRQn,
70 },
71 #endif
72 };
73
74 static struct gd32_hwtimer hwtimer_obj[sizeof(hwtimer_config) / sizeof(hwtimer_config[0])] = {0};
75
gd32_hwtimer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)76 static rt_err_t gd32_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
77 {
78 rt_err_t err = RT_EOK;
79 struct gd32_hwtimer_config *config;
80 RT_ASSERT(timer != RT_NULL);
81
82 config = (struct gd32_hwtimer_config *)timer->parent.user_data;
83
84 switch (cmd)
85 {
86 case HWTIMER_CTRL_FREQ_SET:
87 {
88 uint32_t clk;
89 uint8_t clkpre;
90 uint32_t pre;
91 if (config->timer_periph != TIMER0)
92 {
93 clk = rcu_clock_freq_get(CK_APB1);
94 clkpre = GET_BITS(RCU_CFG0, 8, 10);
95 }
96 else
97 {
98 clk = rcu_clock_freq_get(CK_APB2);
99 clkpre = GET_BITS(RCU_CFG0, 11, 13);
100 }
101 if (clkpre >= 4)
102 {
103 clk = clk * 2;
104 }
105 pre = (clk / * ((uint32_t *)args)) - 1;
106 TIMER_PSC(config->timer_periph) = (uint32_t)pre;
107 }
108 break;
109 case HWTIMER_CTRL_STOP:
110 timer_disable(config->timer_periph);
111 break;
112 default:
113 err = -RT_ENOSYS;
114 break;
115 }
116 return err;
117 }
118
gd32_hwtimer_count_get(rt_hwtimer_t * timer)119 static rt_uint32_t gd32_hwtimer_count_get(rt_hwtimer_t *timer)
120 {
121 rt_uint32_t CurrentTimer_Count;
122 struct gd32_hwtimer_config *config;
123 RT_ASSERT(timer != RT_NULL);
124
125 config = (struct gd32_hwtimer_config *)timer->parent.user_data;
126
127 CurrentTimer_Count = timer_counter_read(config->timer_periph);
128
129 return CurrentTimer_Count;
130 }
131
gd32_hwtimer_init(rt_hwtimer_t * timer,rt_uint32_t state)132 static void gd32_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
133 {
134 struct gd32_hwtimer_config *config;
135 timer_parameter_struct initpara;
136 RT_ASSERT(timer != RT_NULL);
137 config = (struct gd32_hwtimer_config *)timer->parent.user_data;
138
139 if (state == 1)
140 {
141 timer_deinit(config->timer_periph);
142 timer_struct_para_init(&initpara);
143 timer_init(config->timer_periph, &initpara);
144 }
145 else
146 {
147 timer_disable(config->timer_periph);
148 timer_interrupt_enable(config->timer_periph, TIMER_INT_FLAG_UP);
149 ECLIC_DisableIRQ(config->irqn);
150 }
151 }
152
gd32_hwtimer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)153 static rt_err_t gd32_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
154 {
155 struct gd32_hwtimer_config *config;
156 RT_ASSERT(timer != RT_NULL);
157 config = (struct gd32_hwtimer_config *)timer->parent.user_data;
158
159 if (mode == HWTIMER_MODE_ONESHOT)
160 {
161 timer_single_pulse_mode_config(config->timer_periph, TIMER_SP_MODE_SINGLE);
162 }
163 else
164 {
165 timer_single_pulse_mode_config(config->timer_periph, TIMER_SP_MODE_REPETITIVE);
166 }
167 timer_counter_value_config(config->timer_periph, 0);
168 timer_autoreload_value_config(config->timer_periph, cnt);
169 timer_interrupt_enable(config->timer_periph, TIMER_INT_FLAG_UP);
170 timer_enable(config->timer_periph);
171 ECLIC_EnableIRQ(config->irqn);
172
173 return RT_EOK;
174 }
175
gd32_hwtimer_stop(rt_hwtimer_t * timer)176 static void gd32_hwtimer_stop(rt_hwtimer_t *timer)
177 {
178 struct gd32_hwtimer_config *config;
179 RT_ASSERT(timer != RT_NULL);
180 config = (struct gd32_hwtimer_config *)timer->parent.user_data;
181
182 timer_disable(config->timer_periph);
183
184 ECLIC_DisableIRQ(config->irqn);
185 }
186
187 static const struct rt_hwtimer_ops gd32_hwtimer_ops =
188 {
189 .init = gd32_hwtimer_init,
190 .start = gd32_hwtimer_start,
191 .stop = gd32_hwtimer_stop,
192 .count_get = gd32_hwtimer_count_get,
193 .control = gd32_hwtimer_control,
194 };
195
196 static const struct rt_hwtimer_info gd32_hwtimer_info =
197 {
198 54000000, /* the maximum count frequency can be set */
199 1000, /* the minimum count frequency can be set */
200 0xFFFF,
201 HWTIMER_CNTMODE_UP,
202 };
203
204 #ifdef BSP_USING_HWTIMER0
205
TIMER0_UP_IRQHandler(void)206 void TIMER0_UP_IRQHandler(void)
207 {
208 timer_interrupt_flag_clear(hwtimer_obj[0].config->timer_periph, TIMER_INT_FLAG_UP);
209 rt_device_hwtimer_isr(&hwtimer_obj[0].time_device);
210 }
211
212 #endif
213
214 #ifdef BSP_USING_HWTIMER1
215
TIMER1_IRQHandler(void)216 void TIMER1_IRQHandler(void)
217 {
218 timer_interrupt_flag_clear(hwtimer_obj[1].config->timer_periph, TIMER_INT_FLAG_UP);
219 rt_device_hwtimer_isr(&hwtimer_obj[1].time_device);
220 }
221
222 #endif
223
224 #ifdef BSP_USING_HWTIMER2
225
TIMER2_IRQHandler(void)226 void TIMER2_IRQHandler(void)
227 {
228 timer_interrupt_flag_clear(hwtimer_obj[2].config->timer_periph, TIMER_INT_FLAG_UP);
229 rt_device_hwtimer_isr(&hwtimer_obj[2].time_device);
230 }
231
232 #endif
233
234 #ifdef BSP_USING_HWTIMER3
235
TIMER3_IRQHandler(void)236 void TIMER3_IRQHandler(void)
237 {
238 timer_interrupt_flag_clear(hwtimer_obj[3].config->timer_periph, TIMER_INT_FLAG_UP);
239 rt_device_hwtimer_isr(&hwtimer_obj[3].time_device);
240 }
241
242 #endif
243
244 #ifdef BSP_USING_HWTIMER4
245
TIMER4_IRQHandler(void)246 void TIMER4_IRQHandler(void)
247 {
248 timer_interrupt_flag_clear(hwtimer_obj[4].config->timer_periph, TIMER_INT_FLAG_UP);
249 rt_device_hwtimer_isr(&hwtimer_obj[4].time_device);
250 }
251
252 #endif
253
254 #ifdef BSP_USING_HWTIMER5
255
TIMER5_IRQHandler(void)256 void TIMER5_IRQHandler(void)
257 {
258 timer_interrupt_flag_clear(hwtimer_obj[5].config->timer_periph, TIMER_INT_FLAG_UP);
259 rt_device_hwtimer_isr(&hwtimer_obj[5].time_device);
260 }
261
262 #endif
263
264 #ifdef BSP_USING_HWTIMER6
265
TIMER6_IRQHandler(void)266 void TIMER6_IRQHandler(void)
267 {
268 timer_interrupt_flag_clear(hwtimer_obj[6].config->timer_periph, TIMER_INT_FLAG_UP);
269 rt_device_hwtimer_isr(&hwtimer_obj[6].time_device);
270 }
271
272 #endif
273
rt_hwtimer_init(void)274 static int rt_hwtimer_init(void)
275 {
276 int i = 0;
277 int result = RT_EOK;
278
279 #ifdef BSP_USING_HWTIMER0
280 rcu_periph_clock_enable(RCU_TIMER0);
281 #endif
282 #ifdef BSP_USING_HWTIMER1
283 rcu_periph_clock_enable(RCU_TIMER1);
284 #endif
285 #ifdef BSP_USING_HWTIMER2
286 rcu_periph_clock_enable(RCU_TIMER2);
287 #endif
288 #ifdef BSP_USING_HWTIMER3
289 rcu_periph_clock_enable(RCU_TIMER3);
290 #endif
291 #ifdef BSP_USING_HWTIMER4
292 rcu_periph_clock_enable(RCU_TIMER4);
293 #endif
294 #ifdef BSP_USING_HWTIMER5
295 rcu_periph_clock_enable(RCU_TIMER5);
296 #endif
297 #ifdef BSP_USING_HWTIMER6
298 rcu_periph_clock_enable(RCU_TIMER6);
299 #endif
300
301 for (i = 0; i < sizeof(hwtimer_obj) / sizeof(hwtimer_obj[0]); i++)
302 {
303 hwtimer_obj[i].time_device.info = &gd32_hwtimer_info;
304 hwtimer_obj[i].time_device.ops = &gd32_hwtimer_ops;
305 hwtimer_obj[i].config = &hwtimer_config[i];
306 rt_device_hwtimer_register(&hwtimer_obj[i].time_device, \
307 hwtimer_obj[i].config->name, hwtimer_obj[i].config);
308 }
309
310 return result;
311 }
312
313 INIT_DEVICE_EXPORT(rt_hwtimer_init);
314
315 #endif /* RT_USING_HWTIMER */
316