1 /*
2  * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2023-06-21     CDT               first version
9  * 2024-02-20     CDT               support HC32F448
10  * 2024-06-17     CDT               support HC32F472
11  */
12 
13 #include <rtdevice.h>
14 #include "drv_config.h"
15 
16 // #define DRV_DEBUG
17 #define LOG_TAG             "drv.hwtimer"
18 #include <drv_log.h>
19 
20 #ifdef BSP_USING_HWTIMER
21 
22 #include "drv_irq.h"
23 
24 enum
25 {
26 #ifdef BSP_USING_TMRA_1
27     TMRA_1_INDEX,
28 #endif
29 #ifdef BSP_USING_TMRA_2
30     TMRA_2_INDEX,
31 #endif
32 #ifdef BSP_USING_TMRA_3
33     TMRA_3_INDEX,
34 #endif
35 #ifdef BSP_USING_TMRA_4
36     TMRA_4_INDEX,
37 #endif
38 #ifdef BSP_USING_TMRA_5
39     TMRA_5_INDEX,
40 #endif
41 #ifdef BSP_USING_TMRA_6
42     TMRA_6_INDEX,
43 #endif
44 #ifdef BSP_USING_TMRA_7
45     TMRA_7_INDEX,
46 #endif
47 #ifdef BSP_USING_TMRA_8
48     TMRA_8_INDEX,
49 #endif
50 #ifdef BSP_USING_TMRA_9
51     TMRA_9_INDEX,
52 #endif
53 #ifdef BSP_USING_TMRA_10
54     TMRA_10_INDEX,
55 #endif
56 #ifdef BSP_USING_TMRA_11
57     TMRA_11_INDEX,
58 #endif
59 #ifdef BSP_USING_TMRA_12
60     TMRA_12_INDEX,
61 #endif
62 };
63 
64 struct hc32_hwtimer
65 {
66     rt_hwtimer_t time_device;
67     CM_TMRA_TypeDef *tmr_handle;
68     rt_uint32_t clock_source;
69     rt_uint32_t clock;
70     rt_uint32_t flag;
71     struct
72     {
73         en_int_src_t enIntSrc;
74         IRQn_Type enIRQn;
75         rt_uint8_t u8Int_Prio;
76 #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F4A8)
77         func_ptr_t irq_callback;
78 #endif
79     } isr;
80     char *name;
81 };
82 
83 static struct hc32_hwtimer hc32_hwtimer_obj[] =
84 {
85 #ifdef BSP_USING_TMRA_1
86     TMRA_1_CONFIG,
87 #endif
88 #ifdef BSP_USING_TMRA_2
89     TMRA_2_CONFIG,
90 #endif
91 #ifdef BSP_USING_TMRA_3
92     TMRA_3_CONFIG,
93 #endif
94 #ifdef BSP_USING_TMRA_4
95     TMRA_4_CONFIG,
96 #endif
97 #ifdef BSP_USING_TMRA_5
98     TMRA_5_CONFIG,
99 #endif
100 #ifdef BSP_USING_TMRA_6
101     TMRA_6_CONFIG,
102 #endif
103 #ifdef BSP_USING_TMRA_7
104     TMRA_7_CONFIG,
105 #endif
106 #ifdef BSP_USING_TMRA_8
107     TMRA_8_CONFIG,
108 #endif
109 #ifdef BSP_USING_TMRA_9
110     TMRA_9_CONFIG,
111 #endif
112 #ifdef BSP_USING_TMRA_10
113     TMRA_10_CONFIG,
114 #endif
115 #ifdef BSP_USING_TMRA_11
116     TMRA_11_CONFIG,
117 #endif
118 #ifdef BSP_USING_TMRA_12
119     TMRA_12_CONFIG,
120 #endif
121 };
122 
_timer_init(struct rt_hwtimer_device * timer,rt_uint32_t state)123 static void _timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
124 {
125     stc_tmra_init_t stcTmraInit;
126     struct hc32_irq_config irq_config;
127     struct hc32_hwtimer *tmr_device = (struct hc32_hwtimer *)timer;
128 
129     RT_ASSERT(timer != RT_NULL);
130 
131     /* Interrupt configuration */
132     irq_config.irq_num = tmr_device->isr.enIRQn;
133     irq_config.int_src = tmr_device->isr.enIntSrc;
134     irq_config.irq_prio = tmr_device->isr.u8Int_Prio;
135 
136     if (state)  /* open */
137     {
138         /* Counter Frequency Fixed at maxfreq */
139         timer->freq = timer->info->maxfreq;
140 
141         /* Enable TIMERA clock */
142         FCG_Fcg2PeriphClockCmd(tmr_device->clock, ENABLE);
143 
144         /* TIMERA configuration */
145         (void)TMRA_StructInit(&stcTmraInit);
146         stcTmraInit.sw_count.u8ClockDiv = TMRA_CLK_DIV32;
147         stcTmraInit.u32PeriodValue      = timer->info->maxcnt;
148         (void)TMRA_Init(tmr_device->tmr_handle, &stcTmraInit);
149 
150         TMRA_IntCmd(tmr_device->tmr_handle, TMRA_INT_OVF, ENABLE);
151 #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F4A8)
152         hc32_install_irq_handler(&irq_config, tmr_device->isr.irq_callback, RT_TRUE);
153 #elif defined (HC32F448) || defined (HC32F472)
154         hc32_install_irq_handler(&irq_config, NULL, RT_TRUE);
155 #endif
156     }
157     else    /* close */
158     {
159         TMRA_DeInit(tmr_device->tmr_handle);
160 #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F4A8)
161         hc32_install_irq_handler(&irq_config, tmr_device->isr.irq_callback, RT_FALSE);
162 #elif defined (HC32F448) || defined (HC32F472)
163         hc32_install_irq_handler(&irq_config, NULL, RT_FALSE);
164 #endif
165         FCG_Fcg2PeriphClockCmd(tmr_device->clock, DISABLE);
166     }
167 }
168 
_timer_start(rt_hwtimer_t * timer,rt_uint32_t t,rt_hwtimer_mode_t opmode)169 static rt_err_t _timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
170 {
171     rt_err_t result = RT_EOK;
172     struct hc32_hwtimer *tmr_device = RT_NULL;
173 
174     RT_ASSERT(timer != RT_NULL);
175 
176     tmr_device = (struct hc32_hwtimer *)timer;
177 
178     /* set timer arr */
179     TMRA_SetPeriodValue(tmr_device->tmr_handle, t - 1U);
180     /* start timer */
181     TMRA_Start(tmr_device->tmr_handle);
182 
183     return result;
184 }
185 
_timer_stop(rt_hwtimer_t * timer)186 static void _timer_stop(rt_hwtimer_t *timer)
187 {
188     struct hc32_hwtimer *tmr_device = RT_NULL;
189 
190     RT_ASSERT(timer != RT_NULL);
191 
192     tmr_device = (struct hc32_hwtimer *)timer;
193 
194     /* stop timer */
195     TMRA_Stop(tmr_device->tmr_handle);
196     /* reset timer cnt */
197     TMRA_SetCountValue(tmr_device->tmr_handle, 0U);
198 }
199 
_timer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)200 static rt_err_t _timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
201 {
202     rt_err_t result = -RT_ERROR;
203     uint32_t freq = *(uint32_t *)arg;
204 
205     RT_ASSERT(timer != RT_NULL);
206     RT_ASSERT(arg != RT_NULL);
207 
208     switch (cmd)
209     {
210     case HWTIMER_CTRL_FREQ_SET:
211     {
212         if (freq != timer->freq)
213         {
214             LOG_W("Not Support To Set The Counter Frequency! Default is %d Hz", timer->freq);
215             result = -RT_EINVAL;
216         }
217         else
218         {
219             result = RT_EOK;
220         }
221     }
222     break;
223     default:
224     {
225         result = -RT_EINVAL;
226     }
227     break;
228     }
229 
230     return result;
231 }
232 
_timer_counter_get(rt_hwtimer_t * timer)233 static rt_uint32_t _timer_counter_get(rt_hwtimer_t *timer)
234 {
235     struct hc32_hwtimer *tmr_device = RT_NULL;
236     rt_uint32_t Counter;
237 
238     RT_ASSERT(timer != RT_NULL);
239 
240     tmr_device = (struct hc32_hwtimer *)timer;
241 
242     Counter = TMRA_GetCountValue(tmr_device->tmr_handle);
243 
244     return Counter;
245 }
246 
247 #ifdef BSP_USING_TMRA_1
TMRA_1_callback(void)248 static void TMRA_1_callback(void)
249 {
250     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_1_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_1_INDEX].flag);
251     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_1_INDEX].time_device);
252 }
253 
254 #if defined (HC32F448) || defined (HC32F472)
TMRA_1_Ovf_Udf_Handler(void)255 void TMRA_1_Ovf_Udf_Handler(void)
256 {
257     TMRA_1_callback();
258 }
259 #endif
260 #endif /* BSP_USING_TMRA_1 */
261 
262 #ifdef BSP_USING_TMRA_2
TMRA_2_callback(void)263 static void TMRA_2_callback(void)
264 {
265     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_2_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_2_INDEX].flag);
266     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_2_INDEX].time_device);
267 }
268 
269 #if defined (HC32F448) || defined (HC32F472)
TMRA_2_Ovf_Udf_Handler(void)270 void TMRA_2_Ovf_Udf_Handler(void)
271 {
272     TMRA_2_callback();
273 }
274 #endif
275 #endif /* BSP_USING_TMRA_2 */
276 
277 #ifdef BSP_USING_TMRA_3
TMRA_3_callback(void)278 static void TMRA_3_callback(void)
279 {
280     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_3_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_3_INDEX].flag);
281     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_3_INDEX].time_device);
282 }
283 
284 #if defined (HC32F448) || defined (HC32F472)
TMRA_3_Ovf_Udf_Handler(void)285 void TMRA_3_Ovf_Udf_Handler(void)
286 {
287     TMRA_3_callback();
288 }
289 #endif
290 #endif /* BSP_USING_TMRA_3 */
291 
292 #ifdef BSP_USING_TMRA_4
TMRA_4_callback(void)293 static void TMRA_4_callback(void)
294 {
295     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_4_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_4_INDEX].flag);
296     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_4_INDEX].time_device);
297 }
298 
299 #if defined (HC32F448) || defined (HC32F472)
TMRA_4_Ovf_Udf_Handler(void)300 void TMRA_4_Ovf_Udf_Handler(void)
301 {
302     TMRA_4_callback();
303 }
304 #endif
305 #endif /* BSP_USING_TMRA_4 */
306 
307 #ifdef BSP_USING_TMRA_5
TMRA_5_callback(void)308 static void TMRA_5_callback(void)
309 {
310     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_5_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_5_INDEX].flag);
311     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_5_INDEX].time_device);
312 }
313 
314 #if defined (HC32F448) || defined (HC32F472)
TMRA_5_Ovf_Udf_Handler(void)315 void TMRA_5_Ovf_Udf_Handler(void)
316 {
317     TMRA_5_callback();
318 }
319 #endif
320 #endif /* BSP_USING_TMRA_5 */
321 
322 #ifdef BSP_USING_TMRA_6
TMRA_6_callback(void)323 static void TMRA_6_callback(void)
324 {
325     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_6_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_6_INDEX].flag);
326     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_6_INDEX].time_device);
327 }
328 
329 #if defined (HC32F472)
TMRA_6_Ovf_Udf_Handler(void)330 void TMRA_6_Ovf_Udf_Handler(void)
331 {
332     TMRA_6_callback();
333 }
334 #endif /* HC32F472 */
335 #endif /* BSP_USING_TMRA_6 */
336 
337 #ifdef BSP_USING_TMRA_7
TMRA_7_callback(void)338 static void TMRA_7_callback(void)
339 {
340     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_7_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_7_INDEX].flag);
341     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_7_INDEX].time_device);
342 }
343 #endif /* BSP_USING_TMRA_7 */
344 
345 #ifdef BSP_USING_TMRA_8
TMRA_8_callback(void)346 static void TMRA_8_callback(void)
347 {
348     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_8_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_8_INDEX].flag);
349     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_8_INDEX].time_device);
350 }
351 #endif /* BSP_USING_TMRA_8 */
352 
353 #ifdef BSP_USING_TMRA_9
TMRA_9_callback(void)354 static void TMRA_9_callback(void)
355 {
356     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_9_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_9_INDEX].flag);
357     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_9_INDEX].time_device);
358 }
359 #endif /* BSP_USING_TMRA_9 */
360 
361 #ifdef BSP_USING_TMRA_10
TMRA_10_callback(void)362 static void TMRA_10_callback(void)
363 {
364     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_10_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_10_INDEX].flag);
365     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_10_INDEX].time_device);
366 }
367 #endif /* BSP_USING_TMRA_10 */
368 
369 #ifdef BSP_USING_TMRA_11
TMRA_11_callback(void)370 static void TMRA_11_callback(void)
371 {
372     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_11_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_11_INDEX].flag);
373     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_11_INDEX].time_device);
374 }
375 #endif /* BSP_USING_TMRA_11 */
376 
377 #ifdef BSP_USING_TMRA_12
TMRA_12_callback(void)378 static void TMRA_12_callback(void)
379 {
380     TMRA_ClearStatus(hc32_hwtimer_obj[TMRA_12_INDEX].tmr_handle, hc32_hwtimer_obj[TMRA_12_INDEX].flag);
381     rt_device_hwtimer_isr(&hc32_hwtimer_obj[TMRA_12_INDEX].time_device);
382 }
383 #endif /* BSP_USING_TMRA_12 */
384 
385 static struct rt_hwtimer_info _info[sizeof(hc32_hwtimer_obj) / sizeof(hc32_hwtimer_obj[0])];
386 
tmra_get_info_callback(void)387 void tmra_get_info_callback(void)
388 {
389     /* Div = 32 */
390     for (rt_uint8_t i = 0; i < sizeof(_info) / sizeof(_info[0]); i++)
391     {
392         _info[i].maxcnt  = CLK_GetBusClockFreq(hc32_hwtimer_obj[i].clock_source) / 32U / 1000U; /* Period = 1ms */
393         _info[i].maxfreq = CLK_GetBusClockFreq(hc32_hwtimer_obj[i].clock_source) / 32U;
394         _info[i].minfreq = CLK_GetBusClockFreq(hc32_hwtimer_obj[i].clock_source) / 32U / _info[i].maxcnt;
395         _info[i].cntmode = HWTIMER_CNTMODE_UP;
396     }
397 
398 #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F4A8)
399 #ifdef BSP_USING_TMRA_1
400     hc32_hwtimer_obj[TMRA_1_INDEX].isr.irq_callback = TMRA_1_callback;
401 #endif
402 #ifdef BSP_USING_TMRA_2
403     hc32_hwtimer_obj[TMRA_2_INDEX].isr.irq_callback = TMRA_2_callback;
404 #endif
405 #ifdef BSP_USING_TMRA_3
406     hc32_hwtimer_obj[TMRA_3_INDEX].isr.irq_callback = TMRA_3_callback;
407 #endif
408 #ifdef BSP_USING_TMRA_4
409     hc32_hwtimer_obj[TMRA_4_INDEX].isr.irq_callback = TMRA_4_callback;
410 #endif
411 #ifdef BSP_USING_TMRA_5
412     hc32_hwtimer_obj[TMRA_5_INDEX].isr.irq_callback = TMRA_5_callback;
413 #endif
414 #ifdef BSP_USING_TMRA_6
415     hc32_hwtimer_obj[TMRA_6_INDEX].isr.irq_callback = TMRA_6_callback;
416 #endif
417 #ifdef BSP_USING_TMRA_7
418     hc32_hwtimer_obj[TMRA_7_INDEX].isr.irq_callback = TMRA_7_callback;
419 #endif
420 #ifdef BSP_USING_TMRA_8
421     hc32_hwtimer_obj[TMRA_8_INDEX].isr.irq_callback = TMRA_8_callback;
422 #endif
423 #ifdef BSP_USING_TMRA_9
424     hc32_hwtimer_obj[TMRA_9_INDEX].isr.irq_callback = TMRA_9_callback;
425 #endif
426 #ifdef BSP_USING_TMRA_10
427     hc32_hwtimer_obj[TMRA_10_INDEX].isr.irq_callback = TMRA_10_callback;
428 #endif
429 #ifdef BSP_USING_TMRA_11
430     hc32_hwtimer_obj[TMRA_11_INDEX].isr.irq_callback = TMRA_11_callback;
431 #endif
432 #ifdef BSP_USING_TMRA_12
433     hc32_hwtimer_obj[TMRA_12_INDEX].isr.irq_callback = TMRA_12_callback;
434 #endif
435 #endif
436 }
437 
438 static const struct rt_hwtimer_ops _ops =
439 {
440     .init = _timer_init,
441     .start = _timer_start,
442     .stop = _timer_stop,
443     .count_get = _timer_counter_get,
444     .control = _timer_ctrl,
445 };
446 
rt_hw_hwtimer_init(void)447 static int rt_hw_hwtimer_init(void)
448 {
449     int i;
450     int result = RT_EOK;
451 
452     tmra_get_info_callback();
453     for (i = 0; i < sizeof(hc32_hwtimer_obj) / sizeof(hc32_hwtimer_obj[0]); i++)
454     {
455         hc32_hwtimer_obj[i].time_device.info = &_info[i];
456         hc32_hwtimer_obj[i].time_device.ops  = &_ops;
457         if (rt_device_hwtimer_register(&hc32_hwtimer_obj[i].time_device,
458                                        hc32_hwtimer_obj[i].name, &hc32_hwtimer_obj[i].tmr_handle) == RT_EOK)
459         {
460             LOG_D("%s register success", hc32_hwtimer_obj[i].name);
461         }
462         else
463         {
464             LOG_E("%s register failed", hc32_hwtimer_obj[i].name);
465             result = -RT_ERROR;
466         }
467     }
468 
469     return result;
470 }
471 INIT_BOARD_EXPORT(rt_hw_hwtimer_init);
472 
473 #endif /* BSP_USING_HWTIMER */
474