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