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