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  * 2021-08-10     charlown           first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <board.h>
14 
15 #ifdef BSP_USING_HWTIMER
16 
17 #define LOG_TAG "drv.hwtimer"
18 #include <drv_log.h>
19 
20 struct hwtimer_device
21 {
22     struct rt_hwtimer_device parent;
23     TIM_TypeDef *periph;
24     IRQn_Type irqn;
25     char *name;
26 };
27 
28 #ifdef BSP_USING_TIM1_HWTIMER
29 struct hwtimer_device hwtimer_device1 =
30     {
31         .periph = TIM1,
32         .irqn = TIM1_UP_IRQn,
33         .name = "timer1"};
34 #endif
35 
36 #ifdef BSP_USING_TIM2_HWTIMER
37 struct hwtimer_device hwtimer_device2 =
38     {
39         .periph = TIM2,
40         .irqn = TIM2_IRQn,
41         .name = "timer2"};
42 #endif
43 
44 #ifdef BSP_USING_TIM3_HWTIMER
45 struct hwtimer_device hwtimer_device3 =
46     {
47         .periph = TIM3,
48         .irqn = TIM3_IRQn,
49         .name = "timer3"};
50 #endif
51 
52 #ifdef BSP_USING_TIM4_HWTIMER
53 struct hwtimer_device hwtimer_device4 =
54     {
55         .periph = TIM4,
56         .irqn = TIM4_IRQn,
57         .name = "timer4"};
58 #endif
59 
ch32f1_hwtimer_init(struct rt_hwtimer_device * device,rt_uint32_t state)60 static void ch32f1_hwtimer_init(struct rt_hwtimer_device *device, rt_uint32_t state)
61 {
62     struct hwtimer_device *hwtimer_dev;
63     struct rt_hwtimer_info *hwtimer_info;
64     rt_uint32_t clk = 0;
65     rt_uint16_t prescaler_value = 0;
66 
67     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitType;
68     NVIC_InitTypeDef NVIC_InitStructure;
69 
70     RT_ASSERT(device != RT_NULL);
71 
72     hwtimer_dev = (struct hwtimer_device *)device;
73 
74     if (state)
75     {
76         ch32f1_tim_clock_init(hwtimer_dev->periph);
77 
78         hwtimer_info = ch32f1_hwtimer_info_config_get(hwtimer_dev->periph);
79 
80         clk = ch32f1_tim_clock_get(hwtimer_dev->periph);
81 
82         prescaler_value = (rt_uint16_t)(clk / hwtimer_info->minfreq) - 1;
83 
84         /*
85         * (1 / freq) = (cnt + 1) * (1 / (clk/(prescaler_value + 1) ) )
86         */
87 
88         TIM_TimeBaseInitType.TIM_Period = hwtimer_info->maxcnt - 1;
89         TIM_TimeBaseInitType.TIM_Prescaler = prescaler_value;
90         TIM_TimeBaseInitType.TIM_ClockDivision = TIM_CKD_DIV1;
91         TIM_TimeBaseInitType.TIM_RepetitionCounter = 0;
92 
93         if (hwtimer_info == RT_NULL)
94         {
95             TIM_TimeBaseInitType.TIM_CounterMode = TIM_CounterMode_Up;
96         }
97         else
98         {
99             if (hwtimer_info->cntmode == HWTIMER_CNTMODE_UP)
100             {
101                 TIM_TimeBaseInitType.TIM_CounterMode = TIM_CounterMode_Up;
102             }
103             else
104             {
105                 TIM_TimeBaseInitType.TIM_CounterMode = TIM_CounterMode_Down;
106             }
107         }
108 
109         TIM_TimeBaseInit(hwtimer_dev->periph, &TIM_TimeBaseInitType);
110 
111         NVIC_InitStructure.NVIC_IRQChannel = hwtimer_dev->irqn;
112         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
113         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
114         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
115         NVIC_Init(&NVIC_InitStructure);
116 
117         TIM_ITConfig(hwtimer_dev->periph, TIM_IT_Update, ENABLE);
118         TIM_ClearITPendingBit(hwtimer_dev->periph, TIM_IT_Update);
119 
120         LOG_D("%s init success", hwtimer_dev->name);
121     }
122 }
123 
ch32f1_hwtimer_start(struct rt_hwtimer_device * device,rt_uint32_t cnt,rt_hwtimer_mode_t mode)124 static rt_err_t ch32f1_hwtimer_start(struct rt_hwtimer_device *device, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
125 {
126 
127     struct hwtimer_device *hwtimer_dev;
128 
129     RT_ASSERT(device != RT_NULL);
130 
131     hwtimer_dev = (struct hwtimer_device *)device;
132 
133     /*
134     * (1 / freq) = (cnt + 1) * (1 / (clk/(prescaler_value + 1) ) )
135     */
136 
137     TIM_SetCounter(hwtimer_dev->periph, 0);
138     TIM_SetAutoreload(hwtimer_dev->periph, cnt - 1);
139 
140     if (mode == HWTIMER_MODE_ONESHOT)
141     {
142         TIM_SelectOnePulseMode(hwtimer_dev->periph, TIM_OPMode_Single);
143     }
144     else
145     {
146         TIM_SelectOnePulseMode(hwtimer_dev->periph, TIM_OPMode_Repetitive);
147     }
148 
149     TIM_Cmd(hwtimer_dev->periph, ENABLE);
150 
151     LOG_D("%s start, cnt = %d", hwtimer_dev->name, cnt);
152 
153     return RT_EOK;
154 }
155 
ch32f1_hwtimer_stop(struct rt_hwtimer_device * device)156 static void ch32f1_hwtimer_stop(struct rt_hwtimer_device *device)
157 {
158     struct hwtimer_device *hwtimer_dev;
159 
160     RT_ASSERT(device != RT_NULL);
161 
162     hwtimer_dev = (struct hwtimer_device *)device;
163 
164     TIM_Cmd(hwtimer_dev->periph, DISABLE);
165 
166     TIM_SetCounter(hwtimer_dev->periph, 0);
167 }
168 
ch32f1_hwtimer_counter_get(struct rt_hwtimer_device * device)169 static rt_uint32_t ch32f1_hwtimer_counter_get(struct rt_hwtimer_device *device)
170 {
171     struct hwtimer_device *hwtimer_dev;
172 
173     RT_ASSERT(device != RT_NULL);
174 
175     hwtimer_dev = (struct hwtimer_device *)device;
176 
177     return hwtimer_dev->periph->CNT;
178 }
179 
ch32f1_hwtimer_control(struct rt_hwtimer_device * device,rt_uint32_t cmd,void * arg)180 static rt_err_t ch32f1_hwtimer_control(struct rt_hwtimer_device *device, rt_uint32_t cmd, void *arg)
181 {
182     struct hwtimer_device *hwtimer_dev;
183     rt_err_t result = RT_EOK;
184 
185     RT_ASSERT(device != RT_NULL);
186 
187     hwtimer_dev = (struct hwtimer_device *)device;
188 
189     switch (cmd)
190     {
191     case HWTIMER_CTRL_FREQ_SET:
192     {
193         rt_uint32_t freq = 0;
194         rt_uint32_t clk = 0;
195         rt_uint16_t prescaler_value = 0;
196 
197         /*
198         * (1 / freq) = (cnt + 1) * (1 / (clk/(prescaler_value + 1) ) )
199         */
200         if (arg != RT_NULL)
201         {
202 
203             freq = *((rt_uint32_t *)arg);
204 
205             clk = ch32f1_tim_clock_get(hwtimer_dev->periph);
206 
207             prescaler_value = (rt_uint16_t)(clk / freq) - 1;
208 
209             TIM_PrescalerConfig(hwtimer_dev->periph, prescaler_value, TIM_PSCReloadMode_Immediate);
210         }
211         else
212         {
213             result = -RT_EINVAL;
214         }
215     }
216     break;
217 
218     default:
219         result = -RT_ENOSYS;
220         break;
221     }
222 
223     return result;
224 }
225 
226 static const struct rt_hwtimer_ops hwtimer_ops =
227     {
228         .init = ch32f1_hwtimer_init,
229         .start = ch32f1_hwtimer_start,
230         .stop = ch32f1_hwtimer_stop,
231         .count_get = ch32f1_hwtimer_counter_get,
232         .control = ch32f1_hwtimer_control,
233 };
234 
rt_hw_hwtimer_init(void)235 static int rt_hw_hwtimer_init(void)
236 {
237     rt_err_t ret;
238     struct rt_hwtimer_info *hwtimer_info;
239 
240 #ifdef BSP_USING_TIM1_HWTIMER
241     hwtimer_info = ch32f1_hwtimer_info_config_get(hwtimer_device1.periph);
242     hwtimer_device1.parent.info = hwtimer_info;
243     hwtimer_device1.parent.ops = &hwtimer_ops;
244     ret = rt_device_hwtimer_register(&hwtimer_device1.parent, hwtimer_device1.name, RT_NULL);
245     if (ret == RT_EOK)
246     {
247         LOG_D("hwtimer: %s register success.", hwtimer_device1.name);
248     }
249     else
250     {
251         LOG_D("hwtimer: %s register failed.", hwtimer_device1.name);
252     }
253 #endif
254 
255 #ifdef BSP_USING_TIM2_HWTIMER
256     hwtimer_info = ch32f1_hwtimer_info_config_get(hwtimer_device2.periph);
257     hwtimer_device2.parent.info = hwtimer_info;
258     hwtimer_device2.parent.ops = &hwtimer_ops;
259     ret = rt_device_hwtimer_register(&hwtimer_device2.parent, hwtimer_device2.name, RT_NULL);
260     if (ret == RT_EOK)
261     {
262         LOG_D("hwtimer: %s register success.", hwtimer_device2.name);
263     }
264     else
265     {
266         LOG_D("hwtimer: %s register failed.", hwtimer_device2.name);
267     }
268 #endif
269 
270 #ifdef BSP_USING_TIM3_HWTIMER
271     hwtimer_info = ch32f1_hwtimer_info_config_get(hwtimer_device3.periph);
272     hwtimer_device3.parent.info = hwtimer_info;
273     hwtimer_device3.parent.ops = &hwtimer_ops;
274     ret = rt_device_hwtimer_register(&hwtimer_device3.parent, hwtimer_device3.name, RT_NULL);
275     if (ret == RT_EOK)
276     {
277         LOG_D("hwtimer: %s register success.", hwtimer_device3.name);
278     }
279     else
280     {
281         LOG_D("hwtimer: %s register failed.", hwtimer_device3.name);
282     }
283 #endif
284 
285 #ifdef BSP_USING_TIM4_HWTIMER
286     hwtimer_info = ch32f1_hwtimer_info_config_get(hwtimer_device4.periph);
287     hwtimer_device4.parent.info = hwtimer_info;
288     hwtimer_device4.parent.ops = &hwtimer_ops;
289     ret = rt_device_hwtimer_register(&hwtimer_device4.parent, hwtimer_device4.name, RT_NULL);
290     if (ret == RT_EOK)
291     {
292         LOG_D("hwtimer: %s register success.", hwtimer_device4.name);
293     }
294     else
295     {
296         LOG_D("hwtimer: %s register failed.", hwtimer_device4.name);
297     }
298 #endif
299 
300     return RT_EOK;
301 }
302 INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
303 
304 #ifdef BSP_USING_TIM1_HWTIMER
TIM1_UP_IRQHandler(void)305 void TIM1_UP_IRQHandler(void)
306 {
307     /* enter interrupt */
308     rt_interrupt_enter();
309 
310     if (TIM_GetITStatus(hwtimer_device1.periph, TIM_IT_Update) == SET)
311     {
312         TIM_ClearITPendingBit(hwtimer_device1.periph, TIM_IT_Update);
313         rt_device_hwtimer_isr(&hwtimer_device1.parent);
314     }
315     /* leave interrupt */
316     rt_interrupt_leave();
317 }
318 #endif
319 
320 #ifdef BSP_USING_TIM2_HWTIMER
TIM2_IRQHandler(void)321 void TIM2_IRQHandler(void)
322 {
323     /* enter interrupt */
324     rt_interrupt_enter();
325 
326     if (TIM_GetITStatus(hwtimer_device2.periph, TIM_IT_Update) == SET)
327     {
328         TIM_ClearITPendingBit(hwtimer_device2.periph, TIM_IT_Update);
329         rt_device_hwtimer_isr(&hwtimer_device2.parent);
330     }
331     /* leave interrupt */
332     rt_interrupt_leave();
333 }
334 #endif
335 
336 #ifdef BSP_USING_TIM3_HWTIMER
TIM3_IRQHandler(void)337 void TIM3_IRQHandler(void)
338 {
339     /* enter interrupt */
340     rt_interrupt_enter();
341 
342     if (TIM_GetITStatus(hwtimer_device3.periph, TIM_IT_Update) == SET)
343     {
344         TIM_ClearITPendingBit(hwtimer_device3.periph, TIM_IT_Update);
345         rt_device_hwtimer_isr(&hwtimer_device3.parent);
346     }
347     /* leave interrupt */
348     rt_interrupt_leave();
349 }
350 #endif
351 
352 #ifdef BSP_USING_TIM4_HWTIMER
TIM4_IRQHandler(void)353 void TIM4_IRQHandler(void)
354 {
355     /* enter interrupt */
356     rt_interrupt_enter();
357 
358     if (TIM_GetITStatus(hwtimer_device4.periph, TIM_IT_Update) == SET)
359     {
360         TIM_ClearITPendingBit(hwtimer_device4.periph, TIM_IT_Update);
361         rt_device_hwtimer_isr(&hwtimer_device4.parent);
362     }
363     /* leave interrupt */
364     rt_interrupt_leave();
365 }
366 #endif
367 
368 #endif /* BSP_USING_HWTIMER */
369