1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-05-16 shelton first version
9 */
10
11 #include "board.h"
12 #include "drv_hwtimer.h"
13
14 //#define DRV_DEBUG
15 #define LOG_TAG "drv.hwtimer"
16 #include <drv_log.h>
17
18 #ifdef BSP_USING_HWTIMER
19
20 enum
21 {
22 #ifdef BSP_USING_HWTMR1
23 TMR1_INDEX,
24 #endif
25
26 #ifdef BSP_USING_HWTMR2
27 TMR2_INDEX,
28 #endif
29
30 #ifdef BSP_USING_HWTMR3
31 TMR3_INDEX,
32 #endif
33
34 #ifdef BSP_USING_HWTMR4
35 TMR4_INDEX,
36 #endif
37
38 #ifdef BSP_USING_HWTMR5
39 TMR5_INDEX,
40 #endif
41
42 #ifdef BSP_USING_HWTMR6
43 TMR6_INDEX,
44 #endif
45
46 #ifdef BSP_USING_HWTMR7
47 TMR7_INDEX,
48 #endif
49
50 #ifdef BSP_USING_HW_TMR8
51 TMR8_INDEX,
52 #endif
53
54 #ifdef BSP_USING_HWTMR9
55 TMR9_INDEX,
56 #endif
57
58 #ifdef BSP_USING_HWTMR10
59 TMR10_INDEX,
60 #endif
61
62 #ifdef BSP_USING_HWTMR11
63 TMR11_INDEX,
64 #endif
65
66 #ifdef BSP_USING_HWTMR12
67 TMR12_INDEX,
68 #endif
69
70 #ifdef BSP_USING_HWTMR13
71 TMR13_INDEX,
72 #endif
73
74 #ifdef BSP_USING_HWTMR14
75 TMR14_INDEX,
76 #endif
77
78 #ifdef BSP_USING_HWTMR15
79 TMR15_INDEX,
80 #endif
81 };
82
83 struct at32_hwtimer
84 {
85 rt_hwtimer_t tmr_device;
86 tmr_type* tmr_x;
87 IRQn_Type tmr_irqn;
88 char *name;
89 };
90
91 static struct at32_hwtimer at32_hwtimer_obj[] =
92 {
93 #ifdef BSP_USING_HWTMR1
94 TMR1_CONFIG,
95 #endif
96
97 #ifdef BSP_USING_HWTMR2
98 TMR2_CONFIG,
99 #endif
100
101 #ifdef BSP_USING_HWTMR3
102 TMR3_CONFIG,
103 #endif
104
105 #ifdef BSP_USING_HWTMR4
106 TMR4_CONFIG,
107 #endif
108
109 #ifdef BSP_USING_HWTMR5
110 TMR5_CONFIG,
111 #endif
112
113 #ifdef BSP_USING_HWTMR6
114 TMR6_CONFIG,
115 #endif
116
117 #ifdef BSP_USING_HWTMR7
118 TMR7_CONFIG,
119 #endif
120
121 #ifdef BSP_USING_HWTMR8
122 TMR8_CONFIG,
123 #endif
124
125 #ifdef BSP_USING_HWTMR9
126 TMR9_CONFIG,
127 #endif
128
129 #ifdef BSP_USING_HWTMR10
130 TMR10_CONFIG,
131 #endif
132
133 #ifdef BSP_USING_HWTMR11
134 TMR11_CONFIG,
135 #endif
136
137 #ifdef BSP_USING_HWTMR12
138 TMR12_CONFIG,
139 #endif
140
141 #ifdef BSP_USING_HWTMR13
142 TMR13_CONFIG,
143 #endif
144
145 #ifdef BSP_USING_HWTMR14
146 TMR14_CONFIG,
147 #endif
148
149 #ifdef BSP_USING_HWTMR15
150 TMR15_CONFIG,
151 #endif
152 };
153
tmr_pclk_get(rt_uint32_t * pclk1_doubler,rt_uint32_t * pclk2_doubler)154 static void tmr_pclk_get(rt_uint32_t *pclk1_doubler, rt_uint32_t *pclk2_doubler)
155 {
156 crm_clocks_freq_type clocks_struct;
157
158 *pclk1_doubler = 1;
159 *pclk2_doubler = 1;
160
161 crm_clocks_freq_get(&clocks_struct);
162
163 if(clocks_struct.ahb_freq != clocks_struct.apb1_freq)
164 {
165 *pclk1_doubler = 2;
166 }
167
168 if(clocks_struct.ahb_freq != clocks_struct.apb2_freq)
169 {
170 *pclk2_doubler = 2;
171 }
172 }
173
at32_timer_init(struct rt_hwtimer_device * timer,rt_uint32_t state)174 static void at32_timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
175 {
176 crm_clocks_freq_type clocks_struct;
177 rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0;
178 rt_uint32_t prescaler_value = 0, tmr_clock = 0;
179 tmr_type *tmr_x = RT_NULL;
180 struct at32_hwtimer *tmr_device = RT_NULL;
181
182 RT_ASSERT(timer != RT_NULL);
183 if (state)
184 {
185 tmr_x = (tmr_type *)timer->parent.user_data;
186 tmr_device = (struct at32_hwtimer *)timer;
187
188 /* timer clock enable */
189 at32_msp_hwtmr_init(tmr_x);
190
191 /* get timer clock */
192 tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
193 crm_clocks_freq_get(&clocks_struct);
194
195 if(
196 #if defined (TMR1)
197 (tmr_x == TMR1)
198 #endif
199 #if defined (TMR8)
200 || (tmr_x == TMR8)
201 #endif
202 #if defined (TMR9)
203 || (tmr_x == TMR9)
204 #endif
205 #if defined (TMR10)
206 || (tmr_x == TMR10)
207 #endif
208 #if defined (TMR11)
209 || (tmr_x == TMR11)
210 #endif
211 )
212 {
213 tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
214 }
215 else
216 {
217 tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
218 }
219 /* set timer clock is 1mhz */
220 prescaler_value = (uint32_t)(tmr_clock / 10000) - 1;
221 tmr_base_init(tmr_x, 10000 - 1, prescaler_value);
222 tmr_clock_source_div_set(tmr_x, TMR_CLOCK_DIV1);
223 tmr_repetition_counter_set(tmr_x, 0);
224
225 if (timer->info->cntmode == HWTIMER_CNTMODE_UP)
226 {
227 tmr_cnt_dir_set(tmr_x, TMR_COUNT_UP);
228 }
229 else
230 {
231 tmr_cnt_dir_set(tmr_x, TMR_COUNT_DOWN);
232 }
233
234 /* enable the timer global interrupt and clear flag */
235 nvic_irq_enable(tmr_device->tmr_irqn, 2, 0);
236
237 tmr_interrupt_enable(tmr_x, TMR_OVF_INT, TRUE);
238 tmr_flag_clear(tmr_x, TMR_OVF_INT);
239
240 LOG_D("%s init success", tmr_device->name);
241 }
242 }
243
at32_timer_start(rt_hwtimer_t * timer,rt_uint32_t pr,rt_hwtimer_mode_t opmode)244 static rt_err_t at32_timer_start(rt_hwtimer_t *timer, rt_uint32_t pr, rt_hwtimer_mode_t opmode)
245 {
246 rt_err_t result = RT_EOK;
247 tmr_type *tmr_x = RT_NULL;
248
249 RT_ASSERT(timer != RT_NULL);
250 tmr_x = (tmr_type *)timer->parent.user_data;
251
252 /* set tmr_x count */
253 tmr_counter_value_set(tmr_x, 0);
254 /* set tmr_x period register */
255 tmr_period_value_set(tmr_x, pr - 1);
256
257 if (opmode == HWTIMER_MODE_ONESHOT)
258 {
259 /* set timer to one cycle mode */
260 tmr_one_cycle_mode_enable(tmr_x, TRUE);
261 }
262 else
263 {
264 /* set timer to period mode */
265 tmr_one_cycle_mode_enable(tmr_x, FALSE);
266 }
267
268 /* start timer */
269 tmr_counter_enable(tmr_x, TRUE);
270
271 return result;
272 }
273
at32_timer_stop(rt_hwtimer_t * timer)274 static void at32_timer_stop(rt_hwtimer_t *timer)
275 {
276 tmr_type *tmr_x = RT_NULL;
277
278 RT_ASSERT(timer != RT_NULL);
279 tmr_x = (tmr_type *)timer->parent.user_data;
280
281 /* stop timer */
282 tmr_counter_enable(tmr_x, FALSE);
283
284 /* set tmr_x count */
285 tmr_counter_value_set(tmr_x, 0);
286 }
287
at32_timer_counter_get(rt_hwtimer_t * timer)288 static rt_uint32_t at32_timer_counter_get(rt_hwtimer_t *timer)
289 {
290 tmr_type *tmr_x = RT_NULL;
291
292 RT_ASSERT(timer != RT_NULL);
293
294 tmr_x = (tmr_type *)timer->parent.user_data;
295
296 return tmr_counter_value_get(tmr_x);
297 }
298
at32_timer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)299 static rt_err_t at32_timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
300 {
301 crm_clocks_freq_type clocks_struct;
302 tmr_type *tmr_x = RT_NULL;
303 rt_err_t result = RT_EOK;
304 rt_uint32_t pclk1_doubler = 0, pclk2_doubler = 0, tmr_clock = 0;
305
306 RT_ASSERT(timer != RT_NULL);
307 RT_ASSERT(arg != RT_NULL);
308
309 tmr_x = (tmr_type *)timer->parent.user_data;
310
311 switch(cmd)
312 {
313 case HWTIMER_CTRL_FREQ_SET:
314 {
315 rt_uint32_t freq;
316 rt_uint16_t val;
317
318 /* get timer frequence */
319 freq = *((rt_uint32_t *)arg);
320
321 /* get timer clock */
322 tmr_pclk_get(&pclk1_doubler, &pclk2_doubler);
323 crm_clocks_freq_get(&clocks_struct);
324 if(
325 #if defined (TMR1)
326 (tmr_x == TMR1)
327 #endif
328 #if defined (TMR8)
329 || (tmr_x == TMR8)
330 #endif
331 #if defined (TMR9)
332 || (tmr_x == TMR9)
333 #endif
334 #if defined (TMR10)
335 || (tmr_x == TMR10)
336 #endif
337 #if defined (TMR11)
338 || (tmr_x == TMR11)
339 #endif
340 )
341 {
342 tmr_clock = clocks_struct.apb2_freq * pclk2_doubler;
343 }
344 else
345 {
346 tmr_clock = clocks_struct.apb1_freq * pclk1_doubler;
347 }
348 /* set div value */
349 val = tmr_clock / freq;
350
351 tmr_div_value_set(tmr_x, val - 1);
352 tmr_event_sw_trigger(tmr_x, TMR_OVERFLOW_SWTRIG);
353 }
354 break;
355 default:
356 {
357 result = -RT_ENOSYS;
358 }
359 break;
360 }
361
362 return result;
363 }
364
365 static const struct rt_hwtimer_info _info = TMR_DEV_INFO_CONFIG;
366 static const struct rt_hwtimer_ops _ops =
367 {
368 .init = at32_timer_init,
369 .start = at32_timer_start,
370 .stop = at32_timer_stop,
371 .count_get = at32_timer_counter_get,
372 .control = at32_timer_ctrl,
373 };
374
375 #ifdef BSP_USING_HWTMR2
TMR2_GLOBAL_IRQHandler(void)376 void TMR2_GLOBAL_IRQHandler(void)
377 {
378 /* enter interrupt */
379 rt_interrupt_enter();
380
381 if(tmr_flag_get(TMR2, TMR_OVF_FLAG) == SET)
382 {
383 rt_device_hwtimer_isr(&at32_hwtimer_obj[TMR2_INDEX].tmr_device);
384 tmr_flag_clear(TMR2, TMR_OVF_FLAG);
385 }
386 /* leave interrupt */
387 rt_interrupt_leave();
388 }
389 #endif
390
391 #ifdef BSP_USING_HWTMR3
TMR3_GLOBAL_IRQHandler(void)392 void TMR3_GLOBAL_IRQHandler(void)
393 {
394 /* enter interrupt */
395 rt_interrupt_enter();
396
397 if(tmr_flag_get(TMR3, TMR_OVF_FLAG) == SET)
398 {
399 rt_device_hwtimer_isr(&at32_hwtimer_obj[TMR3_INDEX].tmr_device);
400 tmr_flag_clear(TMR3, TMR_OVF_FLAG);
401 }
402 /* leave interrupt */
403 rt_interrupt_leave();
404 }
405 #endif
406
407 #ifdef BSP_USING_HWTMR4
TMR4_GLOBAL_IRQHandler(void)408 void TMR4_GLOBAL_IRQHandler(void)
409 {
410 /* enter interrupt */
411 rt_interrupt_enter();
412
413 if(tmr_flag_get(TMR4, TMR_OVF_FLAG) == SET)
414 {
415 rt_device_hwtimer_isr(&at32_hwtimer_obj[TMR4_INDEX].tmr_device);
416 tmr_flag_clear(TMR4, TMR_OVF_FLAG);
417 }
418 /* leave interrupt */
419 rt_interrupt_leave();
420 }
421 #endif
422
423 #ifdef BSP_USING_HWTMR5
TMR5_GLOBAL_IRQHandler(void)424 void TMR5_GLOBAL_IRQHandler(void)
425 {
426 /* enter interrupt */
427 rt_interrupt_enter();
428
429 if(tmr_flag_get(TMR5, TMR_OVF_FLAG) == SET)
430 {
431 rt_device_hwtimer_isr(&at32_hwtimer_obj[TMR5_INDEX].tmr_device);
432 tmr_flag_clear(TMR5, TMR_OVF_FLAG);
433 }
434 /* leave interrupt */
435 rt_interrupt_leave();
436 }
437 #endif
438
rt_hw_hwtimer_init(void)439 static int rt_hw_hwtimer_init(void)
440 {
441 int i = 0;
442 int result = RT_EOK;
443
444 for (i = 0; i < sizeof(at32_hwtimer_obj) / sizeof(at32_hwtimer_obj[0]); i++)
445 {
446 at32_hwtimer_obj[i].tmr_device.info = &_info;
447 at32_hwtimer_obj[i].tmr_device.ops = &_ops;
448 if (rt_device_hwtimer_register(&at32_hwtimer_obj[i].tmr_device, at32_hwtimer_obj[i].name, at32_hwtimer_obj[i].tmr_x) == RT_EOK)
449 {
450 LOG_D("%s register success", at32_hwtimer_obj[i].name);
451 }
452 else
453 {
454 LOG_E("%s register failed", at32_hwtimer_obj[i].name);
455 result = -RT_ERROR;
456 }
457 }
458
459 return result;
460 }
461
462 INIT_BOARD_EXPORT(rt_hw_hwtimer_init);
463
464 #endif /* BSP_USING_HWTIMER */
465