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-12-3 Wayne 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 #include <drv_sys.h>
20 #include "nu_timer.h"
21
22 /* Private define ---------------------------------------------------------------*/
23 #define NU_TIMER_DEVICE(timer) (nu_timer_t)(timer)
24
25 enum
26 {
27 TIMER_START = -1,
28 #if defined(BSP_USING_TIMER0)
29 TIMER0_IDX,
30 #endif
31 #if defined(BSP_USING_TIMER1)
32 TIMER1_IDX,
33 #endif
34 #if defined(BSP_USING_TIMER2)
35 TIMER2_IDX,
36 #endif
37 #if defined(BSP_USING_TIMER3)
38 TIMER3_IDX,
39 #endif
40 /* BSP_USING_TIMER4 is reserved for Systick usage. */
41 TIMER_CNT
42 };
43
44 /* Private typedef --------------------------------------------------------------*/
45 struct nu_timer
46 {
47 rt_hwtimer_t parent;
48 char *name;
49 uint32_t idx;
50 IRQn_Type irqn;
51 E_SYS_IPRST rstidx;
52 E_SYS_IPCLK clkidx;
53 };
54 typedef struct nu_timer *nu_timer_t;
55
56 /* Private functions ------------------------------------------------------------*/
57 static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state);
58 static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode);
59 static void nu_timer_stop(rt_hwtimer_t *timer);
60 static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer);
61 static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
62
63 /* Public functions -------------------------------------------------------------*/
64
65
66 /* Private variables ------------------------------------------------------------*/
67 static struct nu_timer nu_timer_arr [] =
68 {
69 #if defined(BSP_USING_TIMER0)
70 {
71 .name = "timer0",
72 .idx = 0,
73 .irqn = IRQ_TMR0,
74 .rstidx = TIMER0RST,
75 .clkidx = TIMER0CKEN,
76 },
77 #endif
78 #if defined(BSP_USING_TIMER1)
79 {
80 .name = "timer1",
81 .idx = 1,
82 .irqn = IRQ_TMR1,
83 .rstidx = TIMER1RST,
84 .clkidx = TIMER1CKEN,
85 },
86 #endif
87 #if defined(BSP_USING_TIMER2)
88 {
89 .name = "timer2",
90 .idx = 2,
91 .irqn = IRQ_TMR2,
92 .rstidx = TIMER2RST,
93 .clkidx = TIMER2CKEN,
94 },
95 #endif
96 #if defined(BSP_USING_TIMER3)
97 {
98 .name = "timer3",
99 .idx = 3,
100 .irqn = IRQ_TMR3,
101 .rstidx = TIMER3RST,
102 .clkidx = TIMER3CKEN,
103 },
104 #endif
105 /* BSP_USING_TIMER4 is reserved for Systick usage. */
106 };
107
108 static struct rt_hwtimer_info nu_timer_info =
109 {
110 12000000, /* maximum count frequency */
111 46875, /* minimum count frequency */
112 0xFFFFFF, /* the maximum counter value */
113 HWTIMER_CNTMODE_UP, /* Increment or Decreasing count mode */
114 };
115
116 static struct rt_hwtimer_ops nu_timer_ops =
117 {
118 nu_timer_init,
119 nu_timer_start,
120 nu_timer_stop,
121 nu_timer_count_get,
122 nu_timer_control
123 };
124
125 /* Functions define ------------------------------------------------------------*/
nu_timer_init(rt_hwtimer_t * timer,rt_uint32_t state)126 static void nu_timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
127 {
128 nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
129 RT_ASSERT(psNuTmr != RT_NULL);
130
131 if (1 == state)
132 {
133 uint32_t timer_clk;
134 struct rt_hwtimer_info *info = &nu_timer_info;
135
136 timer_clk = TIMER_GetModuleClock(psNuTmr->idx);
137 info->maxfreq = timer_clk;
138 info->minfreq = timer_clk / 256;
139 TIMER_Open(psNuTmr->idx, TIMER_ONESHOT_MODE, 1);
140 TIMER_EnableInt(psNuTmr->idx);
141 rt_hw_interrupt_umask(psNuTmr->irqn);
142 }
143 else
144 {
145 rt_hw_interrupt_mask(psNuTmr->irqn);
146 TIMER_DisableInt(psNuTmr->idx);
147 TIMER_Close(psNuTmr->idx);
148 }
149 }
150
nu_timer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t opmode)151 static rt_err_t nu_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t opmode)
152 {
153 rt_err_t ret = -RT_EINVAL;
154 rt_uint32_t u32OpMode;
155
156 nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
157 RT_ASSERT(psNuTmr != RT_NULL);
158
159 if (cnt <= 1 || cnt > 0xFFFFFF)
160 {
161 goto exit_nu_timer_start;
162 }
163
164 switch (opmode)
165 {
166 case HWTIMER_MODE_PERIOD:
167 u32OpMode = TIMER_PERIODIC_MODE;
168 break;
169
170 case HWTIMER_MODE_ONESHOT:
171 u32OpMode = TIMER_ONESHOT_MODE;
172 break;
173
174 default:
175 goto exit_nu_timer_start;
176 }
177
178 TIMER_SET_CMP_VALUE(psNuTmr->idx, cnt);
179 TIMER_SET_OPMODE(psNuTmr->idx, u32OpMode);
180 TIMER_EnableInt(psNuTmr->idx);
181 rt_hw_interrupt_umask(psNuTmr->irqn);
182
183 TIMER_Start(psNuTmr->idx);
184
185 ret = RT_EOK;
186
187 exit_nu_timer_start:
188
189 return -(ret);
190 }
191
nu_timer_stop(rt_hwtimer_t * timer)192 static void nu_timer_stop(rt_hwtimer_t *timer)
193 {
194 nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
195 RT_ASSERT(psNuTmr != RT_NULL);
196
197 rt_hw_interrupt_mask(psNuTmr->irqn);
198 TIMER_DisableInt(psNuTmr->idx);
199 TIMER_Stop(psNuTmr->idx);
200 TIMER_ClearCounter(psNuTmr->idx);
201 }
202
nu_timer_count_get(rt_hwtimer_t * timer)203 static rt_uint32_t nu_timer_count_get(rt_hwtimer_t *timer)
204 {
205 nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
206 RT_ASSERT(psNuTmr != RT_NULL);
207
208 return TIMER_GetCounter(psNuTmr->idx);
209 }
210
nu_timer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)211 static rt_err_t nu_timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
212 {
213 rt_err_t ret = RT_EOK;
214 nu_timer_t psNuTmr = NU_TIMER_DEVICE(timer);
215 RT_ASSERT(psNuTmr != RT_NULL);
216
217 switch (cmd)
218 {
219 case HWTIMER_CTRL_FREQ_SET:
220 {
221 uint32_t clk;
222 uint32_t pre;
223
224 clk = TIMER_GetModuleClock(psNuTmr->idx);
225 pre = clk / *((uint32_t *)args) - 1;
226 TIMER_SET_PRESCALE_VALUE(psNuTmr->idx, pre);
227 *((uint32_t *)args) = clk / (pre + 1) ;
228 }
229 break;
230
231 case HWTIMER_CTRL_STOP:
232 TIMER_Stop(psNuTmr->idx);
233 break;
234
235 default:
236 ret = -RT_EINVAL;
237 break;
238 }
239
240 return -(ret);
241 }
242
243 /**
244 * All UART interrupt service routine
245 */
nu_timer_isr(int vector,void * param)246 static void nu_timer_isr(int vector, void *param)
247 {
248 nu_timer_t psNuTmr = NU_TIMER_DEVICE(param);
249 RT_ASSERT(psNuTmr != RT_NULL);
250
251 if (TIMER_GetIntFlag(psNuTmr->idx))
252 {
253 TIMER_ClearIntFlag(psNuTmr->idx);
254 rt_device_hwtimer_isr(&psNuTmr->parent);
255 }
256 }
257
rt_hw_timer_init(void)258 int rt_hw_timer_init(void)
259 {
260 int i;
261 rt_err_t ret = RT_EOK;
262 for (i = (TIMER_START + 1); i < TIMER_CNT; i++)
263 {
264 nu_sys_ipclk_enable(nu_timer_arr[i].clkidx);
265
266 nu_sys_ip_reset(nu_timer_arr[i].rstidx);
267
268 /* Register Etimer information. */
269 nu_timer_arr[i].parent.info = &nu_timer_info;
270
271 /* Register Etimer operation. */
272 nu_timer_arr[i].parent.ops = &nu_timer_ops;
273
274 /* Register Etimer interrupt service routine. */
275 rt_hw_interrupt_install(nu_timer_arr[i].irqn, nu_timer_isr, &nu_timer_arr[i], nu_timer_arr[i].name);
276
277 /* Register RT hwtimer device. */
278 ret = rt_device_hwtimer_register(&nu_timer_arr[i].parent, nu_timer_arr[i].name, &nu_timer_arr[i]);
279 RT_ASSERT(ret == RT_EOK);
280 }
281 return 0;
282 }
283 INIT_BOARD_EXPORT(rt_hw_timer_init);
284
285 #endif //#if defined(BSP_USING_TIMER) && defined(RT_USING_HWTIMER)
286