1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2021-02-25     iysheng           first version
9  */
10 
11 #include <board.h>
12 #include <rtdevice.h>
13 #include <drivers/hwtimer.h>
14 
15 #ifdef BSP_USING_HWTIMER
16 
17 typedef struct {
18     uint32_t reg_base;
19     IRQn_Type irqn;
20     rcu_periph_enum rcu;
21 } gd32_hwtimer_data;
22 
23 typedef struct {
24     char dev_name[RT_NAME_MAX];
25     const gd32_hwtimer_data hw_data;
26     rt_hwtimer_t hwtimer_dev;
27     const struct rt_hwtimer_info hwtimer_info;
28 } gd32_hwtimer_device;
29 
30 enum timer_index_E {
31 #ifdef BSP_USING_HWTIMER0
32     TIM0_INDEX,
33 #endif
34 #ifdef BSP_USING_HWTIMER1
35     TIM1_INDEX,
36 #endif
37 #ifdef BSP_USING_HWTIMER2
38     TIM2_INDEX,
39 #endif
40 #ifdef BSP_USING_HWTIMER3
41     TIM3_INDEX,
42 #endif
43 #ifdef BSP_USING_HWTIMER4
44     TIM4_INDEX,
45 #endif
46 #ifdef BSP_USING_HWTIMER5
47     TIM5_INDEX,
48 #endif
49 #ifdef BSP_USING_HWTIMER6
50     TIM6_INDEX,
51 #endif
52 #ifdef BSP_USING_HWTIMER7
53     TIM7_INDEX,
54 #endif
55 #ifdef BSP_USING_HWTIMER8
56     TIM8_INDEX,
57 #endif
58 #ifdef BSP_USING_HWTIMER9
59     TIM9_INDEX,
60 #endif
61 #ifdef BSP_USING_HWTIMER10
62     TIM10_INDEX,
63 #endif
64 #ifdef BSP_USING_HWTIMER11
65     TIM11_INDEX,
66 #endif
67 #ifdef BSP_USING_HWTIMER12
68     TIM12_INDEX,
69 #endif
70 #ifdef BSP_USING_HWTIMER13
71     TIM13_INDEX,
72 #endif
73 };
74 
75 /*
76  * static void __set_timerx_freq
77  * Set freq with timerx
78  *
79  * @param timerx the pointer of TIMER_TypeDef
80  * @param freq of the timer clock
81  * @retval None
82  */
__set_timerx_freq(uint32_t timerx,uint32_t freq)83 static void __set_timerx_freq(uint32_t timerx, uint32_t freq)
84 {
85     uint32_t ap1freq, ap2freq;
86     uint16_t prescaler;
87     uint32_t temp;
88 
89     if (timerx == TIMER0 || timerx == TIMER7 || timerx == TIMER8 \
90         || timerx == TIMER9 || timerx == TIMER10)
91     {
92         ap2freq = rcu_clock_freq_get(CK_APB2);
93         temp = RCU_CFG0 & RCU_CFG0_APB2PSC;
94         temp >>= 11;
95         /* whether should frequency doubling */
96         temp = (temp < 4) ? 0 : 1;
97 
98         prescaler = (ap2freq << temp) / freq - 1;
99     }
100     else
101     {
102         ap1freq = rcu_clock_freq_get(CK_APB1);
103         temp = RCU_CFG0 & RCU_CFG0_APB1PSC;
104         temp >>= 8;
105         /* whether should frequency doubling */
106         temp = (temp < 4) ? 0 : 1;
107 
108         prescaler = (ap1freq << temp) / freq - 1;
109     }
110 
111     timer_prescaler_config(timerx, prescaler, TIMER_PSC_RELOAD_NOW);
112 }
113 
gd32_hwtimer_init(struct rt_hwtimer_device * timer,rt_uint32_t state)114 static void gd32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
115 {
116     uint32_t timer_base = (uint32_t)timer->parent.user_data;
117     timer_parameter_struct initpara;
118 
119     if (state)
120     {
121         timer_internal_clock_config(timer_base);
122         timer_struct_para_init(&initpara);
123         initpara.period =  timer->info->maxcnt;
124         timer_init(timer_base, &initpara);
125         __set_timerx_freq(timer_base, timer->info->maxfreq);
126     }
127 }
128 
gd32_hwtimer_start(struct rt_hwtimer_device * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)129 static rt_err_t gd32_hwtimer_start(struct rt_hwtimer_device *timer, \
130     rt_uint32_t cnt, rt_hwtimer_mode_t mode)
131 {
132     uint32_t timer_base = (uint32_t)timer->parent.user_data;
133 
134     if (mode == HWTIMER_MODE_ONESHOT)
135     {
136         timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_SINGLE);
137     }
138     else if (mode == HWTIMER_MODE_PERIOD)
139     {
140         timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_REPETITIVE);
141     }
142 
143     timer_counter_value_config(timer_base, 0);
144     timer_autoreload_value_config(timer_base, cnt - 1);
145     timer_enable(timer_base);
146 
147     return 0;
148 }
149 
gd32_hwtimer_stop(struct rt_hwtimer_device * timer)150 static void gd32_hwtimer_stop(struct rt_hwtimer_device *timer)
151 {
152     uint32_t timer_base = (uint32_t)timer->parent.user_data;
153 
154     timer_disable(timer_base);
155 }
156 
gd32_hwtimer_count_get(struct rt_hwtimer_device * timer)157 static rt_uint32_t gd32_hwtimer_count_get(struct rt_hwtimer_device *timer)
158 {
159     uint32_t timer_base = (uint32_t)timer->parent.user_data;
160     rt_uint32_t count;
161 
162     count = timer_counter_read(timer_base);
163 
164     return count;
165 }
166 
gd32_hwtimer_control(struct rt_hwtimer_device * timer,rt_uint32_t cmd,void * args)167 static rt_err_t gd32_hwtimer_control(struct rt_hwtimer_device *timer, rt_uint32_t cmd, \
168     void *args)
169 {
170     int ret = RT_EOK;
171     rt_int32_t freq;
172     rt_hwtimer_mode_t mode;
173 
174     switch (cmd)
175     {
176     case HWTIMER_CTRL_FREQ_SET:
177         freq = *(rt_uint32_t *)args;
178         __set_timerx_freq((uint32_t)timer->parent.user_data, freq);
179         break;
180     default:
181         rt_kprintf("invalid cmd:%x\n", cmd);
182         ret = -RT_EINVAL;
183         break;
184     }
185 
186     return ret;
187 }
188 
189 static const struct rt_hwtimer_ops g_gd32_hwtimer_ops = {
190     gd32_hwtimer_init,
191     gd32_hwtimer_start,
192     gd32_hwtimer_stop,
193     gd32_hwtimer_count_get,
194     gd32_hwtimer_control,
195 };
196 
197 static gd32_hwtimer_device g_gd32_hwtimer[] = {
198 #ifdef BSP_USING_HWTIMER0
199     {
200         "timer0",
201         {
202              TIMER0,
203              TIMER0_UP_IRQn,
204              RCU_TIMER0,
205         },
206         {0},
207         {
208             1000000,
209             1000,
210             0xffff,
211             0, /* count up mode  */
212         }
213     },
214 #endif
215 #ifdef BSP_USING_HWTIMER1
216     {
217         "timer1",
218         {
219              TIMER1,
220              TIMER1_IRQn,
221              RCU_TIMER1,
222         },
223         {0},
224         {
225             1000000,
226             1000,
227             0xffff,
228             0, /* count up mode  */
229         }
230     },
231 #endif
232 #ifdef BSP_USING_HWTIMER2
233     {
234         "timer2",
235         {
236              TIMER2,
237              TIMER2_IRQn,
238              RCU_TIMER2,
239         },
240         {0},
241         {
242             1000000,
243             1000,
244             0xffff,
245             0, /* count up mode  */
246         }
247     },
248 #endif
249 #ifdef BSP_USING_HWTIMER3
250     {
251         "timer3",
252         {
253              TIMER3,
254              TIMER3_IRQn,
255              RCU_TIMER3,
256         },
257         {0},
258         {
259             1000000,
260             1000,
261             0xffff,
262             0, /* count up mode  */
263         }
264     },
265 #endif
266 #ifdef BSP_USING_HWTIMER4
267     {
268         "timer4",
269         {
270              TIMER4,
271              TIMER4_IRQn,
272              RCU_TIMER4,
273         },
274         {0},
275         {
276             1000000,
277             1000,
278             0xffff,
279             0, /* count up mode  */
280         }
281     },
282 #endif
283 #ifdef BSP_USING_HWTIMER5
284     {
285         "timer5",
286         {
287              TIMER5,
288              TIMER5_IRQn,
289              RCU_TIMER5,
290         },
291         {0},
292         {
293             1000000,
294             1000,
295             0xffff,
296             0, /* count up mode  */
297         }
298     },
299 #endif
300 #ifdef BSP_USING_HWTIMER6
301     {
302         "timer6",
303         {
304              TIMER6,
305              TIMER6_IRQn,
306              RCU_TIMER6,
307         },
308         {0},
309         {
310             1000000,
311             1000,
312             0xffff,
313             0, /* count up mode  */
314         }
315     },
316 #endif
317 #ifdef BSP_USING_HWTIMER7
318     {
319         "timer7",
320         {
321              TIMER7,
322              TIMER7_UP_IRQn,
323              RCU_TIMER7,
324         },
325         {0},
326         {
327             1000000,
328             1000,
329             0xffff,
330             0, /* count up mode  */
331         }
332     },
333 #endif
334 #ifdef BSP_USING_HWTIMER8
335     {
336         "timer8",
337         {
338              TIMER8,
339              TIMER8_IRQn,
340              RCU_TIMER8,
341         },
342         {0},
343         {
344             1000000,
345             1000,
346             0xffff,
347             0, /* count up mode  */
348         }
349     },
350 #endif
351 #ifdef BSP_USING_HWTIMER9
352     {
353         "timer9",
354         {
355              TIMER9,
356              TIMER9_IRQn,
357              RCU_TIMER9,
358         },
359         {0},
360         {
361             1000000,
362             1000,
363             0xffff,
364             0, /* count up mode  */
365         }
366     },
367 #endif
368 #ifdef BSP_USING_HWTIMER10
369     {
370         "timer10",
371         {
372              TIMER10,
373              TIMER10_IRQn,
374              RCU_TIMER10,
375         },
376         {0},
377         {
378             1000000,
379             1000,
380             0xffff,
381             0, /* count up mode  */
382         }
383     },
384 #endif
385 #ifdef BSP_USING_HWTIMER11
386     {
387         "timer11",
388         {
389              TIMER11,
390              TIMER11_IRQn,
391              RCU_TIMER11,
392         },
393         {0},
394         {
395             1000000,
396             1000,
397             0xffff,
398             0, /* count up mode  */
399         }
400     },
401 #endif
402 #ifdef BSP_USING_HWTIMER12
403     {
404         "timer12",
405         {
406              TIMER12,
407              TIMER12_IRQn,
408              RCU_TIMER12,
409         },
410         {0},
411         {
412             1000000,
413             1000,
414             0xffff,
415             0, /* count up mode  */
416         }
417     },
418 #endif
419 #ifdef BSP_USING_HWTIMER13
420     {
421         "timer13",
422         {
423              TIMER13,
424              TIMER13_IRQn,
425              RCU_TIMER13,
426         },
427         {0},
428         {
429             1000000,
430             1000,
431             0xffff,
432             0, /* count up mode  */
433         }
434     },
435 #endif
436 };
437 
438 #ifdef BSP_USING_HWTIMER0
TIMER0_UP_IRQHandler(void)439 void TIMER0_UP_IRQHandler(void)
440 {
441     rt_interrupt_enter();
442     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev);
443     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev.parent.user_data, \
444         TIMER_INT_UP);
445     rt_interrupt_leave();
446 }
447 #endif
448 
449 #ifdef BSP_USING_HWTIMER1
TIMER1_IRQHandler(void)450 void TIMER1_IRQHandler(void)
451 {
452     rt_interrupt_enter();
453     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev);
454     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev.parent.user_data, \
455         TIMER_INT_UP);
456     rt_interrupt_leave();
457 }
458 #endif
459 
460 #ifdef BSP_USING_HWTIMER2
TIMER2_IRQHandler(void)461 void TIMER2_IRQHandler(void)
462 {
463     rt_interrupt_enter();
464     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev);
465     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev.parent.user_data, \
466         TIMER_INT_UP);
467     rt_interrupt_leave();
468 }
469 #endif
470 
471 #ifdef BSP_USING_HWTIMER3
TIMER3_IRQHandler(void)472 void TIMER3_IRQHandler(void)
473 {
474     rt_interrupt_enter();
475     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev);
476     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev.parent.user_data, \
477         TIMER_INT_UP);
478     rt_interrupt_leave();
479 }
480 #endif
481 
482 #ifdef BSP_USING_HWTIMER4
TIMER4_IRQHandler(void)483 void TIMER4_IRQHandler(void)
484 {
485     rt_interrupt_enter();
486     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev);
487     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev.parent.user_data, \
488         TIMER_INT_UP);
489     rt_interrupt_leave();
490 }
491 #endif
492 
493 #ifdef BSP_USING_HWTIMER5
TIMER5_IRQHandler(void)494 void TIMER5_IRQHandler(void)
495 {
496     rt_interrupt_enter();
497     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev);
498     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev.parent.user_data, \
499         TIMER_INT_UP);
500     rt_interrupt_leave();
501 }
502 #endif
503 
504 #ifdef BSP_USING_HWTIMER6
TIMER6_IRQHandler(void)505 void TIMER6_IRQHandler(void)
506 {
507     rt_interrupt_enter();
508     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev);
509     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev.parent.user_data, \
510         TIMER_INT_UP);
511     rt_interrupt_leave();
512 }
513 #endif
514 
515 #ifdef BSP_USING_HWTIMER7
TIMER7_UP_IRQHandler(void)516 void TIMER7_UP_IRQHandler(void)
517 {
518     rt_interrupt_enter();
519     rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev);
520     timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev.parent.user_data, \
521         TIMER_INT_UP);
522     rt_interrupt_leave();
523 }
524 #endif
525 
rt_hwtimer_init(void)526 static int rt_hwtimer_init(void)
527 {
528     int ret = 0, i = 0;
529 
530     for (; i < sizeof(g_gd32_hwtimer) / sizeof(g_gd32_hwtimer[0]); i++)
531     {
532         g_gd32_hwtimer[i].hwtimer_dev.ops = &g_gd32_hwtimer_ops;
533         g_gd32_hwtimer[i].hwtimer_dev.info = &g_gd32_hwtimer[i].hwtimer_info;
534 
535         rcu_periph_clock_enable(g_gd32_hwtimer[i].hw_data.rcu);
536         NVIC_SetPriority(g_gd32_hwtimer[i].hw_data.irqn, 0);
537         NVIC_EnableIRQ(g_gd32_hwtimer[i].hw_data.irqn);
538         timer_interrupt_enable(g_gd32_hwtimer[i].hw_data.reg_base, TIMER_INT_UP);
539         ret = rt_device_hwtimer_register(&g_gd32_hwtimer[i].hwtimer_dev, \
540             g_gd32_hwtimer[i].dev_name, (void *)g_gd32_hwtimer[i].hw_data.reg_base);
541         if (RT_EOK != ret)
542         {
543             rt_kprintf("failed register %s, err=%d\n", g_gd32_hwtimer[i].dev_name, \
544                 ret);
545             break;
546         }
547     }
548 
549     return ret;
550 }
551 INIT_BOARD_EXPORT(rt_hwtimer_init);
552 #endif
553