1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-09-10     MXH          the first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 
14 #ifdef BSP_USING_HWTIMER
15 #define DBG_TAG               "TIM"
16 #define DBG_LVL               DBG_LOG
17 #include <rtdbg.h>
18 
19 #include "drv_hwtimer.h"
20 #include "board.h"
21 
22 #ifdef RT_USING_HWTIMER
23 
24 enum
25 {
26 #ifdef BSP_USING_TIM1
27     TIM1_INDEX,
28 #endif
29 #ifdef BSP_USING_TIM2
30     TIM2_INDEX,
31 #endif
32 #ifdef BSP_USING_TIM3
33     TIM3_INDEX,
34 #endif
35 #ifdef BSP_USING_TIM4
36     TIM4_INDEX,
37 #endif
38 #ifdef BSP_USING_TIM5
39     TIM5_INDEX,
40 #endif
41 #ifdef BSP_USING_TIM6
42     TIM6_INDEX,
43 #endif
44 #ifdef BSP_USING_TIM7
45     TIM7_INDEX,
46 #endif
47 #ifdef BSP_USING_TIM8
48     TIM8_INDEX,
49 #endif
50 #ifdef BSP_USING_TIM9
51     TIM9_INDEX,
52 #endif
53 #ifdef BSP_USING_TIM10
54     TIM10_INDEX,
55 #endif
56 };
57 
58 static struct ch32_hwtimer ch32_hwtimer_obj[] =
59 {
60 #ifdef BSP_USING_TIM1
61     TIM1_CONFIG,
62 #endif
63 
64 #ifdef BSP_USING_TIM2
65     TIM2_CONFIG,
66 #endif
67 
68 #ifdef BSP_USING_TIM3
69     TIM3_CONFIG,
70 #endif
71 
72 #ifdef BSP_USING_TIM4
73     TIM4_CONFIG,
74 #endif
75 
76 #ifdef BSP_USING_TIM5
77     TIM5_CONFIG,
78 #endif
79 
80 #ifdef BSP_USING_TIM6
81     TIM6_CONFIG,
82 #endif
83 
84 #ifdef BSP_USING_TIM7
85     TIM7_CONFIG,
86 #endif
87 
88 #ifdef BSP_USING_TIM8
89     TIM8_CONFIG,
90 #endif
91 
92 #ifdef BSP_USING_TIM9
93     TIM9_CONFIG,
94 #endif
95 
96 #ifdef BSP_USING_TIM10
97     TIM10_CONFIG,
98 #endif
99 };
100 
101 /* APBx timer clocks frequency doubler state related to APB1CLKDivider value */
ch32_get_pclk_doubler(rt_uint32_t * pclk1_doubler,rt_uint32_t * pclk2_doubler)102 void ch32_get_pclk_doubler(rt_uint32_t *pclk1_doubler, rt_uint32_t *pclk2_doubler)
103 {
104     RT_ASSERT(pclk1_doubler != RT_NULL);
105     RT_ASSERT(pclk2_doubler != RT_NULL);
106 
107     *pclk1_doubler = 1;
108     *pclk2_doubler = 1;
109 
110     if((RCC->CFGR0 & RCC_PPRE1) == RCC_PPRE1_DIV1)
111     {
112         *pclk1_doubler = 1;
113     }
114     else
115     {
116         *pclk1_doubler = 2;
117     }
118 
119     if((RCC->CFGR0 & RCC_PPRE2) == RCC_PPRE2_DIV1)
120     {
121         *pclk2_doubler = 1;
122     }
123     else
124     {
125         *pclk2_doubler = 2;
126     }
127 }
128 
ch32_hwtimer_init(struct rt_hwtimer_device * timer,rt_uint32_t state)129 static void ch32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
130 {
131     RT_ASSERT(timer != RT_NULL);
132     TIM_HandleTypeDef *tim = RT_NULL;
133     RCC_ClocksTypeDef RCC_ClockStruct;
134     NVIC_InitTypeDef NVIC_InitStruct;
135     struct ch32_hwtimer *tim_device = RT_NULL;
136     rt_uint32_t prescaler_value = 0;
137     rt_uint32_t pclk1_doubler, pclk2_doubler;
138 
139     RCC_GetClocksFreq(&RCC_ClockStruct);
140     ch32_get_pclk_doubler(&pclk1_doubler, &pclk2_doubler);
141 
142     if(state)
143     {
144         tim = (TIM_HandleTypeDef *)timer->parent.user_data;
145         tim_device = (struct ch32_hwtimer *)timer;
146 
147 #if defined (SOC_RISCV_SERIES_CH32V2)
148         if(tim->instance == TIM1)
149 #elif defined(SOC_RISCV_SERIES_CH32V3)
150         if(tim->instance == TIM1 || tim->instance == TIM8 ||
151                 tim->instance == TIM9 || tim->instance == TIM10)
152 #else
153 #error " unsupported CH32 series! "
154         if(RT_NULL)
155 #endif
156         {
157             RCC_APB2PeriphClockCmd(tim->rcc, ENABLE);
158             prescaler_value = (RCC_ClockStruct.PCLK2_Frequency * pclk2_doubler / 10000) - 1;
159         }
160         else
161         {
162             RCC_APB1PeriphClockCmd(tim->rcc, ENABLE);
163             prescaler_value = (RCC_ClockStruct.PCLK1_Frequency * pclk1_doubler / 10000) - 1;
164         }
165         tim->init.TIM_Prescaler = prescaler_value;
166         tim->init.TIM_ClockDivision = TIM_CKD_DIV1;
167         tim->init.TIM_Period = 10000 - 1;
168         tim->init.TIM_RepetitionCounter = 0;
169 
170         if(timer->info->cntmode == HWTIMER_CNTMODE_UP)
171         {
172             tim->init.TIM_CounterMode = TIM_CounterMode_Up;
173         }
174         else
175         {
176             tim->init.TIM_CounterMode   = TIM_CounterMode_Down;
177         }
178 #if defined (SOC_RISCV_SERIES_CH32V3)
179         /* TIM6 and TIM7 only support counter up mode */
180         if(tim->instance == TIM6 || tim->instance == TIM7)
181         {
182             tim->init.TIM_CounterMode = TIM_CounterMode_Up;
183         }
184 #endif
185         TIM_TimeBaseInit(tim->instance, &tim->init);
186 
187         NVIC_InitStruct.NVIC_IRQChannel = tim_device->irqn;
188         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
189         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
190         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
191         NVIC_Init(&NVIC_InitStruct);
192 
193         TIM_ClearITPendingBit(tim->instance, TIM_IT_Update);
194         TIM_ITConfig(tim->instance, TIM_IT_Update, ENABLE);
195     }
196 }
197 
ch32_hwtimer_start(struct rt_hwtimer_device * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)198 static rt_err_t ch32_hwtimer_start(struct rt_hwtimer_device *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
199 {
200     RT_ASSERT(timer != RT_NULL);
201     TIM_HandleTypeDef *tim = RT_NULL;
202     tim = (TIM_HandleTypeDef *)timer->parent.user_data;
203 
204     /* set tim cnt */
205     tim->instance->CNT = 0;
206     /* set tim arr */
207     tim->instance->ATRLR = cnt - 1;
208     tim->init.TIM_Period = cnt - 1;
209 
210     if (mode == HWTIMER_MODE_ONESHOT)
211     {
212         /* set timer to single mode */
213         tim->instance->CTLR1 &= (rt_uint16_t) ~((rt_uint16_t)TIM_OPM);
214         tim->instance->CTLR1 |= TIM_OPMode_Single;
215     }
216     else
217     {
218         tim->instance->CTLR1 &= (rt_uint16_t) ~((rt_uint16_t)TIM_OPM);
219         tim->instance->CTLR1 |= TIM_OPMode_Repetitive;
220     }
221 
222     /* start timer */
223     TIM_Cmd(tim->instance, ENABLE);
224 
225     return RT_EOK;
226 }
227 
ch32_hwtimer_stop(struct rt_hwtimer_device * timer)228 static void ch32_hwtimer_stop(struct rt_hwtimer_device *timer)
229 {
230     RT_ASSERT(timer != RT_NULL);
231     TIM_HandleTypeDef *tim = RT_NULL;
232 
233     tim = (TIM_HandleTypeDef *)timer->parent.user_data;
234 
235     /* stop timer */
236     TIM_Cmd(tim->instance, DISABLE);
237 
238     /* set tim cnt */
239     tim->instance->CNT = 0;
240 }
241 
ch32_hwtimer_count_get(struct rt_hwtimer_device * timer)242 static rt_uint32_t ch32_hwtimer_count_get(struct rt_hwtimer_device *timer)
243 {
244     RT_ASSERT(timer != RT_NULL);
245     TIM_HandleTypeDef *tim = RT_NULL;
246     tim = (TIM_HandleTypeDef *)timer->parent.user_data;
247 
248     return tim->instance->CNT;
249 }
250 
ch32_hwtimer_control(struct rt_hwtimer_device * timer,rt_uint32_t cmd,void * args)251 static rt_err_t ch32_hwtimer_control(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args)
252 {
253     RT_ASSERT(timer != RT_NULL);
254     RT_ASSERT(args != RT_NULL);
255 
256     TIM_HandleTypeDef *tim = RT_NULL;
257     rt_err_t result = RT_EOK;
258     rt_uint32_t pclk1_doubler, pclk2_doubler;
259 
260     tim = (TIM_HandleTypeDef *)timer->parent.user_data;
261 
262     switch (cmd)
263     {
264     case HWTIMER_CTRL_FREQ_SET:
265     {
266         rt_uint32_t freq;
267         rt_uint16_t val;
268         RCC_ClocksTypeDef RCC_ClockStruct;
269 
270         /* set timer frequence */
271         freq = *((rt_uint32_t *)args);
272 
273         ch32_get_pclk_doubler(&pclk1_doubler, &pclk2_doubler);
274         RCC_GetClocksFreq(&RCC_ClockStruct);
275 
276 #if defined (SOC_RISCV_SERIES_CH32V2)
277         if(tim->instance == TIM1)
278 #elif defined(SOC_RISCV_SERIES_CH32V3)
279         if(tim->instance == TIM1 || tim->instance == TIM8 ||
280                 tim->instance == TIM9 || tim->instance == TIM10)
281 #else
282 #error " unsupported CH32 series! "
283         if(RT_NULL)
284 #endif
285         {
286             val = RCC_ClockStruct.PCLK2_Frequency * pclk2_doubler / freq;
287         }
288         else
289         {
290             val = RCC_ClockStruct.PCLK1_Frequency * pclk1_doubler / freq;
291         }
292 
293         /* Update frequency value */
294         TIM_PrescalerConfig(tim->instance, val - 1, TIM_PSCReloadMode_Immediate);
295 
296         result = RT_EOK;
297         break;
298     }
299 
300     case HWTIMER_CTRL_MODE_SET:
301     {
302         if (*(rt_hwtimer_mode_t *)args == HWTIMER_MODE_ONESHOT)
303         {
304             /* set timer to single mode */
305             tim->instance->CTLR1 &= (rt_uint16_t) ~((rt_uint16_t)TIM_OPM);
306             tim->instance->CTLR1 |= TIM_OPMode_Single;
307         }
308         else
309         {
310             tim->instance->CTLR1 &= (rt_uint16_t) ~((rt_uint16_t)TIM_OPM);
311             tim->instance->CTLR1 |= TIM_OPMode_Repetitive;
312         }
313         break;
314     }
315 
316     case HWTIMER_CTRL_INFO_GET:
317     {
318         *(rt_hwtimer_mode_t *)args = tim->instance->CNT;
319         break;
320     }
321 
322     case HWTIMER_CTRL_STOP:
323     {
324         ch32_hwtimer_stop(timer);
325         break;
326     }
327 
328     default:
329     {
330         result = -RT_EINVAL;
331         break;
332     }
333     }
334 
335     return result;
336 }
337 
338 static const struct rt_hwtimer_info ch32_hwtimer_info = TIM_DEV_INFO_CONFIG;
339 static const struct rt_hwtimer_ops ch32_hwtimer_ops =
340 {
341     ch32_hwtimer_init,
342     ch32_hwtimer_start,
343     ch32_hwtimer_stop,
344     ch32_hwtimer_count_get,
345     ch32_hwtimer_control
346 };
347 
ch32_hwtimer_isr(struct rt_hwtimer_device * device)348 static void ch32_hwtimer_isr(struct rt_hwtimer_device *device)
349 {
350     RT_ASSERT(device != RT_NULL);
351     struct ch32_hwtimer *hwtimer = RT_NULL;
352     hwtimer = rt_container_of(device, struct ch32_hwtimer, device);
353 
354     if(TIM_GetITStatus(hwtimer->handle.instance, TIM_IT_Update) != RESET)
355     {
356         rt_device_hwtimer_isr(device);
357         TIM_ClearITPendingBit(hwtimer->handle.instance, TIM_IT_Update);
358     }
359 }
360 
361 #ifdef BSP_USING_TIM1
362 void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM1_UP_IRQHandler(void)363 void TIM1_UP_IRQHandler(void)
364 {
365     GET_INT_SP();
366     rt_interrupt_enter();
367     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM1_INDEX].device));
368     rt_interrupt_leave();
369     FREE_INT_SP();
370 }
371 #endif /* BSP_USING_TIM1 */
372 
373 #ifdef BSP_USING_TIM2
374 void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM2_IRQHandler(void)375 void TIM2_IRQHandler(void)
376 {
377     GET_INT_SP();
378     rt_interrupt_enter();
379     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM2_INDEX].device));
380     rt_interrupt_leave();
381     FREE_INT_SP();
382 }
383 #endif /* BSP_USING_TIM2 */
384 
385 #ifdef BSP_USING_TIM3
386 void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM3_IRQHandler(void)387 void TIM3_IRQHandler(void)
388 {
389     GET_INT_SP();
390     rt_interrupt_enter();
391     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM3_INDEX].device));
392     rt_interrupt_leave();
393     FREE_INT_SP();
394 }
395 #endif /* BSP_USING_TIM3 */
396 
397 #ifdef BSP_USING_TIM4
398 void TIM4_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM4_IRQHandler(void)399 void TIM4_IRQHandler(void)
400 {
401     GET_INT_SP();
402     rt_interrupt_enter();
403     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM4_INDEX].device));
404     rt_interrupt_leave();
405     FREE_INT_SP();
406 }
407 #endif /* BSP_USING_TIM4 */
408 
409 #ifdef BSP_USING_TIM5
410 void TIM5_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM5_IRQHandler(void)411 void TIM5_IRQHandler(void)
412 {
413     GET_INT_SP();
414     rt_interrupt_enter();
415     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM5_INDEX].device));
416     rt_interrupt_leave();
417     FREE_INT_SP();
418 }
419 #endif /* BSP_USING_TIM5 */
420 
421 #ifdef BSP_USING_TIM6
422 void TIM6_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM6_IRQHandler(void)423 void TIM6_IRQHandler(void)
424 {
425     GET_INT_SP();
426     rt_interrupt_enter();
427     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM6_INDEX].device));
428     rt_interrupt_leave();
429     FREE_INT_SP();
430 }
431 #endif /* BSP_USING_TIM6 */
432 
433 #ifdef BSP_USING_TIM7
434 void TIM7_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM7_IRQHandler(void)435 void TIM7_IRQHandler(void)
436 {
437     GET_INT_SP();
438     rt_interrupt_enter();
439     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM7_INDEX].device));
440     rt_interrupt_leave();
441     FREE_INT_SP();
442 }
443 #endif /* BSP_USING_TIM7 */
444 
445 #ifdef BSP_USING_TIM8
446 void TIM8_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM8_UP_IRQHandler(void)447 void TIM8_UP_IRQHandler(void)
448 {
449     GET_INT_SP();
450     rt_interrupt_enter();
451     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM8_INDEX].device));
452     rt_interrupt_leave();
453     FREE_INT_SP();
454 }
455 #endif /* BSP_USING_TIM8 */
456 
457 #ifdef BSP_USING_TIM9
458 void TIM9_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM9_UP_IRQHandler(void)459 void TIM9_UP_IRQHandler(void)
460 {
461     GET_INT_SP();
462     rt_interrupt_enter();
463     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM9_INDEX].device));
464     rt_interrupt_leave();
465     FREE_INT_SP();
466 }
467 #endif /* BSP_USING_TIM9 */
468 
469 #ifdef BSP_USING_TIM10
470 void TIM10_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
TIM10_UP_IRQHandler(void)471 void TIM10_UP_IRQHandler(void)
472 {
473     GET_INT_SP();
474     rt_interrupt_enter();
475     ch32_hwtimer_isr(&(ch32_hwtimer_obj[TIM10_INDEX].device));
476     rt_interrupt_leave();
477     FREE_INT_SP();
478 }
479 #endif /* BSP_USING_TIM10 */
480 
rt_hw_timer_init(void)481 static int rt_hw_timer_init(void)
482 {
483     int i = 0;
484     int result = RT_EOK;
485 
486     for (i = 0; i < sizeof(ch32_hwtimer_obj) / sizeof(ch32_hwtimer_obj[0]); i++)
487     {
488         ch32_hwtimer_obj[i].device.info = &ch32_hwtimer_info;
489         ch32_hwtimer_obj[i].device.ops  = &ch32_hwtimer_ops;
490         result = rt_device_hwtimer_register(&ch32_hwtimer_obj[i].device,
491                     ch32_hwtimer_obj[i].name, (void *)&ch32_hwtimer_obj[i].handle);
492         RT_ASSERT(result == RT_EOK);
493     }
494 
495     return result;
496 }
497 INIT_BOARD_EXPORT(rt_hw_timer_init);
498 
499 #endif /* RT_USING_HWTIMER */
500 #endif /* BSP_USING_HWTIMER */
501