1 /***************************************************************************//**
2  * @file
3  * @brief Timer/counter (TIMER) peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #ifndef EM_TIMER_H
32 #define EM_TIMER_H
33 
34 #include "em_device.h"
35 #if defined(TIMER_COUNT) && (TIMER_COUNT > 0)
36 
37 #include <stdbool.h>
38 #include "sl_assert.h"
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /***************************************************************************//**
45  * @addtogroup timer
46  * @{
47  ******************************************************************************
48  * @deprecated
49  *   Deprecated macro TIMER_CH_VALID for SDID 80, new code should use TIMER_REF_CH_VALID.*/
50 
51 /*******************************************************************************
52  *******************************   DEFINES   ***********************************
53  ******************************************************************************/
54 
55 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
56 
57 /** Validation of TIMER register block pointer reference for assert statements. */
58 #define TIMER_REF_VALID(ref)  TIMER_Valid(ref)
59 
60 /** Validation of TIMER compare/capture channel number. */
61 #if defined(_SILICON_LABS_32B_SERIES_0)
62 #define TIMER_CH_VALID(ch)    ((ch) < 3)
63 #elif defined(_SILICON_LABS_32B_SERIES_1)
64 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
65 #define TIMER_CH_VALID(ch) _Pragma("GCC warning \"'TIMER_CH_VALID' macro is deprecated for EFR32xG1, Use TIMER_REF_CH_VALID instead\"") ((ch) < 4)
66 #else
67 #define TIMER_CH_VALID(ch)    ((ch) < 4)
68 #endif
69 #else
70 #define TIMER_CH_VALID(ch)    ((ch) < 3)
71 #endif
72 
73 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
74 #define TIMER_REF_CH_VALID(ref, ch) ((ref == TIMER0) ? ((ch) < 3) : ((ch) < 4))
75 #define TIMER_REF_CH_VALIDATE(ref, ch) TIMER_REF_CH_VALID(ref, ch)
76 #else
77 #define TIMER_REF_CH_VALIDATE(ref, ch) TIMER_CH_VALID(ch)
78 #endif
79 
80 /** @endcond */
81 
82 /*******************************************************************************
83  ********************************   ENUMS   ************************************
84  ******************************************************************************/
85 
86 /** Timer compare/capture mode. */
87 typedef enum {
88 #if defined (_TIMER_CC_CTRL_MODE_MASK)
89   timerCCModeOff     = _TIMER_CC_CTRL_MODE_OFF,           /**< Channel turned off. */
90   timerCCModeCapture = _TIMER_CC_CTRL_MODE_INPUTCAPTURE,  /**< Input capture. */
91   timerCCModeCompare = _TIMER_CC_CTRL_MODE_OUTPUTCOMPARE, /**< Output compare. */
92   timerCCModePWM     = _TIMER_CC_CTRL_MODE_PWM            /**< Pulse-Width modulation. */
93 #endif
94 #if defined (_TIMER_CC_CFG_MODE_MASK)
95   timerCCModeOff     = _TIMER_CC_CFG_MODE_OFF,            /**< Channel turned off. */
96   timerCCModeCapture = _TIMER_CC_CFG_MODE_INPUTCAPTURE,   /**< Input capture. */
97   timerCCModeCompare = _TIMER_CC_CFG_MODE_OUTPUTCOMPARE,  /**< Output compare. */
98   timerCCModePWM     = _TIMER_CC_CFG_MODE_PWM             /**< Pulse-Width modulation. */
99 #endif
100 } TIMER_CCMode_TypeDef;
101 
102 /** Clock select. */
103 typedef enum {
104 #if defined (_TIMER_CTRL_CLKSEL_MASK)
105   timerClkSelHFPerClk = _TIMER_CTRL_CLKSEL_PRESCHFPERCLK, /**< Prescaled HFPER / HFPERB clock. */
106   timerClkSelCC1      = _TIMER_CTRL_CLKSEL_CC1,           /**< Compare/Capture Channel 1 Input. */
107   timerClkSelCascade  = _TIMER_CTRL_CLKSEL_TIMEROUF       /**< Cascaded clocked by underflow or overflow by lower numbered timer. */
108 #endif
109 #if defined (_TIMER_CFG_CLKSEL_MASK)
110   timerClkSelHFPerClk = _TIMER_CFG_CLKSEL_PRESCEM01GRPACLK, /**< Prescaled EM01GRPA clock. */
111   timerClkSelCC1      = _TIMER_CFG_CLKSEL_CC1,              /**< Compare/Capture Channel 1 Input. */
112   timerClkSelCascade  = _TIMER_CFG_CLKSEL_TIMEROUF          /**< Cascaded clocked by underflow or overflow by lower numbered timer. */
113 #endif
114 } TIMER_ClkSel_TypeDef;
115 
116 /** Input capture edge select. */
117 typedef enum {
118   /** Rising edges detected. */
119   timerEdgeRising  = _TIMER_CC_CTRL_ICEDGE_RISING,
120 
121   /** Falling edges detected. */
122   timerEdgeFalling = _TIMER_CC_CTRL_ICEDGE_FALLING,
123 
124   /** Both edges detected. */
125   timerEdgeBoth    = _TIMER_CC_CTRL_ICEDGE_BOTH,
126 
127   /** No edge detection, leave signal as is. */
128   timerEdgeNone    = _TIMER_CC_CTRL_ICEDGE_NONE
129 } TIMER_Edge_TypeDef;
130 
131 /** Input capture event control. */
132 typedef enum {
133   /** PRS output pulse, interrupt flag, and DMA request set on every capture. */
134   timerEventEveryEdge    = _TIMER_CC_CTRL_ICEVCTRL_EVERYEDGE,
135   /** PRS output pulse, interrupt flag, and DMA request set on every second capture. */
136   timerEventEvery2ndEdge = _TIMER_CC_CTRL_ICEVCTRL_EVERYSECONDEDGE,
137   /**
138    * PRS output pulse, interrupt flag, and DMA request set on rising edge (if
139    * input capture edge = BOTH).
140    */
141   timerEventRising       = _TIMER_CC_CTRL_ICEVCTRL_RISING,
142   /**
143    * PRS output pulse, interrupt flag, and DMA request set on falling edge (if
144    * input capture edge = BOTH).
145    */
146   timerEventFalling      = _TIMER_CC_CTRL_ICEVCTRL_FALLING
147 } TIMER_Event_TypeDef;
148 
149 /** Input edge action. */
150 typedef enum {
151   /** No action taken. */
152   timerInputActionNone        = _TIMER_CTRL_FALLA_NONE,
153 
154   /** Start counter without reload. */
155   timerInputActionStart       = _TIMER_CTRL_FALLA_START,
156 
157   /** Stop counter without reload. */
158   timerInputActionStop        = _TIMER_CTRL_FALLA_STOP,
159 
160   /** Reload and start counter. */
161   timerInputActionReloadStart = _TIMER_CTRL_FALLA_RELOADSTART
162 } TIMER_InputAction_TypeDef;
163 
164 /** Timer mode. */
165 typedef enum {
166 #if defined (_TIMER_CTRL_MODE_MASK)
167   timerModeUp     = _TIMER_CTRL_MODE_UP,        /**< Up-counting. */
168   timerModeDown   = _TIMER_CTRL_MODE_DOWN,      /**< Down-counting. */
169   timerModeUpDown = _TIMER_CTRL_MODE_UPDOWN,    /**< Up/down-counting. */
170   timerModeQDec   = _TIMER_CTRL_MODE_QDEC       /**< Quadrature decoder. */
171 #endif
172 #if defined (_TIMER_CFG_MODE_MASK)
173   timerModeUp     = _TIMER_CFG_MODE_UP,         /**< Up-counting. */
174   timerModeDown   = _TIMER_CFG_MODE_DOWN,       /**< Down-counting. */
175   timerModeUpDown = _TIMER_CFG_MODE_UPDOWN,     /**< Up/down-counting. */
176   timerModeQDec   = _TIMER_CFG_MODE_QDEC        /**< Quadrature decoder. */
177 #endif
178 } TIMER_Mode_TypeDef;
179 
180 /** Compare/capture output action. */
181 typedef enum {
182   /** No action. */
183   timerOutputActionNone   = _TIMER_CC_CTRL_CUFOA_NONE,
184 
185   /** Toggle on event. */
186   timerOutputActionToggle = _TIMER_CC_CTRL_CUFOA_TOGGLE,
187 
188   /** Clear on event. */
189   timerOutputActionClear  = _TIMER_CC_CTRL_CUFOA_CLEAR,
190 
191   /** Set on event. */
192   timerOutputActionSet    = _TIMER_CC_CTRL_CUFOA_SET
193 } TIMER_OutputAction_TypeDef;
194 
195 /** Prescaler. */
196 typedef enum {
197 #if defined (_TIMER_CTRL_PRESC_MASK)
198   timerPrescale1    = _TIMER_CTRL_PRESC_DIV1,       /**< Divide by 1. */
199   timerPrescale2    = _TIMER_CTRL_PRESC_DIV2,       /**< Divide by 2. */
200   timerPrescale4    = _TIMER_CTRL_PRESC_DIV4,       /**< Divide by 4. */
201   timerPrescale8    = _TIMER_CTRL_PRESC_DIV8,       /**< Divide by 8. */
202   timerPrescale16   = _TIMER_CTRL_PRESC_DIV16,      /**< Divide by 16. */
203   timerPrescale32   = _TIMER_CTRL_PRESC_DIV32,      /**< Divide by 32. */
204   timerPrescale64   = _TIMER_CTRL_PRESC_DIV64,      /**< Divide by 64. */
205   timerPrescale128  = _TIMER_CTRL_PRESC_DIV128,     /**< Divide by 128. */
206   timerPrescale256  = _TIMER_CTRL_PRESC_DIV256,     /**< Divide by 256. */
207   timerPrescale512  = _TIMER_CTRL_PRESC_DIV512,     /**< Divide by 512. */
208   timerPrescale1024 = _TIMER_CTRL_PRESC_DIV1024     /**< Divide by 1024. */
209 #endif
210 #if defined (_TIMER_CFG_PRESC_MASK)
211   timerPrescale1    = _TIMER_CFG_PRESC_DIV1,        /**< Divide by 1. */
212   timerPrescale2    = _TIMER_CFG_PRESC_DIV2,        /**< Divide by 2. */
213   timerPrescale4    = _TIMER_CFG_PRESC_DIV4,        /**< Divide by 4. */
214   timerPrescale8    = _TIMER_CFG_PRESC_DIV8,        /**< Divide by 8. */
215   timerPrescale16   = _TIMER_CFG_PRESC_DIV16,       /**< Divide by 16. */
216   timerPrescale32   = _TIMER_CFG_PRESC_DIV32,       /**< Divide by 32. */
217   timerPrescale64   = _TIMER_CFG_PRESC_DIV64,       /**< Divide by 64. */
218   timerPrescale128  = _TIMER_CFG_PRESC_DIV128,      /**< Divide by 128. */
219   timerPrescale256  = _TIMER_CFG_PRESC_DIV256,      /**< Divide by 256. */
220   timerPrescale512  = _TIMER_CFG_PRESC_DIV512,      /**< Divide by 512. */
221   timerPrescale1024 = _TIMER_CFG_PRESC_DIV1024      /**< Divide by 1024. */
222 #endif
223 } TIMER_Prescale_TypeDef;
224 
225 /** Peripheral Reflex System signal. */
226 typedef uint8_t TIMER_PRSSEL_TypeDef;
227 
228 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
229 /** Deprecated PRS channel selector. New code should use an integer instead of
230  *  using these deprecated enum values. */
231 #define timerPRSSELCh0    0UL
232 #define timerPRSSELCh1    1UL
233 #define timerPRSSELCh2    2UL
234 #define timerPRSSELCh3    3UL
235 #define timerPRSSELCh4    4UL
236 #define timerPRSSELCh5    5UL
237 #define timerPRSSELCh6    6UL
238 #define timerPRSSELCh7    7UL
239 #define timerPRSSELCh8    8UL
240 #define timerPRSSELCh9    9UL
241 #define timerPRSSELCh10  10UL
242 #define timerPRSSELCh11  11UL
243 /** @endcond */
244 
245 #if defined (_TIMER_CC_CFG_INSEL_MASK)
246 /** PRS input type */
247 typedef enum {
248   timerPrsInputNone       =  0x0,                               /**< No PRS input. */
249   timerPrsInputSync       =  _TIMER_CC_CFG_INSEL_PRSSYNC,       /**< Synchronous PRS selected. */
250   timerPrsInputAsyncLevel =  _TIMER_CC_CFG_INSEL_PRSASYNCLEVEL, /**< Asynchronous level PRS selected. */
251   timerPrsInputAsyncPulse =  _TIMER_CC_CFG_INSEL_PRSASYNCPULSE, /**< Asynchronous pulse PRS selected. */
252 } TIMER_PrsInput_TypeDef;
253 #endif
254 
255 #if defined(_TIMER_DTFC_DTFA_MASK) || defined(_TIMER_DTFCFG_DTFA_MASK)
256 /** DT (Dead Time) Fault Actions. */
257 typedef enum {
258 #if defined(_TIMER_DTFC_DTFA_MASK)
259   timerDtiFaultActionNone     = _TIMER_DTFC_DTFA_NONE,          /**< No action on fault. */
260   timerDtiFaultActionInactive = _TIMER_DTFC_DTFA_INACTIVE,      /**< Set outputs inactive. */
261   timerDtiFaultActionClear    = _TIMER_DTFC_DTFA_CLEAR,         /**< Clear outputs. */
262   timerDtiFaultActionTristate = _TIMER_DTFC_DTFA_TRISTATE       /**< Tristate outputs. */
263 #endif
264 #if defined(_TIMER_DTFCFG_DTFA_MASK)
265   timerDtiFaultActionNone     = _TIMER_DTFCFG_DTFA_NONE,        /**< No action on fault. */
266   timerDtiFaultActionInactive = _TIMER_DTFCFG_DTFA_INACTIVE,    /**< Set outputs inactive. */
267   timerDtiFaultActionClear    = _TIMER_DTFCFG_DTFA_CLEAR,       /**< Clear outputs. */
268   timerDtiFaultActionTristate = _TIMER_DTFCFG_DTFA_TRISTATE     /**< Tristate outputs. */
269 #endif
270 } TIMER_DtiFaultAction_TypeDef;
271 #endif
272 
273 /*******************************************************************************
274  *******************************   STRUCTS   ***********************************
275  ******************************************************************************/
276 
277 /** TIMER initialization structure. */
278 typedef struct {
279   /** Start counting when initialization completed. */
280   bool                      enable;
281 
282   /** Counter shall keep running during debug halt. */
283   bool                      debugRun;
284 
285   /** Prescaling factor, if HFPER / HFPERB clock used. */
286   TIMER_Prescale_TypeDef    prescale;
287 
288   /** Clock selection. */
289   TIMER_ClkSel_TypeDef      clkSel;
290 
291 #if defined(TIMER_CTRL_X2CNT) && (defined(TIMER_CTRL_ATI) || defined(TIMER_CFG_ATI)) \
292   && (defined(TIMER_CTRL_RSSCOIST) || defined(TIMER_CFG_RSSCOIST))
293   /** 2x Count mode, counter increments/decrements by 2, meant for PWM mode. */
294   bool                      count2x;
295 
296   /** ATI (Always Track Inputs) makes CCPOL always track
297    * the polarity of the inputs. */
298   bool                      ati;
299 
300   /** Reload-Start Sets COIST
301    * When enabled, compare output is set to COIST value on a Reload-Start event. */
302   bool                      rssCoist;
303 #endif
304 
305   /** Action on falling input edge. */
306   TIMER_InputAction_TypeDef fallAction;
307 
308   /** Action on rising input edge. */
309   TIMER_InputAction_TypeDef riseAction;
310 
311   /** Counting mode. */
312   TIMER_Mode_TypeDef        mode;
313 
314   /** DMA request clear on active. */
315   bool                      dmaClrAct;
316 
317   /** Select X2 or X4 quadrature decode mode (if used). */
318   bool                      quadModeX4;
319 
320   /** Determines if only counting up or down once. */
321   bool                      oneShot;
322 
323   /** Timer can be start/stop/reload by other timers. */
324   bool                      sync;
325 
326 #if defined(TIMER_CTRL_DISSYNCOUT) || defined(TIMER_CFG_DISSYNCOUT)
327   /** Disable ability of timer to start/stop/reload other timers that have their SYNC bit set. */
328   bool                      disSyncOut;
329 #endif
330 } TIMER_Init_TypeDef;
331 
332 /** Default configuration for TIMER initialization structure. */
333 #if defined(TIMER_CTRL_X2CNT) && (defined(TIMER_CTRL_ATI) || defined(TIMER_CFG_ATI)) \
334   && (defined(TIMER_CTRL_RSSCOIST) || defined(TIMER_CFG_RSSCOIST))
335 #if (defined(TIMER_CTRL_DISSYNCOUT) || defined(TIMER_CFG_DISSYNCOUT))
336 #define TIMER_INIT_DEFAULT                                                            \
337   {                                                                                   \
338     true,                 /* Enable timer when initialization completes. */           \
339     false,                /* Stop counter during debug halt. */                       \
340     timerPrescale1,       /* No prescaling. */                                        \
341     timerClkSelHFPerClk,  /* Select HFPER / HFPERB clock. */                          \
342     false,                /* Not 2x count mode. */                                    \
343     false,                /* No ATI. */                                               \
344     false,                /* No RSSCOIST. */                                          \
345     timerInputActionNone, /* No action on falling input edge. */                      \
346     timerInputActionNone, /* No action on rising input edge. */                       \
347     timerModeUp,          /* Up-counting. */                                          \
348     false,                /* Do not clear DMA requests when DMA channel is active. */ \
349     false,                /* Select X2 quadrature decode mode (if used). */           \
350     false,                /* Disable one shot. */                                     \
351     false,                /* Not started/stopped/reloaded by other timers. */         \
352     false                 /* Disable ability to start/stop/reload other timers. */    \
353   }
354 #else
355 #define TIMER_INIT_DEFAULT                                                            \
356   {                                                                                   \
357     true,                 /* Enable timer when initialization completes. */           \
358     false,                /* Stop counter during debug halt. */                       \
359     timerPrescale1,       /* No prescaling. */                                        \
360     timerClkSelHFPerClk,  /* Select HFPER / HFPERB clock. */                          \
361     false,                /* Not 2x count mode. */                                    \
362     false,                /* No ATI. */                                               \
363     false,                /* No RSSCOIST. */                                          \
364     timerInputActionNone, /* No action on falling input edge. */                      \
365     timerInputActionNone, /* No action on rising input edge. */                       \
366     timerModeUp,          /* Up-counting. */                                          \
367     false,                /* Do not clear DMA requests when DMA channel is active. */ \
368     false,                /* Select X2 quadrature decode mode (if used). */           \
369     false,                /* Disable one shot. */                                     \
370     false                 /* Not started/stopped/reloaded by other timers. */         \
371   }
372 #endif
373 #else
374 #define TIMER_INIT_DEFAULT                                                            \
375   {                                                                                   \
376     true,                 /* Enable timer when initialization completes. */           \
377     false,                /* Stop counter during debug halt. */                       \
378     timerPrescale1,       /* No prescaling. */                                        \
379     timerClkSelHFPerClk,  /* Select HFPER / HFPERB clock. */                          \
380     timerInputActionNone, /* No action on falling input edge. */                      \
381     timerInputActionNone, /* No action on rising input edge. */                       \
382     timerModeUp,          /* Up-counting. */                                          \
383     false,                /* Do not clear DMA requests when DMA channel is active. */ \
384     false,                /* Select X2 quadrature decode mode (if used). */           \
385     false,                /* Disable one shot. */                                     \
386     false                 /* Not started/stopped/reloaded by other timers. */         \
387   }
388 #endif
389 
390 /** PRS Output configuration. */
391 typedef enum {
392   timerPrsOutputPulse   = 0,                   /**< Pulse PRS output from a channel. */
393   timerPrsOutputLevel   = 1,                   /**< PRS output follows CC out level. */
394   timerPrsOutputDefault = timerPrsOutputPulse, /**< Default PRS output behavior. */
395 } TIMER_PrsOutput_t;
396 
397 /** TIMER compare/capture initialization structure. */
398 typedef struct {
399   /** Input capture event control. */
400   TIMER_Event_TypeDef        eventCtrl;
401 
402   /** Input capture edge select. */
403   TIMER_Edge_TypeDef         edge;
404 
405   /**
406    * Peripheral reflex system trigger selection. Only applicable if @p prsInput
407    * is enabled.
408    */
409   TIMER_PRSSEL_TypeDef       prsSel;
410 
411   /** Counter underflow output action. */
412   TIMER_OutputAction_TypeDef cufoa;
413 
414   /** Counter overflow output action. */
415   TIMER_OutputAction_TypeDef cofoa;
416 
417   /** Counter match output action. */
418   TIMER_OutputAction_TypeDef cmoa;
419 
420   /** Compare/capture channel mode. */
421   TIMER_CCMode_TypeDef       mode;
422 
423   /** Enable digital filter. */
424   bool                       filter;
425 
426   /** Select TIMERnCCx (false) or PRS input (true). */
427   bool                       prsInput;
428 
429   /**
430    * Compare output initial state. Only used in Output Compare and PWM mode.
431    * When true, the compare/PWM output is set high when the counter is
432    * disabled. When counting resumes, this value will represent the initial
433    * value for the compare/PWM output. If the bit is cleared, the output
434    * will be cleared when the counter is disabled.
435    */
436   bool                       coist;
437 
438   /** Invert output from compare/capture channel. */
439   bool                       outInvert;
440 
441   /**
442    * PRS output configuration. PRS output from a timer can either be a
443    * pulse output or a level output that follows the CC out value.
444    */
445   TIMER_PrsOutput_t          prsOutput;
446 
447 #if defined(_TIMER_CC_CFG_INSEL_MASK)
448   /** When PRS input is used this field is used to configure the type of
449    * PRS input. */
450   TIMER_PrsInput_TypeDef     prsInputType;
451 #endif
452 } TIMER_InitCC_TypeDef;
453 
454 /** Default configuration for TIMER compare/capture initialization structure. */
455 #if defined(_TIMER_CC_CFG_INSEL_MASK)
456 #define TIMER_INITCC_DEFAULT                                                 \
457   {                                                                          \
458     timerEventEveryEdge,    /* Event on every capture. */                    \
459     timerEdgeRising,        /* Input capture edge on rising edge. */         \
460     0,                      /* Not used by default, select PRS channel 0. */ \
461     timerOutputActionNone,  /* No action on underflow. */                    \
462     timerOutputActionNone,  /* No action on overflow. */                     \
463     timerOutputActionNone,  /* No action on match. */                        \
464     timerCCModeOff,         /* Disable compare/capture channel. */           \
465     false,                  /* Disable filter. */                            \
466     false,                  /* No PRS input. */                              \
467     false,                  /* Clear output when counter disabled. */        \
468     false,                  /* Do not invert output. */                      \
469     timerPrsOutputDefault,  /* Use default PRS output configuration. */      \
470     timerPrsInputNone       /* No PRS input, so input type is none. */       \
471   }
472 #else
473 #define TIMER_INITCC_DEFAULT                                                 \
474   {                                                                          \
475     timerEventEveryEdge,    /* Event on every capture. */                    \
476     timerEdgeRising,        /* Input capture edge on rising edge. */         \
477     0,                      /* Not used by default, select PRS channel 0. */ \
478     timerOutputActionNone,  /* No action on underflow. */                    \
479     timerOutputActionNone,  /* No action on overflow. */                     \
480     timerOutputActionNone,  /* No action on match. */                        \
481     timerCCModeOff,         /* Disable compare/capture channel. */           \
482     false,                  /* Disable filter. */                            \
483     false,                  /* No PRS input. */                              \
484     false,                  /* Clear output when counter disabled. */        \
485     false,                  /* Do not invert output. */                      \
486     timerPrsOutputDefault,  /* Use default PRS output configuration. */      \
487   }
488 #endif
489 
490 #if defined(_TIMER_DTCTRL_MASK)
491 /** TIMER Dead Time Insertion (DTI) initialization structure. */
492 typedef struct {
493   /** Enable DTI or leave it disabled until @ref TIMER_EnableDTI() is called. */
494   bool                          enable;
495 
496   /** DTI Output Polarity. */
497   bool                          activeLowOut;
498 
499   /** DTI Complementary Output Invert. */
500   bool                          invertComplementaryOut;
501 
502   /** Enable Automatic Start-up functionality (when debugger exits). */
503   bool                          autoRestart;
504 
505   /** Enable/disable PRS as DTI input. */
506   bool                          enablePrsSource;
507 
508   /** Select which PRS channel as DTI input. Only valid if @p enablePrsSource
509      is enabled. */
510   TIMER_PRSSEL_TypeDef          prsSel;
511 
512   /** DTI prescaling factor, if HFPER / HFPERB clock used. */
513   TIMER_Prescale_TypeDef        prescale;
514 
515   /** DTI Rise Time */
516   unsigned int                  riseTime;
517 
518   /** DTI Fall Time */
519   unsigned int                  fallTime;
520 
521   /** DTI outputs enable bit mask, consisting of one bit per DTI
522       output signal, i.e., CC0, CC1, CC2, CDTI0, CDTI1, and CDTI2.
523       This value should consist of one or more TIMER_DTOGEN_DTOGnnnEN flags
524       (defined in \<part_name\>_timer.h) OR'ed together. */
525   uint32_t                      outputsEnableMask;
526 
527   /** Enable core lockup as a fault source. */
528   bool                          enableFaultSourceCoreLockup;
529 
530   /** Enable debugger as a fault source. */
531   bool                          enableFaultSourceDebugger;
532 
533   /** Enable PRS fault source 0 (@p faultSourcePrsSel0). */
534   bool                          enableFaultSourcePrsSel0;
535 
536   /** Select which PRS signal to be PRS fault source 0. */
537   TIMER_PRSSEL_TypeDef          faultSourcePrsSel0;
538 
539   /** Enable PRS fault source 1 (@p faultSourcePrsSel1). */
540   bool                          enableFaultSourcePrsSel1;
541 
542   /** Select which PRS signal to be PRS fault source 1. */
543   TIMER_PRSSEL_TypeDef          faultSourcePrsSel1;
544 
545   /** Fault Action */
546   TIMER_DtiFaultAction_TypeDef  faultAction;
547 } TIMER_InitDTI_TypeDef;
548 
549 /** Default configuration for TIMER DTI initialization structure. */
550 #define TIMER_INITDTI_DEFAULT                                                      \
551   {                                                                                \
552     true,                   /* Enable the DTI. */                                  \
553     false,                  /* CC[0|1|2] outputs are active high. */               \
554     false,                  /* CDTI[0|1|2] outputs are not inverted. */            \
555     false,                  /* No auto restart when debugger exits. */             \
556     false,                  /* No PRS source selected. */                          \
557     0,                      /* Not used by default, select PRS channel 0. */       \
558     timerPrescale1,         /* No prescaling.  */                                  \
559     0,                      /* No rise time. */                                    \
560     0,                      /* No fall time. */                                    \
561     TIMER_DTOGEN_DTOGCC0EN | TIMER_DTOGEN_DTOGCDTI0EN, /* Enable CC0 and CDTI0. */ \
562     true,                   /* Enable core lockup as fault source. */              \
563     true,                   /* Enable debugger as fault source. */                 \
564     false,                  /* Disable PRS fault source 0. */                      \
565     0,                      /* Not used by default, select PRS channel 0. */       \
566     false,                  /* Disable PRS fault source 1. */                      \
567     0,                      /* Not used by default, select PRS channel 0. */       \
568     timerDtiFaultActionInactive, /* No fault action. */                            \
569   }
570 #endif /* _TIMER_DTCTRL_MASK */
571 
572 /*******************************************************************************
573  *****************************   PROTOTYPES   **********************************
574  ******************************************************************************/
575 
576 #if defined(TIMER_STATUS_SYNCBUSY)
577 void TIMER_SyncWait(TIMER_TypeDef * timer);
578 #endif
579 
580 /***************************************************************************//**
581  * @brief
582  *   Validate the TIMER register block pointer.
583  *
584  * @param[in] ref
585  *   Pointer to the TIMER peripheral register block.
586  *
587  * @return
588  *   True if ref points to a valid timer, false otherwise.
589  ******************************************************************************/
TIMER_Valid(const TIMER_TypeDef * ref)590 __STATIC_INLINE bool TIMER_Valid(const TIMER_TypeDef *ref)
591 {
592   return (ref == TIMER0)
593 #if defined(TIMER1)
594          || (ref == TIMER1)
595 #endif
596 #if defined(TIMER2)
597          || (ref == TIMER2)
598 #endif
599 #if defined(TIMER3)
600          || (ref == TIMER3)
601 #endif
602 #if defined(TIMER4)
603          || (ref == TIMER4)
604 #endif
605 #if defined(TIMER5)
606          || (ref == TIMER5)
607 #endif
608 #if defined(TIMER6)
609          || (ref == TIMER6)
610 #endif
611 #if defined(TIMER7)
612          || (ref == TIMER7)
613 #endif
614 #if defined(TIMER8)
615          || (ref == TIMER8)
616 #endif
617 #if defined(TIMER9)
618          || (ref == TIMER9)
619 #endif
620 #if defined(WTIMER0)
621          || (ref == WTIMER0)
622 #endif
623 #if defined(WTIMER1)
624          || (ref == WTIMER1)
625 #endif
626 #if defined(WTIMER2)
627          || (ref == WTIMER2)
628 #endif
629 #if defined(WTIMER3)
630          || (ref == WTIMER3)
631 #endif
632   ;
633 }
634 
635 /***************************************************************************//**
636  * @brief
637  *   Check whether the TIMER is valid and supports Dead Timer Insertion (DTI).
638  *
639  * @param[in] ref
640  *   Pointer to the TIMER peripheral register block.
641  *
642  * @return
643  *   True if ref points to a valid timer that supports DTI, false otherwise.
644  ******************************************************************************/
TIMER_SupportsDTI(const TIMER_TypeDef * ref)645 __STATIC_INLINE bool TIMER_SupportsDTI(const TIMER_TypeDef *ref)
646 {
647   (void) ref;
648 
649   return 0
650 #if defined(TIMER0_DTI)
651 #if (TIMER0_DTI == 1)
652          || (ref == TIMER0)
653 #endif
654 #elif defined(_TIMER_DTCTRL_MASK)
655          || (ref == TIMER0)
656 #endif
657 #if defined(TIMER1_DTI) && (TIMER1_DTI == 1)
658          || (ref == TIMER1)
659 #endif
660 #if defined(TIMER2_DTI) && (TIMER2_DTI == 1)
661          || (ref == TIMER2)
662 #endif
663 #if defined(TIMER3_DTI) && (TIMER3_DTI == 1)
664          || (ref == TIMER3)
665 #endif
666 #if defined(TIMER4_DTI) && (TIMER4_DTI == 1)
667          || (ref == TIMER4)
668 #endif
669 #if defined(TIMER5_DTI) && (TIMER5_DTI == 1)
670          || (ref == TIMER5)
671 #endif
672 #if defined(TIMER6_DTI) && (TIMER6_DTI == 1)
673          || (ref == TIMER6)
674 #endif
675 #if defined(TIMER7_DTI) && (TIMER7_DTI == 1)
676          || (ref == TIMER7)
677 #endif
678 #if defined(TIMER8_DTI) && (TIMER8_DTI == 1)
679          || (ref == TIMER8)
680 #endif
681 #if defined(TIMER9_DTI) && (TIMER9_DTI == 1)
682          || (ref == TIMER9)
683 #endif
684 #if defined(WTIMER0)
685          || (ref == WTIMER0)
686 #endif
687   ;
688 }
689 
690 /***************************************************************************//**
691  * @brief
692  *   Get the Max count of the timer.
693  *
694  * @param[in] ref
695  *   Pointer to the TIMER peripheral register block.
696  *
697  * @return
698  *   The max count value of the timer. This is 0xFFFF for 16 bit timers
699  *   and 0xFFFFFFFF for 32 bit timers.
700  ******************************************************************************/
TIMER_MaxCount(const TIMER_TypeDef * ref)701 __STATIC_INLINE uint32_t TIMER_MaxCount(const TIMER_TypeDef *ref)
702 {
703   (void) ref;
704 
705 #if defined(WTIMER_PRESENT)
706   if ((ref == WTIMER0)
707 #if defined(WTIMER1)
708       || (ref == WTIMER1)
709 #endif
710 #if defined(WTIMER2)
711       || (ref == WTIMER2)
712 #endif
713 #if defined(WTIMER3)
714       || (ref == WTIMER3)
715 #endif
716       ) {
717     return 0xFFFFFFFFUL;
718   }
719 #endif /* defined(WTIMER_PRESENT) */
720 
721 #if defined(_SILICON_LABS_32B_SERIES_2)
722   EFM_ASSERT(TIMER_NUM(ref) != -1);
723 
724   return (uint32_t)((1ULL << TIMER_CNTWIDTH(TIMER_NUM(ref))) - 1);
725 #else
726   return 0xFFFFUL;
727 #endif /* defined(_SILICON_LABS_32B_SERIES_2) */
728 }
729 
730 /***************************************************************************//**
731  * @brief
732  *   Get compare/capture value for the compare/capture channel.
733  *
734  * @param[in] timer
735  *   Pointer to the TIMER peripheral register block.
736  *
737  * @param[in] ch
738  *   Compare/capture channel to access.
739  *
740  * @return
741  *   Current capture value.
742  ******************************************************************************/
TIMER_CaptureGet(TIMER_TypeDef * timer,unsigned int ch)743 __STATIC_INLINE uint32_t TIMER_CaptureGet(TIMER_TypeDef *timer, unsigned int ch)
744 {
745 #if defined (_TIMER_CC_CFG_MASK)
746   if ((timer->CC[ch].CFG & _TIMER_CC_CFG_MODE_MASK) == TIMER_CC_CFG_MODE_INPUTCAPTURE) {
747     return timer->CC[ch].ICF;
748   } else {
749     return timer->CC[ch].OC;
750   }
751 #else
752   return timer->CC[ch].CCV;
753 #endif
754 }
755 
756 /***************************************************************************//**
757  * @brief
758  *   Get the buffered compare/capture value for compare/capture channel.
759  *
760  * @param[in] timer
761  *   Pointer to the TIMER peripheral register block.
762  *
763  * @param[in] ch
764  *   Compare/capture channel to access.
765  *
766  * @return
767  *   Current buffered capture value.
768  ******************************************************************************/
TIMER_CaptureBufGet(TIMER_TypeDef * timer,unsigned int ch)769 __STATIC_INLINE uint32_t TIMER_CaptureBufGet(TIMER_TypeDef *timer, unsigned int ch)
770 {
771 #if defined (_TIMER_CC_CFG_MASK)
772   if ((timer->CC[ch].CFG & _TIMER_CC_CFG_MODE_MASK) == TIMER_CC_CFG_MODE_INPUTCAPTURE) {
773     return timer->CC[ch].ICOF;
774   } else {
775     return timer->CC[ch].OCB;
776   }
777 #else
778   return timer->CC[ch].CCVB;
779 #endif
780 }
781 
782 /***************************************************************************//**
783  * @brief
784  *   Set the compare value buffer for the compare/capture channel when operating in
785  *   compare or PWM mode.
786  *
787  * @details
788  *   The compare value buffer holds the value which will be written to
789  *   TIMERn_CCx_CCV on an update event if the buffer has been updated since
790  *   the last event.
791  *
792  * @param[in] timer
793  *   Pointer to the TIMER peripheral register block.
794  *
795  * @param[in] ch
796  *   Compare/capture channel to access.
797  *
798  * @param[in] val
799  *   Value to set in compare value buffer register.
800  ******************************************************************************/
TIMER_CompareBufSet(TIMER_TypeDef * timer,unsigned int ch,uint32_t val)801 __STATIC_INLINE void TIMER_CompareBufSet(TIMER_TypeDef *timer,
802                                          unsigned int ch,
803                                          uint32_t val)
804 {
805   EFM_ASSERT(val <= TIMER_MaxCount(timer));
806 #if defined (_TIMER_CC_CFG_MASK)
807   EFM_ASSERT(timer->EN & TIMER_EN_EN);
808   timer->CC[ch].OCB = val;
809 #else
810   timer->CC[ch].CCVB = val;
811 #endif
812 }
813 
814 /***************************************************************************//**
815  * @brief
816  *   Set the compare value for compare/capture channel when operating in compare
817  *   or PWM mode.
818  *
819  * @param[in] timer
820  *   Pointer to the TIMER peripheral register block.
821  *
822  * @param[in] ch
823  *   Compare/capture channel to access.
824  *
825  * @param[in] val
826  *   Value to set in compare value register.
827  ******************************************************************************/
TIMER_CompareSet(TIMER_TypeDef * timer,unsigned int ch,uint32_t val)828 __STATIC_INLINE void TIMER_CompareSet(TIMER_TypeDef *timer,
829                                       unsigned int ch,
830                                       uint32_t val)
831 {
832   EFM_ASSERT(val <= TIMER_MaxCount(timer));
833 #if defined (_TIMER_CC_CFG_MASK)
834   EFM_ASSERT(timer->EN & TIMER_EN_EN);
835   timer->CC[ch].OC = val;
836 #else
837   timer->CC[ch].CCV = val;
838 #endif
839 }
840 
841 /***************************************************************************//**
842  * @brief
843  *   Get the TIMER counter value.
844  *
845  * @param[in] timer
846  *   Pointer to TIMER peripheral register block.
847  *
848  * @return
849  *   Current TIMER counter value.
850  ******************************************************************************/
TIMER_CounterGet(TIMER_TypeDef * timer)851 __STATIC_INLINE uint32_t TIMER_CounterGet(TIMER_TypeDef *timer)
852 {
853   return timer->CNT;
854 }
855 
856 /***************************************************************************//**
857  * @brief
858  *   Set the TIMER counter value.
859  *
860  * @param[in] timer
861  *   Pointer to the TIMER peripheral register block.
862  *
863  * @param[in] val
864  *   Value to set counter to.
865  ******************************************************************************/
TIMER_CounterSet(TIMER_TypeDef * timer,uint32_t val)866 __STATIC_INLINE void TIMER_CounterSet(TIMER_TypeDef *timer, uint32_t val)
867 {
868   EFM_ASSERT(val <= TIMER_MaxCount(timer));
869 #if defined(TIMER_HAS_SET_CLEAR)
870   bool enabled = (timer->EN & TIMER_EN_EN) != 0UL;
871   timer->EN_SET = TIMER_EN_EN;
872 #endif
873   timer->CNT = val;
874 #if defined(TIMER_HAS_SET_CLEAR)
875   if (!enabled) {
876     TIMER_SyncWait(timer);
877     timer->EN_CLR = TIMER_EN_EN;
878 #if defined(_TIMER_EN_DISABLING_MASK)
879     while (timer->EN & _TIMER_EN_DISABLING_MASK) {
880     }
881 #endif
882   }
883 #endif
884 }
885 
886 /***************************************************************************//**
887  * @brief
888  *   Start/stop TIMER.
889  *
890  * @param[in] timer
891  *   Pointer to the TIMER peripheral register block.
892  *
893  * @param[in] enable
894  *   Set to true to enable counting; set to false otherwise.
895  ******************************************************************************/
TIMER_Enable(TIMER_TypeDef * timer,bool enable)896 __STATIC_INLINE void TIMER_Enable(TIMER_TypeDef *timer, bool enable)
897 {
898   EFM_ASSERT(TIMER_REF_VALID(timer));
899 
900   if (enable) {
901     timer->CMD = TIMER_CMD_START;
902   } else {
903     timer->CMD = TIMER_CMD_STOP;
904   }
905 }
906 
907 void TIMER_Init(TIMER_TypeDef *timer, const TIMER_Init_TypeDef *init);
908 void TIMER_InitCC(TIMER_TypeDef *timer,
909                   unsigned int ch,
910                   const TIMER_InitCC_TypeDef *init);
911 
912 #if defined(_TIMER_DTCTRL_MASK)
913 void TIMER_InitDTI(TIMER_TypeDef *timer, const TIMER_InitDTI_TypeDef *init);
914 
915 /***************************************************************************//**
916  * @brief
917  *   Enable or disable DTI unit.
918  *
919  * @param[in] timer
920  *   Pointer to the TIMER peripheral register block.
921  *
922  * @param[in] enable
923  *   Set to true to enable DTI unit; set to false otherwise.
924  ******************************************************************************/
TIMER_EnableDTI(TIMER_TypeDef * timer,bool enable)925 __STATIC_INLINE void TIMER_EnableDTI(TIMER_TypeDef *timer, bool enable)
926 {
927 #if defined(TIMER_HAS_SET_CLEAR)
928   uint32_t timerEn = timer->EN & TIMER_EN_EN;
929   TIMER_SyncWait(timer);
930   timer->EN_CLR = TIMER_EN_EN;
931 #if defined(_TIMER_EN_DISABLING_MASK)
932   while (timer->EN & _TIMER_EN_DISABLING_MASK) {
933   }
934 #endif
935   if (enable) {
936     timer->DTCFG_SET = TIMER_DTCFG_DTEN;
937   } else {
938     timer->DTCFG_CLR = TIMER_DTCFG_DTEN;
939   }
940   timer->EN_SET = timerEn;
941 #else
942   EFM_ASSERT(TIMER_SupportsDTI(timer));
943 
944   if (enable) {
945     timer->DTCTRL |= TIMER_DTCTRL_DTEN;
946   } else {
947     timer->DTCTRL &= ~TIMER_DTCTRL_DTEN;
948   }
949 #endif
950 }
951 
952 /***************************************************************************//**
953  * @brief
954  *   Get DTI fault source flags status.
955  *
956  * @note
957  *   Event bits are not cleared by this function.
958  *
959  * @param[in] timer
960  *   Pointer to the TIMER peripheral register block.
961  *
962  * @return
963  *   Status of the DTI fault source flags. Returns one or more valid
964  *   DTI fault source flags (TIMER_DTFAULT_nnn) OR'ed together.
965  ******************************************************************************/
TIMER_GetDTIFault(TIMER_TypeDef * timer)966 __STATIC_INLINE uint32_t TIMER_GetDTIFault(TIMER_TypeDef *timer)
967 {
968   EFM_ASSERT(TIMER_SupportsDTI(timer));
969   return timer->DTFAULT;
970 }
971 
972 /***************************************************************************//**
973  * @brief
974  *   Clear DTI fault source flags.
975  *
976  * @param[in] timer
977  *   Pointer to the TIMER peripheral register block.
978  *
979  * @param[in] flags
980  *   DTI fault source(s) to clear. Use one or more valid DTI fault
981  *   source flags (TIMER_DTFAULT_nnn) OR'ed together.
982  ******************************************************************************/
TIMER_ClearDTIFault(TIMER_TypeDef * timer,uint32_t flags)983 __STATIC_INLINE void TIMER_ClearDTIFault(TIMER_TypeDef *timer, uint32_t flags)
984 
985 {
986   EFM_ASSERT(TIMER_SupportsDTI(timer));
987 #if defined (TIMER_EN_EN)
988   EFM_ASSERT(timer->EN & TIMER_EN_EN);
989 #endif
990 
991   timer->DTFAULTC = flags;
992 }
993 #endif /* _TIMER_DTCTRL_MASK */
994 
995 /***************************************************************************//**
996  * @brief
997  *   Clear one or more pending TIMER interrupts.
998  *
999  * @param[in] timer
1000  *   Pointer to the TIMER peripheral register block.
1001  *
1002  * @param[in] flags
1003  *   Pending TIMER interrupt source(s) to clear. Use one or more valid
1004  *   interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
1005  ******************************************************************************/
TIMER_IntClear(TIMER_TypeDef * timer,uint32_t flags)1006 __STATIC_INLINE void TIMER_IntClear(TIMER_TypeDef *timer, uint32_t flags)
1007 {
1008 #if defined (TIMER_HAS_SET_CLEAR)
1009   timer->IF_CLR = flags;
1010 #else
1011   timer->IFC = flags;
1012 #endif
1013 }
1014 
1015 /***************************************************************************//**
1016  * @brief
1017  *   Disable one or more TIMER interrupts.
1018  *
1019  * @param[in] timer
1020  *   Pointer to the TIMER peripheral register block.
1021  *
1022  * @param[in] flags
1023  *   TIMER interrupt source(s) to disable. Use one or more valid
1024  *   interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
1025  ******************************************************************************/
TIMER_IntDisable(TIMER_TypeDef * timer,uint32_t flags)1026 __STATIC_INLINE void TIMER_IntDisable(TIMER_TypeDef *timer, uint32_t flags)
1027 {
1028   timer->IEN &= ~flags;
1029 }
1030 
1031 /***************************************************************************//**
1032  * @brief
1033  *   Enable one or more TIMER interrupts.
1034  *
1035  * @note
1036  *   Depending on the use, a pending interrupt may already be set prior to
1037  *   enabling the interrupt.  To ignore a pending interrupt, consider using
1038  *   TIMER_IntClear() prior to enabling the interrupt.
1039 
1040  *
1041  * @param[in] timer
1042  *   Pointer to the TIMER peripheral register block.
1043  *
1044  * @param[in] flags
1045  *   TIMER interrupt source(s) to enable. Use one or more valid
1046  *   interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
1047  ******************************************************************************/
TIMER_IntEnable(TIMER_TypeDef * timer,uint32_t flags)1048 __STATIC_INLINE void TIMER_IntEnable(TIMER_TypeDef *timer, uint32_t flags)
1049 {
1050   timer->IEN |= flags;
1051 }
1052 
1053 /***************************************************************************//**
1054  * @brief
1055  *   Get pending TIMER interrupt flags.
1056  *
1057  * @note
1058  *   Event bits are not cleared by this function.
1059  *
1060  * @param[in] timer
1061  *   Pointer to the TIMER peripheral register block.
1062  *
1063  * @return
1064  *   TIMER interrupt source(s) pending. Returns one or more valid
1065  *   interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
1066  ******************************************************************************/
TIMER_IntGet(TIMER_TypeDef * timer)1067 __STATIC_INLINE uint32_t TIMER_IntGet(TIMER_TypeDef *timer)
1068 {
1069   return timer->IF;
1070 }
1071 
1072 /***************************************************************************//**
1073  * @brief
1074  *   Get enabled and pending TIMER interrupt flags.
1075  *   Useful for handling more interrupt sources in the same interrupt handler.
1076  *
1077  * @param[in] timer
1078  *   Pointer to the TIMER peripheral register block.
1079  *
1080  * @note
1081  *   Interrupt flags are not cleared by this function.
1082  *
1083  * @return
1084  *   Pending and enabled TIMER interrupt sources.
1085  *   The return value is the bitwise AND combination of
1086  *   - the OR combination of enabled interrupt sources in TIMERx_IEN_nnn
1087  *     register (TIMERx_IEN_nnn) and
1088  *   - the OR combination of valid interrupt flags of the TIMER module
1089  *     (TIMERx_IF_nnn).
1090  ******************************************************************************/
TIMER_IntGetEnabled(TIMER_TypeDef * timer)1091 __STATIC_INLINE uint32_t TIMER_IntGetEnabled(TIMER_TypeDef *timer)
1092 {
1093   uint32_t ien;
1094 
1095   /* Store TIMER->IEN in temporary variable in order to define explicit order
1096    * of volatile accesses. */
1097   ien = timer->IEN;
1098 
1099   /* Bitwise AND of pending and enabled interrupts */
1100   return timer->IF & ien;
1101 }
1102 
1103 /***************************************************************************//**
1104  * @brief
1105  *   Set one or more pending TIMER interrupts from SW.
1106  *
1107  * @param[in] timer
1108  *   Pointer to the TIMER peripheral register block.
1109  *
1110  * @param[in] flags
1111  *   TIMER interrupt source(s) to set to pending. Use one or more valid
1112  *   interrupt flags for the TIMER module (TIMER_IF_nnn) OR'ed together.
1113  ******************************************************************************/
TIMER_IntSet(TIMER_TypeDef * timer,uint32_t flags)1114 __STATIC_INLINE void TIMER_IntSet(TIMER_TypeDef *timer, uint32_t flags)
1115 {
1116 #if defined (TIMER_HAS_SET_CLEAR)
1117   timer->IF_SET = flags;
1118 #else
1119   timer->IFS = flags;
1120 #endif
1121 }
1122 
1123 #if defined(_TIMER_DTLOCK_LOCKKEY_LOCK)
1124 /***************************************************************************//**
1125  * @brief
1126  *   Lock some TIMER registers to protect them from being
1127  *   modified.
1128  *
1129  * @details
1130  *   Refer to the reference manual for TIMER registers that will be locked.
1131  *
1132  * @note
1133  *   If locking the TIMER registers, they must be unlocked prior to using any
1134  *   TIMER API function that modifies TIMER registers protected by the lock.
1135  *
1136  * @param[in] timer
1137  *   Pointer to TIMER peripheral register block.
1138  ******************************************************************************/
TIMER_Lock(TIMER_TypeDef * timer)1139 __STATIC_INLINE void TIMER_Lock(TIMER_TypeDef *timer)
1140 {
1141   EFM_ASSERT(TIMER0 == timer);
1142 #if defined (TIMER_EN_EN)
1143   EFM_ASSERT(timer->EN & TIMER_EN_EN);
1144 #endif
1145 
1146   timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_LOCK;
1147 }
1148 #endif
1149 
1150 void TIMER_Reset(TIMER_TypeDef *timer);
1151 
1152 /***************************************************************************//**
1153  * @brief
1154  *   Set the top value buffer for the timer.
1155  *
1156  * @details
1157  *   When top value buffer register is updated, value is loaded into
1158  *   top value register at the next wrap around. This feature is useful
1159  *   in order to update top value safely when timer is running.
1160  *
1161  * @param[in] timer
1162  *   Pointer to the TIMER peripheral register block.
1163  *
1164  * @param[in] val
1165  *   Value to set in top value buffer register.
1166  ******************************************************************************/
TIMER_TopBufSet(TIMER_TypeDef * timer,uint32_t val)1167 __STATIC_INLINE void TIMER_TopBufSet(TIMER_TypeDef *timer, uint32_t val)
1168 {
1169   EFM_ASSERT(val <= TIMER_MaxCount(timer));
1170 #if defined (TIMER_EN_EN)
1171   EFM_ASSERT(timer->EN & TIMER_EN_EN);
1172 #endif
1173 
1174   timer->TOPB = val;
1175 }
1176 
1177 /***************************************************************************//**
1178  * @brief
1179  *   Get the top value setting for the timer.
1180  *
1181  * @param[in] timer
1182  *   Pointer to the TIMER peripheral register block.
1183  *
1184  * @return
1185  *   Current top value.
1186  ******************************************************************************/
TIMER_TopGet(TIMER_TypeDef * timer)1187 __STATIC_INLINE uint32_t TIMER_TopGet(TIMER_TypeDef *timer)
1188 {
1189   return timer->TOP;
1190 }
1191 
1192 /***************************************************************************//**
1193  * @brief
1194  *   Set the top value for timer.
1195  *
1196  * @param[in] timer
1197  *   Pointer to the TIMER peripheral register block.
1198  *
1199  * @param[in] val
1200  *   Value to set in top value register.
1201  ******************************************************************************/
TIMER_TopSet(TIMER_TypeDef * timer,uint32_t val)1202 __STATIC_INLINE void TIMER_TopSet(TIMER_TypeDef *timer, uint32_t val)
1203 {
1204   EFM_ASSERT(val <= TIMER_MaxCount(timer));
1205 #if defined (TIMER_EN_EN)
1206   EFM_ASSERT(timer->EN & TIMER_EN_EN);
1207 #endif
1208 
1209   timer->TOP = val;
1210 }
1211 
1212 #if defined(TIMER_DTLOCK_LOCKKEY_UNLOCK)
1213 /***************************************************************************//**
1214  * @brief
1215  *   Unlock TIMER to enable writing to locked registers again.
1216  *
1217  * @param[in] timer
1218  *   Pointer to the TIMER peripheral register block.
1219  ******************************************************************************/
TIMER_Unlock(TIMER_TypeDef * timer)1220 __STATIC_INLINE void TIMER_Unlock(TIMER_TypeDef *timer)
1221 {
1222   EFM_ASSERT(TIMER0 == timer);
1223 #if defined (TIMER_EN_EN)
1224   EFM_ASSERT(timer->EN & TIMER_EN_EN);
1225 #endif
1226 
1227   timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_UNLOCK;
1228 }
1229 #endif
1230 
1231 /** @} (end addtogroup timer) */
1232 
1233 #ifdef __cplusplus
1234 }
1235 #endif
1236 
1237 #endif /* defined(TIMER_COUNT) && (TIMER_COUNT > 0) */
1238 #endif /* EM_TIMER_H */
1239