1 /***************************************************************************//**
2 * @file
3 * @brief Low Energy Timer (LETIMER) 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 #include "em_letimer.h"
32 #if defined(LETIMER_COUNT) && (LETIMER_COUNT > 0)
33 #include "em_cmu.h"
34 #include "em_assert.h"
35
36 /***************************************************************************//**
37 * @addtogroup letimer LETIMER - Low Energy Timer
38 * @brief Low Energy Timer (LETIMER) Peripheral API
39 * @details
40 * This module contains functions to control the LETIMER peripheral of Silicon
41 * Labs 32-bit MCUs and SoCs. The LETIMER is a down-counter that can keep track
42 * of time and output configurable waveforms.
43 * @{
44 ******************************************************************************/
45
46 /*******************************************************************************
47 ******************************* DEFINES ***********************************
48 ******************************************************************************/
49
50 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
51
52 /** A validation of the valid comparator register for assert statements. */
53 #define LETIMER_COMP_REG_VALID(reg) (((reg) <= 1))
54
55 /** A validation of the LETIMER register block pointer reference for assert statements. */
56 #if (LETIMER_COUNT == 1)
57 #define LETIMER_REF_VALID(ref) ((ref) == LETIMER0)
58 #elif (LETIMER_COUNT == 2)
59 #define LETIMER_REF_VALID(ref) (((ref) == LETIMER0) || ((ref) == LETIMER1))
60 #else
61 #error Undefined number of analog comparators (ACMP).
62 #endif
63
64 /** A validation of the valid repeat counter register for assert statements. */
65 #define LETIMER_REP_REG_VALID(reg) (((reg) <= 1))
66
67 /** @endcond */
68
69 /*******************************************************************************
70 ************************** LOCAL FUNCTIONS ********************************
71 ******************************************************************************/
72
73 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
74
75 /***************************************************************************//**
76 * @brief
77 * Wait for an ongoing sync of register(s) to the low-frequency domain to complete.
78 *
79 * @note
80 * See the reference manual chapter about Access to Low Energy Peripherals
81 * (Asynchronos Registers) for details.
82 *
83 * @param[in] letimer
84 * A pointer to the LETIMER peripheral register block.
85 *
86 * @param[in] mask
87 * A bitmask corresponding to SYNCBUSY register defined bits, indicating
88 * registers that must complete any ongoing synchronization.
89 ******************************************************************************/
regSync(LETIMER_TypeDef * letimer,uint32_t mask)90 __STATIC_INLINE void regSync(LETIMER_TypeDef *letimer, uint32_t mask)
91 {
92 #if defined(_LETIMER_FREEZE_MASK)
93 /* Avoid a deadlock if modifying the same register twice when freeze mode is */
94 /* activated. */
95 if (letimer->FREEZE & LETIMER_FREEZE_REGFREEZE) {
96 return;
97 }
98 #endif
99
100 /* Wait for any pending write operation to complete. */
101 while (letimer->SYNCBUSY & mask) {
102 }
103 }
104
105 /** @endcond */
106
107 /*******************************************************************************
108 ************************** GLOBAL FUNCTIONS *******************************
109 ******************************************************************************/
110
111 /***************************************************************************//**
112 * @brief
113 * Get the LETIMER compare register value.
114 *
115 * @param[in] letimer
116 * A pointer to the LETIMER peripheral register block.
117 *
118 * @param[in] comp
119 * A compare register to get, either 0 or 1.
120 *
121 * @return
122 * A compare register value, 0 if invalid register selected.
123 ******************************************************************************/
LETIMER_CompareGet(LETIMER_TypeDef * letimer,unsigned int comp)124 uint32_t LETIMER_CompareGet(LETIMER_TypeDef *letimer, unsigned int comp)
125 {
126 uint32_t ret;
127
128 EFM_ASSERT(LETIMER_REF_VALID(letimer) && LETIMER_COMP_REG_VALID(comp));
129
130 /* Initialize the selected compare value. */
131 switch (comp) {
132 case 0:
133 #if defined(LETIMER_SYNCBUSY_COMP0)
134 regSync(letimer, LETIMER_SYNCBUSY_COMP0);
135 #endif
136 ret = letimer->COMP0;
137 break;
138
139 case 1:
140 #if defined(LETIMER_SYNCBUSY_COMP1)
141 regSync(letimer, LETIMER_SYNCBUSY_COMP1);
142 #endif
143 ret = letimer->COMP1;
144 break;
145
146 default:
147 /* An unknown compare register selected. */
148 ret = 0;
149 break;
150 }
151
152 return ret;
153 }
154
155 /***************************************************************************//**
156 * @brief
157 * Get LETIMER counter value.
158 *
159 * @param[in] letimer
160 * Pointer to the LETIMER peripheral register block.
161 *
162 * @return
163 * Current LETIMER counter value.
164 ******************************************************************************/
LETIMER_CounterGet(LETIMER_TypeDef * letimer)165 uint32_t LETIMER_CounterGet(LETIMER_TypeDef *letimer)
166 {
167 #if defined(LETIMER_SYNCBUSY_CNT)
168 regSync(letimer, LETIMER_SYNCBUSY_CNT);
169 #endif
170 return letimer->CNT;
171 }
172
173 #if !defined(_EFM32_GECKO_FAMILY)
174 /***************************************************************************//**
175 * @brief
176 * Set LETIMER counter value.
177 *
178 * @param[in] letimer
179 * Pointer to the LETIMER peripheral register block.
180 *
181 * @param[in] value
182 * New counter value.
183 ******************************************************************************/
LETIMER_CounterSet(LETIMER_TypeDef * letimer,uint32_t value)184 void LETIMER_CounterSet(LETIMER_TypeDef *letimer, uint32_t value)
185 {
186 #if defined(LETIMER_SYNCBUSY_CNT)
187 regSync(letimer, LETIMER_SYNCBUSY_CNT);
188 #endif
189 letimer->CNT = value;
190 }
191 #endif
192
193 /***************************************************************************//**
194 * @brief
195 * Set the LETIMER compare register value.
196 *
197 * @note
198 * The setting of a compare register requires synchronization into the
199 * low frequency domain. If the same register is modified before a previous
200 * update has completed, this function will stall until the previous
201 * synchronization has completed. This only applies to the Gecko Family. See
202 * comments in the LETIMER_Sync() internal function call.
203 *
204 * @param[in] letimer
205 * A pointer to the LETIMER peripheral register block.
206 *
207 * @param[in] comp
208 * A compare register to set, either 0 or 1.
209 *
210 * @param[in] value
211 * An initialization value (<= 0x0000ffff).
212 ******************************************************************************/
LETIMER_CompareSet(LETIMER_TypeDef * letimer,unsigned int comp,uint32_t value)213 void LETIMER_CompareSet(LETIMER_TypeDef *letimer,
214 unsigned int comp,
215 uint32_t value)
216 {
217 volatile uint32_t *compReg;
218
219 EFM_ASSERT(LETIMER_REF_VALID(letimer)
220 && LETIMER_COMP_REG_VALID(comp)
221 && ((value & ~(_LETIMER_COMP0_COMP0_MASK
222 >> _LETIMER_COMP0_COMP0_SHIFT))
223 == 0));
224
225 /* Initialize the selected compare value. */
226 switch (comp) {
227 case 0:
228 compReg = &letimer->COMP0;
229 #if defined(LETIMER_SYNCBUSY_COMP0)
230 regSync(letimer, LETIMER_SYNCBUSY_COMP0);
231 #endif
232 break;
233
234 case 1:
235 compReg = &letimer->COMP1;
236 #if defined(LETIMER_SYNCBUSY_COMP1)
237 regSync(letimer, LETIMER_SYNCBUSY_COMP1);
238 #endif
239 break;
240
241 default:
242 /* An unknown compare register selected, abort. */
243 return;
244 }
245
246 *compReg = value;
247 }
248
249 /***************************************************************************//**
250 * @brief
251 * Start/stop LETIMER.
252 *
253 * @note
254 * The enabling/disabling of the LETIMER modifies the LETIMER CMD register
255 * which requires synchronization into the low-frequency domain. If this
256 * register is modified before a previous update to the same register has
257 * completed, this function will stall until the previous synchronization has
258 * completed. This only applies to the Gecko Family. See comments in the
259 * LETIMER_Sync() internal function call.
260 *
261 * @param[in] letimer
262 * A pointer to the LETIMER peripheral register block.
263 *
264 * @param[in] enable
265 * True to enable counting, false to disable.
266 ******************************************************************************/
LETIMER_Enable(LETIMER_TypeDef * letimer,bool enable)267 void LETIMER_Enable(LETIMER_TypeDef *letimer, bool enable)
268 {
269 EFM_ASSERT(LETIMER_REF_VALID(letimer));
270
271 #if defined(LETIMER_SYNCBUSY_CMD)
272 regSync(letimer, LETIMER_SYNCBUSY_CMD);
273 #elif defined (LETIMER_SYNCBUSY_START) && defined (LETIMER_SYNCBUSY_STOP)
274 regSync(letimer, LETIMER_SYNCBUSY_STOP | LETIMER_SYNCBUSY_START);
275 #endif
276
277 if (enable) {
278 letimer->CMD = LETIMER_CMD_START;
279 } else {
280 letimer->CMD = LETIMER_CMD_STOP;
281 }
282 }
283
284 #if defined(_LETIMER_FREEZE_MASK)
285 /***************************************************************************//**
286 * @brief
287 * LETIMER register synchronization freeze control.
288 *
289 * @details
290 * Some LETIMER registers require synchronization into the low-frequency (LF)
291 * domain. The freeze feature allows for several such registers to be
292 * modified before passing them to the LF domain simultaneously (which
293 * takes place when the freeze mode is disabled).
294 *
295 * @note
296 * When enabling freeze mode, this function will wait for all current
297 * ongoing LETIMER synchronization to the LF domain to complete (Normally
298 * synchronization will not be in progress.) However, for this reason, when
299 * using freeze mode, modifications of registers requiring the LF synchronization
300 * should be done within one freeze enable/disable block to avoid unecessary
301 * stalling.
302 *
303 * @param[in] letimer
304 * A pointer to the LETIMER peripheral register block.
305 *
306 * @param[in] enable
307 * @li True - enable freeze, modified registers are not propagated to the
308 * LF domain
309 * @li False - disables freeze, modified registers are propagated to the LF
310 * domain
311 ******************************************************************************/
LETIMER_FreezeEnable(LETIMER_TypeDef * letimer,bool enable)312 void LETIMER_FreezeEnable(LETIMER_TypeDef *letimer, bool enable)
313 {
314 if (enable) {
315 /*
316 * Wait for any ongoing LF synchronization to complete to
317 * protect against the rare case when a user
318 * - modifies a register requiring LF sync
319 * - then enables freeze before LF sync completed
320 * - then modifies the same register again
321 * since modifying a register while it is in sync progress should be
322 * avoided.
323 */
324 while (letimer->SYNCBUSY) {
325 }
326
327 letimer->FREEZE = LETIMER_FREEZE_REGFREEZE;
328 } else {
329 letimer->FREEZE = 0;
330 }
331 }
332 #endif /* defined(_LETIMER_FREEZE_MASK) */
333
334 /***************************************************************************//**
335 * @brief
336 * Initialize LETIMER.
337 *
338 * @details
339 * Note that the compare/repeat values must be set separately with
340 * LETIMER_CompareSet() and LETIMER_RepeatSet(). That should probably be done
341 * prior using this function if configuring the LETIMER to start when
342 * initialization is complete.
343 *
344 * @note
345 * The initialization of the LETIMER modifies the LETIMER CTRL/CMD registers
346 * which require synchronization into the low-frequency domain. If any of those
347 * registers are modified before a previous update to the same register has
348 * completed, this function will stall until the previous synchronization has
349 * completed. This only applies to the Gecko Family. See comments in the
350 * LETIMER_Sync() internal function call.
351 *
352 * @param[in] letimer
353 * A pointer to the LETIMER peripheral register block.
354 *
355 * @param[in] init
356 * A pointer to the LETIMER initialization structure.
357 ******************************************************************************/
LETIMER_Init(LETIMER_TypeDef * letimer,const LETIMER_Init_TypeDef * init)358 void LETIMER_Init(LETIMER_TypeDef *letimer, const LETIMER_Init_TypeDef *init)
359 {
360 uint32_t tmp = 0;
361
362 EFM_ASSERT(LETIMER_REF_VALID(letimer));
363
364 #if defined (LETIMER_EN_EN)
365 letimer->EN_SET = LETIMER_EN_EN;
366 #endif
367
368 /* Stop the timer if specified to be disabled and running. */
369 if (!(init->enable) && (letimer->STATUS & LETIMER_STATUS_RUNNING)) {
370 #if defined(LETIMER_SYNCBUSY_CMD)
371 regSync(letimer, LETIMER_SYNCBUSY_CMD);
372 #elif defined(LETIMER_SYNCBUSY_STOP)
373 regSync(letimer, LETIMER_SYNCBUSY_STOP);
374 #endif
375 letimer->CMD = LETIMER_CMD_STOP;
376 }
377
378 /* Configure the DEBUGRUN flag, which sets whether or not the counter should be
379 * updated when the debugger is active. */
380 if (init->debugRun) {
381 tmp |= LETIMER_CTRL_DEBUGRUN;
382 }
383
384 #if defined(LETIMER_CTRL_RTCC0TEN)
385 if (init->rtcComp0Enable) {
386 tmp |= LETIMER_CTRL_RTCC0TEN;
387 }
388
389 if (init->rtcComp1Enable) {
390 tmp |= LETIMER_CTRL_RTCC1TEN;
391 }
392 #endif
393
394 if ((init->comp0Top) || (init->topValue != 0U)) {
395 #if defined (LETIMER_CTRL_COMP0TOP)
396 tmp |= LETIMER_CTRL_COMP0TOP;
397 if (init->topValue != 0U) {
398 letimer->COMP0 = init->topValue;
399 }
400 #elif defined (LETIMER_CTRL_CNTTOPEN)
401 tmp |= LETIMER_CTRL_CNTTOPEN;
402 if (init->topValue != 0U) {
403 letimer->TOP = init->topValue;
404 }
405 #endif
406 }
407
408 if (init->bufTop) {
409 tmp |= LETIMER_CTRL_BUFTOP;
410 }
411
412 if (init->out0Pol) {
413 tmp |= LETIMER_CTRL_OPOL0;
414 }
415
416 if (init->out1Pol) {
417 tmp |= LETIMER_CTRL_OPOL1;
418 }
419
420 tmp |= init->ufoa0 << _LETIMER_CTRL_UFOA0_SHIFT;
421 tmp |= init->ufoa1 << _LETIMER_CTRL_UFOA1_SHIFT;
422 tmp |= init->repMode << _LETIMER_CTRL_REPMODE_SHIFT;
423
424 #if defined(LETIMER_SYNCBUSY_CTRL)
425 /* LF register about to be modified requires sync; busy check. */
426 regSync(letimer, LETIMER_SYNCBUSY_CTRL);
427 #endif
428 letimer->CTRL = tmp;
429
430 /* Start the timer if specified to be enabled and not already running. */
431 if (init->enable && !(letimer->STATUS & LETIMER_STATUS_RUNNING)) {
432 #if defined(LETIMER_SYNCBUSY_CMD)
433 regSync(letimer, LETIMER_SYNCBUSY_CMD);
434 #elif defined(LETIMER_SYNCBUSY_START)
435 regSync(letimer, LETIMER_SYNCBUSY_START);
436 #endif
437 letimer->CMD = LETIMER_CMD_START;
438 }
439 }
440
441 /***************************************************************************//**
442 * @brief
443 * Get the LETIMER repeat register value.
444 *
445 * @param[in] letimer
446 * A pointer to the LETIMER peripheral register block.
447 *
448 * @param[in] rep
449 * Repeat register to get, either 0 or 1.
450 *
451 * @return
452 * Repeat register value, 0 if invalid register selected.
453 ******************************************************************************/
LETIMER_RepeatGet(LETIMER_TypeDef * letimer,unsigned int rep)454 uint32_t LETIMER_RepeatGet(LETIMER_TypeDef *letimer, unsigned int rep)
455 {
456 uint32_t ret;
457
458 EFM_ASSERT(LETIMER_REF_VALID(letimer) && LETIMER_REP_REG_VALID(rep));
459
460 /* Initialize the selected compare value. */
461 switch (rep) {
462 case 0:
463 #if defined(LETIMER_SYNCBUSY_REP0)
464 /* Wait for sync to complete to read the potentially pending value. */
465 regSync(letimer, LETIMER_SYNCBUSY_REP0);
466 #endif
467 ret = letimer->REP0;
468 break;
469
470 case 1:
471 #if defined(LETIMER_SYNCBUSY_REP1)
472 regSync(letimer, LETIMER_SYNCBUSY_REP1);
473 #endif
474 ret = letimer->REP1;
475 break;
476
477 default:
478 /* An unknown compare register selected. */
479 ret = 0;
480 break;
481 }
482
483 return ret;
484 }
485
486 /***************************************************************************//**
487 * @brief
488 * Set the LETIMER repeat counter register value.
489 *
490 * @note
491 * The setting of a repeat counter register requires synchronization into the
492 * low-frequency domain. If the same register is modified before a previous
493 * update has completed, this function will stall until the previous
494 * synchronization has completed. This only applies to the Gecko Family. See
495 * comments in the LETIMER_Sync() internal function call.
496 *
497 * @param[in] letimer
498 * A pointer to the LETIMER peripheral register block.
499 *
500 * @param[in] rep
501 * Repeat counter register to set, either 0 or 1.
502 *
503 * @param[in] value
504 * An initialization value (<= 0x0000ffff).
505 ******************************************************************************/
LETIMER_RepeatSet(LETIMER_TypeDef * letimer,unsigned int rep,uint32_t value)506 void LETIMER_RepeatSet(LETIMER_TypeDef *letimer,
507 unsigned int rep,
508 uint32_t value)
509 {
510 volatile uint32_t *repReg;
511 EFM_ASSERT(LETIMER_REF_VALID(letimer)
512 && LETIMER_REP_REG_VALID(rep)
513 && ((value & ~(_LETIMER_REP0_REP0_MASK
514 >> _LETIMER_REP0_REP0_SHIFT))
515 == 0));
516
517 /* Initialize the selected compare value. */
518 switch (rep) {
519 case 0:
520 repReg = &(letimer->REP0);
521 #if defined(LETIMER_SYNCBUSY_REP0)
522 regSync(letimer, LETIMER_SYNCBUSY_REP0);
523 #endif
524 break;
525
526 case 1:
527 repReg = &(letimer->REP1);
528 #if defined(LETIMER_SYNCBUSY_REP1)
529 regSync(letimer, LETIMER_SYNCBUSY_REP1);
530 #endif
531 break;
532
533 default:
534 /* An unknown compare register selected, abort. */
535 return;
536 }
537
538 *repReg = value;
539 }
540
541 /***************************************************************************//**
542 * @brief
543 * Reset LETIMER to the same state that it was in after a hardware reset.
544 *
545 * @note
546 * The ROUTE register is NOT reset by this function to allow for
547 * a centralized setup of this feature.
548 *
549 * @param[in] letimer
550 * A pointer to the LETIMER peripheral register block.
551 ******************************************************************************/
LETIMER_Reset(LETIMER_TypeDef * letimer)552 void LETIMER_Reset(LETIMER_TypeDef *letimer)
553 {
554 #if defined (LETIMER_EN_EN)
555 letimer->EN_SET = LETIMER_EN_EN;
556 #endif
557 LETIMER_SyncWait(letimer);
558
559 #ifdef LETIMER_SWRST_SWRST
560
561 letimer->SWRST_SET = LETIMER_SWRST_SWRST;
562 while (letimer->SWRST & _LETIMER_SWRST_RESETTING_MASK) ;
563
564 #else
565
566 #if defined(_LETIMER_FREEZE_MASK)
567 /* Freeze registers to avoid stalling for LF synchronization. */
568 LETIMER_FreezeEnable(letimer, true);
569 #endif
570
571 /* Make sure disabled first, before resetting other registers. */
572 letimer->CMD = LETIMER_CMD_STOP | LETIMER_CMD_CLEAR
573 | LETIMER_CMD_CTO0 | LETIMER_CMD_CTO1;
574 letimer->CTRL = _LETIMER_CTRL_RESETVALUE;
575 letimer->COMP0 = _LETIMER_COMP0_RESETVALUE;
576 letimer->COMP1 = _LETIMER_COMP1_RESETVALUE;
577 letimer->REP0 = _LETIMER_REP0_RESETVALUE;
578 letimer->REP1 = _LETIMER_REP1_RESETVALUE;
579 letimer->IEN = _LETIMER_IEN_RESETVALUE;
580 LETIMER_IntClear(letimer, _LETIMER_IF_MASK);
581
582 #if defined(_LETIMER_FREEZE_MASK)
583 /* Unfreeze registers and pass new settings to LETIMER. */
584 LETIMER_FreezeEnable(letimer, false);
585 #endif
586
587 LETIMER_SyncWait(letimer);
588
589 #if defined (LETIMER_EN_EN)
590 letimer->EN_CLR = LETIMER_EN_EN;
591 #if defined(_LETIMER_EN_DISABLING_MASK)
592 /*
593 * Currently, there are no chips without SWRST and with LETIMER_EN_DISABLING
594 * so this code should never be reached, but that way the same pattern of
595 * checking the disabling bit is spread across emlib, and code is slightly
596 * more resilient to feature addition/removal.
597 */
598 while (letimer->EN & _LETIMER_EN_DISABLING_MASK) {
599 }
600 #endif
601 #endif
602 #endif
603 }
604
605 /***************************************************************************//**
606 * @brief
607 * Wait for the LETIMER to complete all synchronization of register changes
608 * and commands.
609 *
610 * @param[in] letimer
611 * A pointer to the LETIMER peripheral register block.
612 ******************************************************************************/
LETIMER_SyncWait(LETIMER_TypeDef * letimer)613 void LETIMER_SyncWait(LETIMER_TypeDef *letimer)
614 {
615 #if defined(_SILICON_LABS_32B_SERIES_2)
616 while ((letimer->EN != 0U) && (letimer->SYNCBUSY != 0U)) {
617 /* Wait for previous synchronization to finish */
618 }
619 #else
620 while (letimer->SYNCBUSY != 0U) {
621 /* Wait for previous synchronization to finish */
622 }
623 #endif
624 }
625
626 /***************************************************************************//**
627 * @brief
628 * Set the LETIMER top value.
629 *
630 * @note
631 * The LETIMER is a down-counter, so when the counter reaches 0 then the top
632 * value will be loaded into the counter. This function can be used to set
633 * the top value.
634 *
635 * If the LETIMER is not already configured to use a top value then this
636 * function will enable that functionality for the user.
637 *
638 * @param[in] letimer
639 * A pointer to the LETIMER peripheral register block.
640 *
641 * @param[in] value
642 * The top value. This can be a 16 bit value on series-0 and series-1 devices
643 * and a 24 bit value on series-2 devices.
644 ******************************************************************************/
LETIMER_TopSet(LETIMER_TypeDef * letimer,uint32_t value)645 void LETIMER_TopSet(LETIMER_TypeDef *letimer, uint32_t value)
646 {
647 #if defined(LETIMER_SYNCBUSY_CTRL)
648 regSync(letimer, LETIMER_SYNCBUSY_CTRL);
649 #elif defined(LETIMER_SYNCBUSY_TOP)
650 regSync(letimer, LETIMER_SYNCBUSY_TOP);
651 #endif
652
653 #if defined(_LETIMER_TOP_MASK)
654 /* Make sure TOP value is enabled. */
655 if ((letimer->CTRL & LETIMER_CTRL_CNTTOPEN) == 0U) {
656 letimer->CTRL_SET = LETIMER_CTRL_CNTTOPEN;
657 }
658 letimer->TOP = value;
659 #else
660 /* Make sure TOP value is enabled. */
661 if ((letimer->CTRL & LETIMER_CTRL_COMP0TOP) == 0U) {
662 letimer->CTRL |= LETIMER_CTRL_COMP0TOP;
663 }
664 LETIMER_CompareSet(letimer, 0, value);
665 #endif
666 }
667
668 /***************************************************************************//**
669 * @brief
670 * Get the current LETIMER top value.
671 *
672 * @param[in] letimer
673 * A pointer to the LETIMER peripheral register block.
674 *
675 * @return
676 * The top value. This will be a 16 bit value on series-0 and series-1
677 * devices and a 24 bit value on series-2 devices.
678 ******************************************************************************/
LETIMER_TopGet(LETIMER_TypeDef * letimer)679 uint32_t LETIMER_TopGet(LETIMER_TypeDef *letimer)
680 {
681 #if defined(_LETIMER_TOP_MASK)
682 regSync(letimer, LETIMER_SYNCBUSY_TOP);
683 return letimer->TOP;
684 #else
685 #if defined(LETIMER_SYNCBUSY_COMP0)
686 regSync(letimer, LETIMER_SYNCBUSY_COMP0);
687 #endif
688 return letimer->COMP0;
689 #endif
690 }
691
692 /** @} (end addtogroup letimer) */
693 #endif /* defined(LETIMER_COUNT) && (LETIMER_COUNT > 0) */
694