1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2011-01-18 onelife Initial creation for EFM32
9 * 2011-06-17 onelife Modify init function for efm32lib v2 upgrading
10 */
11
12 /***************************************************************************//**
13 * @addtogroup efm32
14 * @{
15 ******************************************************************************/
16
17 /* Includes ------------------------------------------------------------------*/
18 #include "board.h"
19 #include "drv_timer.h"
20
21 #if (defined(RT_USING_TIMER0) || defined(RT_USING_TIMER1) || defined(RT_USING_TIMER2))
22 /* Private typedef -----------------------------------------------------------*/
23 /* Private define ------------------------------------------------------------*/
24 /* Private macro -------------------------------------------------------------*/
25 #ifdef RT_TIMER_DEBUG
26 #define timer_debug(format,args...) rt_kprintf(format, ##args)
27 #else
28 #define timer_debug(format,args...)
29 #endif
30 #define TIMER_TopCalculate(p) \
31 (p * (EFM32_HFXO_FREQUENCY / (1 << TMR_CFG_PRESCALER) / 1000))
32
33 /* Private variables ---------------------------------------------------------*/
34 #ifdef RT_USING_TIMER0
35 static struct rt_device timer0_device;
36 #endif
37 #ifdef RT_USING_TIMER1
38 static struct rt_device timer1_device;
39 #endif
40 #ifdef RT_USING_TIMER2
41 static struct rt_device timer2_device;
42 #endif
43
44 /* Private function prototypes -----------------------------------------------*/
45 /* Private functions ---------------------------------------------------------*/
46 /***************************************************************************//**
47 * @brief
48 * Initialize Timer device
49 *
50 * @details
51 *
52 * @note
53 *
54 * @param[in] dev
55 * Pointer to device descriptor
56 *
57 * @return
58 * Error code
59 ******************************************************************************/
rt_hs_timer_init(rt_device_t dev)60 static rt_err_t rt_hs_timer_init (rt_device_t dev)
61 {
62 RT_ASSERT(dev != RT_NULL);
63
64 struct efm32_timer_device_t *timer;
65
66 timer = (struct efm32_timer_device_t *)(dev->user_data);
67
68 timer->hook.cbFunc = RT_NULL;
69 timer->hook.userPtr = RT_NULL;
70
71 return RT_EOK;
72 }
73
74 /***************************************************************************//**
75 * @brief
76 * Configure Timer device
77 *
78 * @details
79 *
80 * @note
81 *
82 * @param[in] dev
83 * Pointer to device descriptor
84 *
85 * @param[in] cmd
86 * Timer control command
87 *
88 * @param[in] args
89 * Arguments
90 *
91 * @return
92 * Error code
93 ******************************************************************************/
rt_hs_timer_control(rt_device_t dev,rt_uint8_t cmd,void * args)94 static rt_err_t rt_hs_timer_control (
95 rt_device_t dev,
96 rt_uint8_t cmd,
97 void *args)
98 {
99 RT_ASSERT(dev != RT_NULL);
100
101 struct efm32_timer_device_t *timer;
102
103 timer = (struct efm32_timer_device_t *)(dev->user_data);
104
105 switch (cmd)
106 {
107 case RT_DEVICE_CTRL_SUSPEND:
108 /* Suspend device */
109 dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
110 TIMER_Enable(timer->timer_device, false);
111 break;
112
113 case RT_DEVICE_CTRL_RESUME:
114 /* Resume device */
115 dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
116 TIMER_Enable(timer->timer_device, true);
117 break;
118
119 case RT_DEVICE_CTRL_TIMER_PERIOD:
120 {
121 /* change device setting */
122 struct efm32_timer_control_t *control;
123 rt_uint32_t running;
124
125 control = (struct efm32_timer_control_t *)args;
126 running = timer->timer_device->STATUS & 0x00000001;
127
128 TIMER_Enable(timer->timer_device, false);
129 timer->timer_device->CNT = _TIMER_CNT_RESETVALUE;
130 TIMER_TopSet(timer->timer_device, TIMER_TopCalculate(control->period));
131 timer->hook.cbFunc = control->hook.cbFunc;
132 timer->hook.userPtr = control->hook.userPtr;
133 if (running)
134 {
135 TIMER_Enable(timer->timer_device, true);
136 }
137 }
138 break;
139 }
140
141 return RT_EOK;
142 }
143
144 /***************************************************************************//**
145 * @brief
146 * Register Timer device
147 *
148 * @details
149 *
150 * @note
151 *
152 * @param[in] device
153 * Pointer to device descriptor
154 *
155 * @param[in] name
156 * Device name
157 *
158 * @param[in] flag
159 * Configuration flags
160 *
161 * @param[in] timer
162 * Pointer to Timer device descriptor
163 *
164 * @return
165 * Error code
166 ******************************************************************************/
rt_hw_timer_register(rt_device_t device,const char * name,rt_uint32_t flag,struct efm32_timer_device_t * timer)167 rt_err_t rt_hw_timer_register(
168 rt_device_t device,
169 const char *name,
170 rt_uint32_t flag,
171 struct efm32_timer_device_t *timer)
172 {
173 RT_ASSERT(device != RT_NULL);
174
175 device->type = RT_Device_Class_Char; /* fixme: should be timer type*/
176 device->rx_indicate = RT_NULL;
177 device->tx_complete = RT_NULL;
178 device->init = rt_hs_timer_init;
179 device->open = RT_NULL;
180 device->close = RT_NULL;
181 device->read = RT_NULL;
182 device->write = RT_NULL;
183 device->control = rt_hs_timer_control;
184 device->user_data = timer;
185
186 /* register a character device */
187 return rt_device_register(device, name, flag);
188 }
189
190 /***************************************************************************//**
191 * @brief
192 * Timer counter overflow interrupt handler
193 *
194 * @details
195 *
196 * @note
197 ******************************************************************************/
rt_hw_timer_isr(rt_device_t dev)198 void rt_hw_timer_isr(rt_device_t dev)
199 {
200 RT_ASSERT(dev != RT_NULL);
201
202 struct efm32_timer_device_t *timer;
203
204 timer = (struct efm32_timer_device_t *)(dev->user_data);
205
206 if (timer->hook.cbFunc != RT_NULL)
207 {
208 (timer->hook.cbFunc)(timer->hook.userPtr);
209 }
210 }
211
212 /***************************************************************************//**
213 * @brief
214 * Initialize the specified TIMER unit
215 *
216 * @details
217 *
218 * @note
219 *
220 * @param[in] device
221 * Pointer to device descriptor
222 *
223 * @param[in] unitNumber
224 * Unit number
225 *
226 * @return
227 * Pointer to TIMER device
228 ******************************************************************************/
rt_hw_timer_unit_init(rt_device_t device,rt_uint8_t unitNumber,rt_uint8_t mode)229 static struct efm32_timer_device_t *rt_hw_timer_unit_init(
230 rt_device_t device,
231 rt_uint8_t unitNumber,
232 rt_uint8_t mode)
233 {
234 struct efm32_timer_device_t *timer;
235 TIMER_Init_TypeDef init;
236 efm32_irq_hook_init_t hook;
237 CMU_Clock_TypeDef timerClock;
238 IRQn_Type timerIrq;
239
240 do
241 {
242 /* Allocate device */
243 timer = rt_malloc(sizeof(struct efm32_timer_device_t));
244 if (timer == RT_NULL)
245 {
246 timer_debug("no memory for TIMER%d driver\n", unitNumber);
247 break;
248 }
249
250 /* Initialization */
251 if (unitNumber >= TIMER_COUNT)
252 {
253 break;
254 }
255 switch (unitNumber)
256 {
257 case 0:
258 timer->timer_device = TIMER0;
259 timerClock = (CMU_Clock_TypeDef)cmuClock_TIMER0;
260 timerIrq = TIMER0_IRQn;
261 break;
262
263 case 1:
264 timer->timer_device = TIMER1;
265 timerClock = (CMU_Clock_TypeDef)cmuClock_TIMER1;
266 timerIrq = TIMER1_IRQn;
267 break;
268
269 case 2:
270 timer->timer_device = TIMER2;
271 timerClock = (CMU_Clock_TypeDef)cmuClock_TIMER2;
272 timerIrq = TIMER2_IRQn;
273 break;
274
275 default:
276 break;
277 }
278
279 /* Enable TIMER clock */
280 CMU_ClockEnable(timerClock, true);
281
282 /* Reset */
283 TIMER_Reset(timer->timer_device);
284
285 /* Init specified TIMER unit */
286 init.enable = false;
287 init.debugRun = true;
288 init.prescale = TMR_CFG_PRESCALER;
289 init.clkSel = timerClkSelHFPerClk;
290 init.fallAction = timerInputActionNone;
291 init.riseAction = timerInputActionNone;
292 init.mode = timerModeUp;
293 init.dmaClrAct = false;
294 init.quadModeX4 = false;
295 init.oneShot = (mode > 0) ? true : false;
296 init.sync = false;
297 TIMER_Init(timer->timer_device, &init);
298
299 /* Config interrupt and NVIC */
300 hook.type = efm32_irq_type_timer;
301 hook.unit = unitNumber;
302 hook.cbFunc = rt_hw_timer_isr;
303 hook.userPtr = device;
304 efm32_irq_hook_register(&hook);
305
306 /* Enable overflow interrupt */
307 TIMER_IntEnable(timer->timer_device, TIMER_IF_OF);
308 TIMER_IntClear(timer->timer_device, TIMER_IF_OF);
309
310 /* Enable TIMERn interrupt vector in NVIC */
311 NVIC_ClearPendingIRQ(timerIrq);
312 NVIC_SetPriority(timerIrq, EFM32_IRQ_PRI_DEFAULT);
313 NVIC_EnableIRQ(timerIrq);
314
315 return timer;
316 } while(0);
317
318 if (timer)
319 {
320 rt_free(timer);
321 }
322 rt_kprintf("TIMER: Init failed!\n");
323 return RT_NULL;
324 }
325
326 /***************************************************************************//**
327 * @brief
328 * Initialize all Timer module related hardware and register Timer device to
329 * kernel
330 *
331 * @details
332 *
333 * @note
334 ******************************************************************************/
rt_hw_timer_init(void)335 void rt_hw_timer_init(void)
336 {
337 struct efm32_timer_device_t *timer;
338
339 #ifdef RT_USING_TIMER0
340 if ((timer = rt_hw_timer_unit_init(&timer0_device, 0, RT_USING_TIMER0)) \
341 != RT_NULL)
342 {
343 rt_hw_timer_register(&timer0_device, RT_TIMER0_NAME, 0, timer);
344 }
345 #endif
346
347
348 #ifdef RT_USING_TIMER1
349 if ((timer = rt_hw_timer_unit_init(&timer1_device, 1, RT_USING_TIMER1)) \
350 != RT_NULL)
351 {
352 rt_hw_timer_register(&timer1_device, RT_TIMER1_NAME, 0, timer);
353 }
354 #endif
355
356 #ifdef RT_USING_TIMER2
357 if ((timer = rt_hw_timer_unit_init(&timer2_device, 2, RT_USING_TIMER2)) \
358 != RT_NULL)
359 {
360 rt_hw_timer_register(&timer2_device, RT_TIMER2_NAME, 0, timer);
361 }
362 #endif
363 }
364
365 #endif
366 /***************************************************************************//**
367 * @}
368 ******************************************************************************/
369