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