1 /**************************************************************************//**
2 *
3 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2020-2-7 YCHuang12 First version
10 *
11 ******************************************************************************/
12
13 #include <rtconfig.h>
14
15 #if (defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER))
16
17 #include <rtdevice.h>
18 #include "NuMicro.h"
19
20 /* Private define ---------------------------------------------------------------*/
21 #define NU_TIMER_DEVICE(timer) (nu_timer_t *)(timer)
22
23 /* Private typedef --------------------------------------------------------------*/
24 typedef struct nu_timer
25 {
26 rt_hwtimer_t parent;
27 TIMER_T *timer_periph;
28 IRQn_Type IRQn;
29 } nu_timer_t;
30
31 /* Private functions ------------------------------------------------------------*/
32 static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state);
33 static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode);
34 static void nu_timer_stop(rt_hwtimer_t *timer);
35 static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer);
36 static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
37
38 /* Public functions -------------------------------------------------------------*/
39
40
41 /* Private variables ------------------------------------------------------------*/
42 #ifdef BSP_USING_TIMER0
43 static nu_timer_t nu_timer0;
44 #endif
45
46 #ifdef BSP_USING_TIMER1
47 static nu_timer_t nu_timer1;
48 #endif
49
50 #ifdef BSP_USING_TIMER2
51 static nu_timer_t nu_timer2;
52 #endif
53
54 #ifdef BSP_USING_TIMER3
55 static nu_timer_t nu_timer3;
56 #endif
57
58 static struct rt_hwtimer_info nu_timer_info =
59 {
60 12000000, /* maximum count frequency */
61 46875, /* minimum count frequency */
62 0xFFFFFF, /* the maximum counter value */
63 HWTIMER_CNTMODE_UP,/* Increment or Decreasing count mode */
64 };
65
66 static struct rt_hwtimer_ops nu_timer_ops =
67 {
68 nu_timer_init,
69 nu_timer_start,
70 nu_timer_stop,
71 nu_timer_count_get,
72 nu_timer_control
73 };
74
75 /* Functions define ------------------------------------------------------------*/
nu_timer_init(rt_hwtimer_t * timer,rt_uint32_t state)76 static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
77 {
78 RT_ASSERT(timer != RT_NULL);
79
80 nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data);
81 RT_ASSERT(nu_timer != RT_NULL);
82 RT_ASSERT(nu_timer->timer_periph != RT_NULL);
83
84 if (1 == state)
85 {
86 uint32_t timer_clk;
87 struct rt_hwtimer_info *info = &nu_timer_info;
88
89 timer_clk = TIMER_GetModuleClock(nu_timer->timer_periph);
90 info->maxfreq = timer_clk;
91 info->minfreq = timer_clk / 256;
92 TIMER_Open(nu_timer->timer_periph, TIMER_ONESHOT_MODE, 1);
93 TIMER_EnableInt(nu_timer->timer_periph);
94 NVIC_EnableIRQ(nu_timer->IRQn);
95 }
96 else
97 {
98 NVIC_DisableIRQ(nu_timer->IRQn);
99 TIMER_DisableInt(nu_timer->timer_periph);
100 TIMER_Close(nu_timer->timer_periph);
101 }
102 }
103
nu_timer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t opmode)104 static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode)
105 {
106 rt_err_t err = RT_EOK;
107 RT_ASSERT(timer != RT_NULL);
108
109 nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data);
110 RT_ASSERT(nu_timer != RT_NULL);
111 RT_ASSERT(nu_timer->timer_periph != RT_NULL);
112
113 if (cnt > 1 && cnt <= 0xFFFFFF)
114 {
115 TIMER_SET_CMP_VALUE(nu_timer->timer_periph, cnt);
116 }
117 else
118 {
119 rt_kprintf("nu_timer_start set compared value failed\n");
120 err = -RT_ERROR;
121 }
122
123 if (HWTIMER_MODE_PERIOD == opmode)
124 {
125 TIMER_SET_OPMODE(nu_timer->timer_periph, TIMER_PERIODIC_MODE);
126 }
127 else if (HWTIMER_MODE_ONESHOT == opmode)
128 {
129 TIMER_SET_OPMODE(nu_timer->timer_periph, TIMER_ONESHOT_MODE);
130 }
131 else
132 {
133 rt_kprintf("nu_timer_start set operation mode failed\n");
134 err = -RT_ERROR;
135 }
136
137 TIMER_Start(nu_timer->timer_periph);
138
139 return err;
140 }
141
nu_timer_stop(rt_hwtimer_t * timer)142 static void nu_timer_stop(rt_hwtimer_t *timer)
143 {
144 RT_ASSERT(timer != RT_NULL);
145
146 nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data);
147 RT_ASSERT(nu_timer != RT_NULL);
148 RT_ASSERT(nu_timer->timer_periph != RT_NULL);
149
150 TIMER_Stop(nu_timer->timer_periph);
151 }
152
nu_timer_count_get(rt_hwtimer_t * timer)153 static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer)
154 {
155 RT_ASSERT(timer != RT_NULL);
156
157 nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data);
158 RT_ASSERT(nu_timer != RT_NULL);
159 RT_ASSERT(nu_timer->timer_periph != RT_NULL);
160
161 return TIMER_GetCounter(nu_timer->timer_periph);
162 }
163
nu_timer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)164 static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
165 {
166 rt_err_t ret = RT_EOK;
167
168 RT_ASSERT(timer != RT_NULL);
169
170 nu_timer_t *nu_timer = NU_TIMER_DEVICE(timer->parent.user_data);
171 RT_ASSERT(nu_timer != RT_NULL);
172 RT_ASSERT(nu_timer->timer_periph != RT_NULL);
173
174 switch (cmd)
175 {
176 case HWTIMER_CTRL_FREQ_SET:
177 {
178 uint32_t clk;
179 uint32_t pre;
180
181 clk = TIMER_GetModuleClock(nu_timer->timer_periph);
182 pre = clk / *((uint32_t *)args) - 1;
183 TIMER_SET_PRESCALE_VALUE(nu_timer->timer_periph, pre);
184 *((uint32_t *)args) = clk / (pre + 1) ;
185 }
186 break;
187
188 case HWTIMER_CTRL_STOP:
189 TIMER_Stop(nu_timer->timer_periph);
190 break;
191
192 default:
193 ret = -RT_EINVAL;
194 break;
195 }
196
197 return ret;
198 }
199
rt_hw_timer_init(void)200 int rt_hw_timer_init(void)
201 {
202 rt_err_t ret = RT_EOK;
203
204 #ifdef BSP_USING_TIMER0
205 nu_timer0.timer_periph = TIMER0;
206 nu_timer0.parent.info = &nu_timer_info;
207 nu_timer0.parent.ops = &nu_timer_ops;
208 nu_timer0.IRQn = TMR0_IRQn;
209 ret = rt_device_hwtimer_register(&nu_timer0.parent, "timer0", &nu_timer0);
210 if (ret != RT_EOK)
211 {
212 rt_kprintf("timer0 register failed\n");
213 }
214 SYS_ResetModule(TMR0_RST);
215 CLK_EnableModuleClock(TMR0_MODULE);
216 #endif
217
218 #ifdef BSP_USING_TIMER1
219 nu_timer1.timer_periph = TIMER1;
220 nu_timer1.parent.info = &nu_timer_info;
221 nu_timer1.parent.ops = &nu_timer_ops;
222 nu_timer1.IRQn = TMR1_IRQn;
223 ret = rt_device_hwtimer_register(&nu_timer1.parent, "timer1", &nu_timer1);
224 if (ret != RT_EOK)
225 {
226 rt_kprintf("timer1 register failed\n");
227 }
228 SYS_ResetModule(TMR1_RST);
229 CLK_EnableModuleClock(TMR1_MODULE);
230 #endif
231
232 #ifdef BSP_USING_TIMER2
233 nu_timer2.timer_periph = TIMER2;
234 nu_timer2.parent.info = &nu_timer_info;
235 nu_timer2.parent.ops = &nu_timer_ops;
236 nu_timer2.IRQn = TMR2_IRQn;
237 ret = rt_device_hwtimer_register(&nu_timer2.parent, "timer2", &nu_timer2);
238 if (ret != RT_EOK)
239 {
240 rt_kprintf("timer2 register failed\n");
241 }
242 SYS_ResetModule(TMR2_RST);
243 CLK_EnableModuleClock(TMR2_MODULE);
244 #endif
245
246 #ifdef BSP_USING_TIMER3
247 nu_timer3.timer_periph = TIMER3;
248 nu_timer3.parent.info = &nu_timer_info;
249 nu_timer3.parent.ops = &nu_timer_ops;
250 nu_timer3.IRQn = TMR3_IRQn;
251 ret = rt_device_hwtimer_register(&nu_timer3.parent, "timer3", &nu_timer3);
252 if (ret != RT_EOK)
253 {
254 rt_kprintf("timer3 register failed\n");
255 }
256 SYS_ResetModule(TMR3_RST);
257 CLK_EnableModuleClock(TMR3_MODULE);
258 #endif
259
260 return ret;
261 }
262
263 INIT_BOARD_EXPORT(rt_hw_timer_init);
264
265 #ifdef BSP_USING_TIMER0
TMR0_IRQHandler(void)266 void TMR0_IRQHandler(void)
267 {
268 rt_interrupt_enter();
269
270 if (TIMER_GetIntFlag(TIMER0))
271 {
272 TIMER_ClearIntFlag(TIMER0);
273 rt_device_hwtimer_isr(&nu_timer0.parent);
274 }
275
276 rt_interrupt_leave();
277 }
278 #endif
279
280 #ifdef BSP_USING_TIMER1
TMR1_IRQHandler(void)281 void TMR1_IRQHandler(void)
282 {
283 rt_interrupt_enter();
284
285 if (TIMER_GetIntFlag(TIMER1))
286 {
287 TIMER_ClearIntFlag(TIMER1);
288 rt_device_hwtimer_isr(&nu_timer1.parent);
289 }
290
291 rt_interrupt_leave();
292 }
293 #endif
294
295 #ifdef BSP_USING_TIMER2
TMR2_IRQHandler(void)296 void TMR2_IRQHandler(void)
297 {
298 rt_interrupt_enter();
299
300 if (TIMER_GetIntFlag(TIMER2))
301 {
302 TIMER_ClearIntFlag(TIMER2);
303 rt_device_hwtimer_isr(&nu_timer2.parent);
304 }
305
306 rt_interrupt_leave();
307 }
308 #endif
309
310 #ifdef BSP_USING_TIMER3
TMR3_IRQHandler(void)311 void TMR3_IRQHandler(void)
312 {
313 rt_interrupt_enter();
314
315 if (TIMER_GetIntFlag(TIMER3))
316 {
317 TIMER_ClearIntFlag(TIMER3);
318 rt_device_hwtimer_isr(&nu_timer3.parent);
319 }
320
321 rt_interrupt_leave();
322 }
323 #endif
324
325 #endif //#if (defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER))
326