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