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