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-20 breo.com first version
9 */
10
11 #include <board.h>
12 #include "drv_hwtimer.h"
13
14 #define DRV_DEBUG
15 #define LOG_TAG "drv.hwtimer"
16 #include <drv_log.h>
17
18 #ifdef BSP_USING_HWTIMER
19 enum
20 {
21 #ifdef BSP_USING_HWTIM1
22 TIM1_INDEX,
23 #endif
24
25 #ifdef BSP_USING_HWTIM2
26 TIM2_INDEX,
27 #endif
28
29 #ifdef BSP_USING_HWTIM3
30 TIM3_INDEX,
31 #endif
32
33 #ifdef BSP_USING_HWTIM4
34 TIM4_INDEX,
35 #endif
36
37 #ifdef BSP_USING_HWTIM5
38 TIM5_INDEX,
39 #endif
40
41 #ifdef BSP_USING_HWTIM6
42 TIM6_INDEX,
43 #endif
44
45 #ifdef BSP_USING_HWTIM7
46 TIM7_INDEX,
47 #endif
48
49 #ifdef BSP_USING_HW_TIM8
50 TIM8_INDEX,
51 #endif
52 };
53
54 struct n32_hwtimer
55 {
56 rt_hwtimer_t time_device;
57 TIM_Module *tim_handle;
58 IRQn_Type tim_irqn;
59 char *name;
60 };
61
62 static struct n32_hwtimer n32_hwtimer_obj[] =
63 {
64 #ifdef BSP_USING_HWTIM1
65 TIM1_CONFIG,
66 #endif
67
68 #ifdef BSP_USING_HWTIM2
69 TIM2_CONFIG,
70 #endif
71
72 #ifdef BSP_USING_HWTIM3
73 TIM3_CONFIG,
74 #endif
75
76 #ifdef BSP_USING_HWTIM4
77 TIM4_CONFIG,
78 #endif
79
80 #ifdef BSP_USING_HWTIM5
81 TIM5_CONFIG,
82 #endif
83
84 #ifdef BSP_USING_HWTIM6
85 TIM6_CONFIG,
86 #endif
87
88 #ifdef BSP_USING_HWTIM7
89 TIM7_CONFIG,
90 #endif
91
92 #ifdef BSP_USING_HWTIM8
93 TIM8_CONFIG,
94 #endif
95 };
96
n32_timer_init(struct rt_hwtimer_device * timer,rt_uint32_t state)97 static void n32_timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
98 {
99 RCC_ClocksType RCC_ClockStruct;
100 TIM_TimeBaseInitType TIM_TimeBaseStructure;
101 NVIC_InitType NVIC_InitStructure;
102 uint32_t freq = 0;
103 uint32_t input_clock;
104 uint32_t prescaler_value = 0;
105 TIM_Module *tim = RT_NULL;
106 struct n32_hwtimer *tim_device = RT_NULL;
107
108 RT_ASSERT(timer != RT_NULL);
109 if (state)
110 {
111 tim = (TIM_Module *)timer->parent.user_data;
112 tim_device = (struct n32_hwtimer *)timer;
113
114 RT_ASSERT((tim == TIM2) || (tim == TIM3) || (tim == TIM4) || (tim == TIM5)
115 || (tim == TIM6) || (tim == TIM7));
116
117 /* timer clock enable */
118 n32_msp_hwtim_init(tim);
119
120 freq = timer->freq;
121 RCC_GetClocksFreqValue(&RCC_ClockStruct);
122 if (1 == (RCC_ClockStruct.HclkFreq / RCC_ClockStruct.Pclk1Freq))
123 input_clock = RCC_ClockStruct.Pclk1Freq;
124 else
125 input_clock = RCC_ClockStruct.Pclk1Freq * 2;
126 prescaler_value = (uint32_t)(input_clock / freq) - 1;
127
128 TIM_TimeBaseStructure.Period = freq - 1;
129 TIM_TimeBaseStructure.Prescaler = prescaler_value;
130 TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
131 TIM_TimeBaseStructure.RepetCnt = 0;
132
133 if (timer->info->cntmode == HWTIMER_CNTMODE_UP)
134 {
135 TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
136 }
137 else
138 {
139 TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_DOWN;
140 }
141
142 TIM_InitTimeBase(tim, &TIM_TimeBaseStructure);
143
144 /* Enable the TIMx global Interrupt */
145 NVIC_InitStructure.NVIC_IRQChannel = tim_device->tim_irqn;
146 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
147 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
148 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
149 NVIC_Init(&NVIC_InitStructure);
150
151 TIM_ConfigInt(tim, TIM_INT_UPDATE, ENABLE);
152 TIM_ClrIntPendingBit(tim, TIM_INT_UPDATE);
153
154 LOG_D("%s init success", tim_device->name);
155 }
156 }
157
n32_timer_start(rt_hwtimer_t * timer,rt_uint32_t t,rt_hwtimer_mode_t opmode)158 static rt_err_t n32_timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
159 {
160 rt_err_t result = RT_EOK;
161 TIM_Module *tim = RT_NULL;
162
163 RT_ASSERT(timer != RT_NULL);
164
165 tim = (TIM_Module *)timer->parent.user_data;
166
167 /* set tim cnt */
168 TIM_SetCnt(tim, 0);
169 /* set tim arr */
170 TIM_SetAutoReload(tim, t - 1);
171 if (opmode == HWTIMER_MODE_ONESHOT)
172 {
173 /* set timer to single mode */
174 TIM_SelectOnePulseMode(tim, TIM_OPMODE_SINGLE);
175 }
176 else
177 {
178 TIM_SelectOnePulseMode(tim, TIM_OPMODE_REPET);
179 }
180
181 /* start timer */
182 TIM_Enable(tim, ENABLE);
183
184 return result;
185 }
186
n32_timer_stop(rt_hwtimer_t * timer)187 static void n32_timer_stop(rt_hwtimer_t *timer)
188 {
189 TIM_Module *tim = RT_NULL;
190
191 RT_ASSERT(timer != RT_NULL);
192
193 tim = (TIM_Module *)timer->parent.user_data;
194
195 /* stop timer */
196 TIM_Enable(tim, DISABLE);
197 /* set tim cnt */
198 TIM_SetCnt(tim, 0);
199 }
200
n32_timer_counter_get(rt_hwtimer_t * timer)201 static rt_uint32_t n32_timer_counter_get(rt_hwtimer_t *timer)
202 {
203 TIM_Module *tim = RT_NULL;
204
205 RT_ASSERT(timer != RT_NULL);
206
207 tim = (TIM_Module *)timer->parent.user_data;
208
209 return tim->CNT;
210 }
211
n32_timer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)212 static rt_err_t n32_timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
213 {
214 RCC_ClocksType RCC_ClockStruct;
215 TIM_Module *tim = RT_NULL;
216 rt_err_t result = RT_EOK;
217
218 RT_ASSERT(timer != RT_NULL);
219 RT_ASSERT(arg != RT_NULL);
220
221 tim = (TIM_Module *)timer->parent.user_data;
222
223 switch (cmd)
224 {
225 case HWTIMER_CTRL_FREQ_SET:
226 {
227 rt_uint32_t input_clock;
228 rt_uint32_t freq;
229 rt_uint16_t val;
230
231 /* set timer frequence */
232 freq = *((rt_uint32_t *)arg);
233
234 /* time init */
235 RCC_GetClocksFreqValue(&RCC_ClockStruct);
236 if (1 == (RCC_ClockStruct.HclkFreq / RCC_ClockStruct.Pclk1Freq))
237 input_clock = RCC_ClockStruct.Pclk1Freq;
238 else
239 input_clock = RCC_ClockStruct.Pclk1Freq * 2;
240 val = input_clock / freq;
241 TIM_ConfigPrescaler(tim, val - 1, TIM_PSC_RELOAD_MODE_IMMEDIATE);
242 }
243 break;
244 default:
245 {
246 result = -RT_ENOSYS;
247 }
248 break;
249 }
250
251 return result;
252 }
253
254 static const struct rt_hwtimer_info _info = TIM_DEV_INFO_CONFIG;
255 static const struct rt_hwtimer_ops _ops =
256 {
257 .init = n32_timer_init,
258 .start = n32_timer_start,
259 .stop = n32_timer_stop,
260 .count_get = n32_timer_counter_get,
261 .control = n32_timer_ctrl,
262 };
263
264 #ifdef BSP_USING_HWTIM2
TIM2_IRQHandler(void)265 void TIM2_IRQHandler(void)
266 {
267 /* enter interrupt */
268 rt_interrupt_enter();
269
270 if (TIM_GetIntStatus(TIM2, TIM_INT_UPDATE) == SET)
271 {
272
273 rt_device_hwtimer_isr(&n32_hwtimer_obj[TIM2_INDEX].time_device);
274 TIM_ClrIntPendingBit(TIM2, TIM_INT_UPDATE);
275
276 }
277 /* leave interrupt */
278 rt_interrupt_leave();
279 }
280 #endif
281
282 #ifdef BSP_USING_HWTIM3
TIM3_IRQHandler(void)283 void TIM3_IRQHandler(void)
284 {
285 /* enter interrupt */
286 rt_interrupt_enter();
287
288 if (TIM_GetIntStatus(TIM3, TIM_INT_UPDATE) == SET)
289 {
290
291 rt_device_hwtimer_isr(&n32_hwtimer_obj[TIM3_INDEX].time_device);
292 TIM_ClrIntPendingBit(TIM3, TIM_INT_UPDATE);
293
294 }
295 /* leave interrupt */
296 rt_interrupt_leave();
297 }
298 #endif
299
300 #ifdef BSP_USING_HWTIM4
TIM4_IRQHandler(void)301 void TIM4_IRQHandler(void)
302 {
303 /* enter interrupt */
304 rt_interrupt_enter();
305
306 if (TIM_GetIntStatus(TIM4, TIM_INT_UPDATE) == SET)
307 {
308
309 rt_device_hwtimer_isr(&n32_hwtimer_obj[TIM4_INDEX].time_device);
310 TIM_ClrIntPendingBit(TIM4, TIM_INT_UPDATE);
311
312 }
313 /* leave interrupt */
314 rt_interrupt_leave();
315 }
316 #endif
317
318 #ifdef BSP_USING_HWTIM5
TIM5_IRQHandler(void)319 void TIM5_IRQHandler(void)
320 {
321 /* enter interrupt */
322 rt_interrupt_enter();
323
324 if (TIM_GetIntStatus(TIM5, TIM_INT_UPDATE) == SET)
325 {
326
327 rt_device_hwtimer_isr(&n32_hwtimer_obj[TIM5_INDEX].time_device);
328 TIM_ClrIntPendingBit(TIM5, TIM_INT_UPDATE);
329
330 }
331 /* leave interrupt */
332 rt_interrupt_leave();
333 }
334 #endif
335
336 #ifdef BSP_USING_HWTIM6
TIM6_IRQHandler(void)337 void TIM6_IRQHandler(void)
338 {
339 /* enter interrupt */
340 rt_interrupt_enter();
341
342 if (TIM_GetIntStatus(TIM6, TIM_INT_UPDATE) == SET)
343 {
344
345 rt_device_hwtimer_isr(&n32_hwtimer_obj[TIM6_INDEX].time_device);
346 TIM_ClrIntPendingBit(TIM6, TIM_INT_UPDATE);
347
348 }
349 /* leave interrupt */
350 rt_interrupt_leave();
351 }
352 #endif
353
354 #ifdef BSP_USING_HWTIM7
TIM7_IRQHandler(void)355 void TIM7_IRQHandler(void)
356 {
357 /* enter interrupt */
358 rt_interrupt_enter();
359
360 if (TIM_GetIntStatus(TIM7, TIM_INT_UPDATE) == SET)
361 {
362
363 rt_device_hwtimer_isr(&n32_hwtimer_obj[TIM7_INDEX].time_device);
364 TIM_ClrIntPendingBit(TIM7, TIM_INT_UPDATE);
365
366 }
367 /* leave interrupt */
368 rt_interrupt_leave();
369 }
370 #endif
371
rt_hw_hwtimer_init(void)372 static int rt_hw_hwtimer_init(void)
373 {
374 int i = 0;
375 int result = RT_EOK;
376
377 for (i = 0; i < sizeof(n32_hwtimer_obj) / sizeof(n32_hwtimer_obj[0]); i++)
378 {
379 n32_hwtimer_obj[i].time_device.info = &_info;
380 n32_hwtimer_obj[i].time_device.ops = &_ops;
381 if (rt_device_hwtimer_register(&n32_hwtimer_obj[i].time_device, n32_hwtimer_obj[i].name, n32_hwtimer_obj[i].tim_handle) == RT_EOK)
382 {
383 LOG_D("%s register success", n32_hwtimer_obj[i].name);
384 }
385 else
386 {
387 LOG_E("%s register failed", n32_hwtimer_obj[i].name);
388 result = -RT_ERROR;
389 }
390 }
391
392 return result;
393 }
394 INIT_BOARD_EXPORT(rt_hw_hwtimer_init);
395
396 #endif /* BSP_USING_HWTIMER */
397
398
399
400
401
402
403
404