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 #include "em_timer.h"
32 #if defined(TIMER_COUNT) && (TIMER_COUNT > 0)
33
34 #include "sl_assert.h"
35
36 /***************************************************************************//**
37 * @addtogroup timer TIMER - Timer/Counter
38 * @brief Timer/Counter (TIMER) Peripheral API
39 * @details
40 * The timer module consists of three main parts:
41 * @li General timer configuration and enable control.
42 * @li Compare/capture control.
43 * @li Dead time insertion control (may not be available for all timers).
44 * @{
45 ******************************************************************************/
46
47 /*******************************************************************************
48 ************************** LOCAL FUNCTIONS ********************************
49 ******************************************************************************/
50
51 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
52 #if defined(_PRS_CONSUMER_TIMER0_CC0_MASK)
53
54 /** Map TIMER reference to index of device. */
55 #if defined(TIMER9)
56 #define TIMER_DEVICE_ID(timer) ( \
57 (timer) == TIMER0 ? 0 \
58 : (timer) == TIMER1 ? 1 \
59 : (timer) == TIMER2 ? 2 \
60 : (timer) == TIMER3 ? 3 \
61 : (timer) == TIMER4 ? 4 \
62 : (timer) == TIMER5 ? 5 \
63 : (timer) == TIMER6 ? 6 \
64 : (timer) == TIMER7 ? 7 \
65 : (timer) == TIMER8 ? 8 \
66 : (timer) == TIMER9 ? 9 \
67 : -1)
68 #elif defined(TIMER7)
69 #define TIMER_DEVICE_ID(timer) ( \
70 (timer) == TIMER0 ? 0 \
71 : (timer) == TIMER1 ? 1 \
72 : (timer) == TIMER2 ? 2 \
73 : (timer) == TIMER3 ? 3 \
74 : (timer) == TIMER4 ? 4 \
75 : (timer) == TIMER5 ? 5 \
76 : (timer) == TIMER6 ? 6 \
77 : (timer) == TIMER7 ? 7 \
78 : -1)
79 #elif defined(TIMER4)
80 #define TIMER_DEVICE_ID(timer) ( \
81 (timer) == TIMER0 ? 0 \
82 : (timer) == TIMER1 ? 1 \
83 : (timer) == TIMER2 ? 2 \
84 : (timer) == TIMER3 ? 3 \
85 : (timer) == TIMER4 ? 4 \
86 : -1)
87 #else
88 #define TIMER_DEVICE_ID(timer) ( \
89 (timer) == TIMER0 ? 0 \
90 : (timer) == TIMER1 ? 1 \
91 : (timer) == TIMER2 ? 2 \
92 : (timer) == TIMER3 ? 3 \
93 : -1)
94 #endif
95
96 #define TIMER_INPUT_CHANNEL_DTI 3UL
97 #define TIMER_INPUT_CHANNEL_DTIFS1 4UL
98 #define TIMER_INPUT_CHANNEL_DTIFS2 5UL
99
100 /**
101 * TIMER PRS registers are moved into the PRS register space on series 2 devices.
102 * The PRS Consumer registers for a timer consist of 6 registers.
103 *
104 * [0] - CC0 PRS Consumer
105 * [1] - CC1 PRS Consumer
106 * [2] - CC2 PRS Consumer
107 * [3] - DTI PRS Consumer
108 * [4] - DTIFS1 PRS Consumer
109 * [5] - DTIFS2 PRS Consumer
110 */
111 typedef struct {
112 __IOM uint32_t CONSUMER_CH[6]; /**< TIMER PRS consumers. */
113 } PRS_TIMERn_Consumer_TypeDef;
114
115 typedef struct {
116 PRS_TIMERn_Consumer_TypeDef TIMER_CONSUMER[TIMER_COUNT];
117 } PRS_TIMERn_TypeDef;
118
119 /**
120 * @brief Configure a timer capture/compare channel to use a PRS channel as input.
121 *
122 * @param[in] timer
123 *
124 * @param[in] cc
125 * Timer input channel. Valid input is 0-5.
126 * 0 - CC0
127 * 1 - CC1
128 * 2 - CC2
129 * 3 - DTI
130 * 4 - DTIFS1
131 * 5 - DTIFS2
132 *
133 * @param[in] prsCh
134 * PRS channel number.
135 *
136 * @param[in] async
137 * true for asynchronous PRS channel, false for synchronous PRS channel.
138 */
timerPrsConfig(TIMER_TypeDef * timer,unsigned int cc,unsigned int prsCh,bool async)139 static void timerPrsConfig(TIMER_TypeDef * timer, unsigned int cc, unsigned int prsCh, bool async)
140 {
141 int i = TIMER_DEVICE_ID(timer);
142 volatile PRS_TIMERn_TypeDef * base = (PRS_TIMERn_TypeDef *) &PRS->CONSUMER_TIMER0_CC0;
143 EFM_ASSERT(i >= 0);
144
145 if (i >= 0) {
146 if (async) {
147 base->TIMER_CONSUMER[i].CONSUMER_CH[cc] = prsCh << _PRS_CONSUMER_TIMER0_CC0_PRSSEL_SHIFT;
148 } else {
149 base->TIMER_CONSUMER[i].CONSUMER_CH[cc] = prsCh << _PRS_CONSUMER_TIMER0_CC0_SPRSSEL_SHIFT;
150 }
151 }
152 }
153 #endif
154
155 /** @endcond */
156
157 /*******************************************************************************
158 ************************** GLOBAL FUNCTIONS *******************************
159 ******************************************************************************/
160
161 /***************************************************************************//**
162 * @brief
163 * Initialize TIMER.
164 *
165 * @details
166 * Notice that the counter top must be configured separately with, for instance
167 * TIMER_TopSet(). In addition, compare/capture and dead-time insertion
168 * initialization must be initialized separately if used, which should probably
169 * be done prior to using this function if configuring the TIMER to
170 * start when initialization is completed.
171 *
172 * @param[in] timer
173 * A pointer to the TIMER peripheral register block.
174 *
175 * @param[in] init
176 * A pointer to the TIMER initialization structure.
177 ******************************************************************************/
TIMER_Init(TIMER_TypeDef * timer,const TIMER_Init_TypeDef * init)178 void TIMER_Init(TIMER_TypeDef *timer, const TIMER_Init_TypeDef *init)
179 {
180 EFM_ASSERT(TIMER_REF_VALID(timer));
181 uint32_t ctrlRegVal = 0;
182
183 #if defined (_TIMER_CFG_PRESC_SHIFT)
184 TIMER_SyncWait(timer);
185 timer->EN_CLR = TIMER_EN_EN;
186 #if defined(_TIMER_EN_DISABLING_MASK)
187 while (timer->EN & _TIMER_EN_DISABLING_MASK) {
188 }
189 #endif
190 timer->CFG = ((uint32_t)init->prescale << _TIMER_CFG_PRESC_SHIFT)
191 | ((uint32_t)init->clkSel << _TIMER_CFG_CLKSEL_SHIFT)
192 | ((uint32_t)init->mode << _TIMER_CFG_MODE_SHIFT)
193 | (init->debugRun ? TIMER_CFG_DEBUGRUN : 0)
194 | (init->dmaClrAct ? TIMER_CFG_DMACLRACT : 0)
195 | (init->quadModeX4 ? TIMER_CFG_QDM_X4 : 0)
196 | (init->oneShot ? TIMER_CFG_OSMEN : 0)
197 | (init->sync ? TIMER_CFG_SYNC : 0)
198 | (init->disSyncOut ? TIMER_CFG_DISSYNCOUT : 0)
199 | (init->ati ? TIMER_CFG_ATI : 0)
200 | (init->rssCoist ? TIMER_CFG_RSSCOIST : 0);
201 timer->EN_SET = TIMER_EN_EN;
202 #endif
203
204 /* Stop the timer if specified to be disabled (doesn't hurt if already stopped). */
205 if (!(init->enable)) {
206 timer->CMD = TIMER_CMD_STOP;
207 }
208
209 /* Reset the counter. */
210 timer->CNT = _TIMER_CNT_RESETVALUE;
211
212 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
213 ctrlRegVal = ((uint32_t)init->prescale << _TIMER_CTRL_PRESC_SHIFT)
214 | ((uint32_t)init->clkSel << _TIMER_CTRL_CLKSEL_SHIFT)
215 | ((uint32_t)init->fallAction << _TIMER_CTRL_FALLA_SHIFT)
216 | ((uint32_t)init->riseAction << _TIMER_CTRL_RISEA_SHIFT)
217 | ((uint32_t)init->mode << _TIMER_CTRL_MODE_SHIFT)
218 | (init->debugRun ? TIMER_CTRL_DEBUGRUN : 0)
219 | (init->dmaClrAct ? TIMER_CTRL_DMACLRACT : 0)
220 | (init->quadModeX4 ? TIMER_CTRL_QDM_X4 : 0)
221 | (init->oneShot ? TIMER_CTRL_OSMEN : 0)
222 #if defined(TIMER_CTRL_DISSYNCOUT)
223 | (init->disSyncOut ? TIMER_CTRL_DISSYNCOUT : 0)
224 #endif
225 | (init->sync ? TIMER_CTRL_SYNC : 0);
226
227 #if defined(TIMER_CTRL_X2CNT) && defined(TIMER_CTRL_ATI) && defined(TIMER_CTRL_RSSCOIST)
228 ctrlRegVal |= (init->count2x ? TIMER_CTRL_X2CNT : 0)
229 | (init->ati ? TIMER_CTRL_ATI : 0)
230 | (init->rssCoist ? TIMER_CTRL_RSSCOIST : 0);
231 #endif
232
233 #else
234 ctrlRegVal = ((uint32_t)init->fallAction << _TIMER_CTRL_FALLA_SHIFT)
235 | ((uint32_t)init->riseAction << _TIMER_CTRL_RISEA_SHIFT)
236 | (init->count2x ? TIMER_CTRL_X2CNT : 0);
237 #endif
238
239 timer->CTRL = ctrlRegVal;
240
241 /* Start the timer if specified to be enabled (doesn't hurt if already started). */
242 if (init->enable) {
243 timer->CMD = TIMER_CMD_START;
244 }
245 }
246
247 /***************************************************************************//**
248 * @brief
249 * Initialize the TIMER compare/capture channel.
250 *
251 * @details
252 * Notice that if operating the channel in compare mode, the CCV and CCVB register
253 * must be set separately, as required.
254 *
255 * @param[in] timer
256 * A pointer to the TIMER peripheral register block.
257 *
258 * @param[in] ch
259 * A compare/capture channel to initialize for.
260 *
261 * @param[in] init
262 * A pointer to the TIMER initialization structure.
263 ******************************************************************************/
TIMER_InitCC(TIMER_TypeDef * timer,unsigned int ch,const TIMER_InitCC_TypeDef * init)264 void TIMER_InitCC(TIMER_TypeDef *timer,
265 unsigned int ch,
266 const TIMER_InitCC_TypeDef *init)
267 {
268 EFM_ASSERT(TIMER_REF_VALID(timer));
269 EFM_ASSERT(TIMER_REF_CH_VALIDATE(timer, ch));
270
271 #if defined (_TIMER_CC_CFG_MASK)
272 TIMER_SyncWait(timer);
273 timer->EN_CLR = TIMER_EN_EN;
274 #if defined(_TIMER_EN_DISABLING_MASK)
275 while (timer->EN & _TIMER_EN_DISABLING_MASK) {
276 }
277 #endif
278 timer->CC[ch].CFG =
279 ((uint32_t)init->mode << _TIMER_CC_CFG_MODE_SHIFT)
280 | (init->filter ? TIMER_CC_CFG_FILT_ENABLE : 0)
281 | (init->coist ? TIMER_CC_CFG_COIST : 0)
282 | ((uint32_t)init->prsOutput << _TIMER_CC_CFG_PRSCONF_SHIFT);
283
284 if (init->prsInput) {
285 timer->CC[ch].CFG |= (uint32_t)init->prsInputType << _TIMER_CC_CFG_INSEL_SHIFT;
286 bool async = (init->prsInputType != timerPrsInputSync);
287 timerPrsConfig(timer, ch, init->prsSel, async);
288 } else {
289 timer->CC[ch].CFG |= TIMER_CC_CFG_INSEL_PIN;
290 }
291 timer->EN_SET = TIMER_EN_EN;
292
293 timer->CC[ch].CTRL =
294 ((uint32_t)init->eventCtrl << _TIMER_CC_CTRL_ICEVCTRL_SHIFT)
295 | ((uint32_t)init->edge << _TIMER_CC_CTRL_ICEDGE_SHIFT)
296 | ((uint32_t)init->cufoa << _TIMER_CC_CTRL_CUFOA_SHIFT)
297 | ((uint32_t)init->cofoa << _TIMER_CC_CTRL_COFOA_SHIFT)
298 | ((uint32_t)init->cmoa << _TIMER_CC_CTRL_CMOA_SHIFT)
299 | (init->outInvert ? TIMER_CC_CTRL_OUTINV : 0);
300 #else
301 timer->CC[ch].CTRL =
302 ((uint32_t)init->eventCtrl << _TIMER_CC_CTRL_ICEVCTRL_SHIFT)
303 | ((uint32_t)init->edge << _TIMER_CC_CTRL_ICEDGE_SHIFT)
304 | ((uint32_t)init->prsSel << _TIMER_CC_CTRL_PRSSEL_SHIFT)
305 | ((uint32_t)init->cufoa << _TIMER_CC_CTRL_CUFOA_SHIFT)
306 | ((uint32_t)init->cofoa << _TIMER_CC_CTRL_COFOA_SHIFT)
307 | ((uint32_t)init->cmoa << _TIMER_CC_CTRL_CMOA_SHIFT)
308 | ((uint32_t)init->mode << _TIMER_CC_CTRL_MODE_SHIFT)
309 | (init->filter ? TIMER_CC_CTRL_FILT_ENABLE : 0)
310 | (init->prsInput ? TIMER_CC_CTRL_INSEL_PRS : 0)
311 | (init->coist ? TIMER_CC_CTRL_COIST : 0)
312 | (init->outInvert ? TIMER_CC_CTRL_OUTINV : 0)
313 #if defined(_TIMER_CC_CTRL_PRSCONF_MASK)
314 | ((uint32_t)init->prsOutput << _TIMER_CC_CTRL_PRSCONF_SHIFT)
315 #endif
316 ;
317 #endif
318 }
319
320 #if defined(_TIMER_DTCTRL_MASK)
321 /***************************************************************************//**
322 * @brief
323 * Initialize the TIMER DTI unit.
324 *
325 * @param[in] timer
326 * A pointer to the TIMER peripheral register block.
327 *
328 * @param[in] init
329 * A pointer to the TIMER DTI initialization structure.
330 ******************************************************************************/
TIMER_InitDTI(TIMER_TypeDef * timer,const TIMER_InitDTI_TypeDef * init)331 void TIMER_InitDTI(TIMER_TypeDef *timer, const TIMER_InitDTI_TypeDef *init)
332 {
333 EFM_ASSERT(TIMER_SupportsDTI(timer));
334
335 /* Make sure the DTI unit is disabled while initializing. */
336 TIMER_EnableDTI(timer, false);
337
338 #if defined (_TIMER_DTCFG_MASK)
339 TIMER_SyncWait(timer);
340 timer->EN_CLR = TIMER_EN_EN;
341 #if defined(_TIMER_EN_DISABLING_MASK)
342 while (timer->EN & _TIMER_EN_DISABLING_MASK) {
343 }
344 #endif
345 timer->DTCFG = (init->autoRestart ? TIMER_DTCFG_DTDAS : 0)
346 | (init->enablePrsSource ? TIMER_DTCFG_DTPRSEN : 0);
347 if (init->enablePrsSource) {
348 timerPrsConfig(timer, TIMER_INPUT_CHANNEL_DTI, init->prsSel, true);
349 }
350
351 timer->DTTIMECFG =
352 ((uint32_t)init->prescale << _TIMER_DTTIMECFG_DTPRESC_SHIFT)
353 | ((uint32_t)init->riseTime << _TIMER_DTTIMECFG_DTRISET_SHIFT)
354 | ((uint32_t)init->fallTime << _TIMER_DTTIMECFG_DTFALLT_SHIFT);
355
356 timer->DTFCFG =
357 (init->enableFaultSourceCoreLockup ? TIMER_DTFCFG_DTLOCKUPFEN : 0)
358 | (init->enableFaultSourceDebugger ? TIMER_DTFCFG_DTDBGFEN : 0)
359 | (init->enableFaultSourcePrsSel0 ? TIMER_DTFCFG_DTPRS0FEN : 0)
360 | (init->enableFaultSourcePrsSel1 ? TIMER_DTFCFG_DTPRS1FEN : 0)
361 | ((uint32_t)(init->faultAction) << _TIMER_DTFCFG_DTFA_SHIFT);
362
363 if (init->enableFaultSourcePrsSel0) {
364 timerPrsConfig(timer, TIMER_INPUT_CHANNEL_DTIFS1, init->faultSourcePrsSel0, true);
365 }
366 if (init->enableFaultSourcePrsSel1) {
367 timerPrsConfig(timer, TIMER_INPUT_CHANNEL_DTIFS2, init->faultSourcePrsSel1, true);
368 }
369
370 timer->EN_SET = TIMER_EN_EN;
371 #endif
372
373 #if defined(TIMER_DTCTRL_DTDAS)
374 /* Set up the DTCTRL register.
375 The enable bit will be set at the end of the function if specified. */
376 timer->DTCTRL =
377 (init->autoRestart ? TIMER_DTCTRL_DTDAS : 0)
378 | (init->activeLowOut ? TIMER_DTCTRL_DTIPOL : 0)
379 | (init->invertComplementaryOut ? TIMER_DTCTRL_DTCINV : 0)
380 | (init->enablePrsSource ? TIMER_DTCTRL_DTPRSEN : 0)
381 | ((uint32_t)(init->prsSel) << _TIMER_DTCTRL_DTPRSSEL_SHIFT);
382 #endif
383
384 #if defined (TIMER_DTCFG_DTDAS)
385 timer->DTCTRL = (init->activeLowOut ? TIMER_DTCTRL_DTIPOL : 0)
386 | (init->invertComplementaryOut ? TIMER_DTCTRL_DTCINV : 0);
387 #endif
388
389 #if defined (_TIMER_DTTIME_DTPRESC_SHIFT)
390 /* Set up the DTTIME register. */
391 timer->DTTIME = ((uint32_t)init->prescale << _TIMER_DTTIME_DTPRESC_SHIFT)
392 | ((uint32_t)init->riseTime << _TIMER_DTTIME_DTRISET_SHIFT)
393 | ((uint32_t)init->fallTime << _TIMER_DTTIME_DTFALLT_SHIFT);
394 #endif
395
396 #if defined (TIMER_DTFC_DTLOCKUPFEN)
397 /* Set up the DTFC register. */
398 timer->DTFC =
399 (init->enableFaultSourceCoreLockup ? TIMER_DTFC_DTLOCKUPFEN : 0)
400 | (init->enableFaultSourceDebugger ? TIMER_DTFC_DTDBGFEN : 0)
401 | (init->enableFaultSourcePrsSel0 ? TIMER_DTFC_DTPRS0FEN : 0)
402 | (init->enableFaultSourcePrsSel1 ? TIMER_DTFC_DTPRS1FEN : 0)
403 | ((uint32_t)init->faultAction << _TIMER_DTFC_DTFA_SHIFT)
404 | ((uint32_t)init->faultSourcePrsSel0 << _TIMER_DTFC_DTPRS0FSEL_SHIFT)
405 | ((uint32_t)init->faultSourcePrsSel1 << _TIMER_DTFC_DTPRS1FSEL_SHIFT);
406 #endif
407
408 /* Set up the DTOGEN register. */
409 timer->DTOGEN = init->outputsEnableMask;
410
411 /* Clear any previous DTI faults. */
412 TIMER_ClearDTIFault(timer, TIMER_GetDTIFault(timer));
413
414 /* Enable/disable before returning. */
415 TIMER_EnableDTI(timer, init->enable);
416 }
417 #endif
418
419 /***************************************************************************//**
420 * @brief
421 * Reset the TIMER to the same state that it was in after a hardware reset.
422 *
423 * @note
424 * The ROUTE register is NOT reset by this function to allow for
425 * a centralized setup of this feature.
426 *
427 * @param[in] timer
428 * A pointer to the TIMER peripheral register block.
429 ******************************************************************************/
TIMER_Reset(TIMER_TypeDef * timer)430 void TIMER_Reset(TIMER_TypeDef *timer)
431 {
432 int i;
433
434 EFM_ASSERT(TIMER_REF_VALID(timer));
435
436 #if defined(TIMER_EN_EN)
437 timer->EN_SET = TIMER_EN_EN;
438 #endif
439
440 /* Make sure disabled first, before resetting other registers. */
441 timer->CMD = TIMER_CMD_STOP;
442
443 timer->CTRL = _TIMER_CTRL_RESETVALUE;
444 timer->IEN = _TIMER_IEN_RESETVALUE;
445 #if defined (TIMER_HAS_SET_CLEAR)
446 timer->IF_CLR = _TIMER_IF_MASK;
447 #else
448 timer->IFC = _TIMER_IFC_MASK;
449 #endif
450 timer->TOPB = _TIMER_TOPB_RESETVALUE;
451 /* Write TOP after TOPB to invalidate TOPB (clear TIMER_STATUS_TOPBV). */
452 timer->TOP = _TIMER_TOP_RESETVALUE;
453 timer->CNT = _TIMER_CNT_RESETVALUE;
454 /* Do not reset the route register, setting should be done independently. */
455 /* Note: The ROUTE register may be locked by the DTLOCK register. */
456
457 for (i = 0; TIMER_REF_CH_VALIDATE(timer, i); i++) {
458 timer->CC[i].CTRL = _TIMER_CC_CTRL_RESETVALUE;
459 #if defined (_TIMER_CC_CCV_RESETVALUE) && defined (_TIMER_CC_CCVB_RESETVALUE)
460 timer->CC[i].CCV = _TIMER_CC_CCV_RESETVALUE;
461 timer->CC[i].CCVB = _TIMER_CC_CCVB_RESETVALUE;
462 #endif
463 #if defined (_TIMER_CC_OC_RESETVALUE) && defined (_TIMER_CC_OCB_RESETVALUE) \
464 && defined (_TIMER_CC_ICF_RESETVALUE) && defined (_TIMER_CC_ICOF_RESETVALUE)
465 timer->CC[i].OC = _TIMER_CC_OC_RESETVALUE;
466 timer->CC[i].OCB = _TIMER_CC_OCB_RESETVALUE;
467 #endif
468 }
469
470 /* Reset dead time insertion module, which has no effect on timers without DTI. */
471 #if defined(_TIMER_DTCFG_MASK)
472 timer->DTLOCK = TIMER_DTLOCK_DTILOCKKEY_UNLOCK;
473 timer->DTCTRL = _TIMER_DTCTRL_RESETVALUE;
474 timer->DTOGEN = _TIMER_DTOGEN_RESETVALUE;
475 timer->DTFAULTC = _TIMER_DTFAULTC_MASK;
476 #elif defined(TIMER_DTLOCK_LOCKKEY_UNLOCK)
477 /* Unlock DTI registers first if locked. */
478 timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_UNLOCK;
479 timer->DTCTRL = _TIMER_DTCTRL_RESETVALUE;
480 timer->DTTIME = _TIMER_DTTIME_RESETVALUE;
481 timer->DTFC = _TIMER_DTFC_RESETVALUE;
482 timer->DTOGEN = _TIMER_DTOGEN_RESETVALUE;
483 timer->DTFAULTC = _TIMER_DTFAULTC_MASK;
484 #endif
485
486 #if defined(_TIMER_CFG_MASK)
487 TIMER_SyncWait(timer);
488 /* CFG registers must be reset after the timer is disabled */
489 timer->EN_CLR = TIMER_EN_EN;
490 #if defined(_TIMER_EN_DISABLING_MASK)
491 while (timer->EN & _TIMER_EN_DISABLING_MASK) {
492 }
493 #endif
494 timer->CFG = _TIMER_CFG_RESETVALUE;
495 for (i = 0; TIMER_REF_CH_VALIDATE(timer, i); i++) {
496 timer->CC[i].CFG = _TIMER_CC_CFG_RESETVALUE;
497 }
498 timer->DTCFG = _TIMER_DTCFG_RESETVALUE;
499 timer->DTFCFG = _TIMER_DTFCFG_RESETVALUE;
500 timer->DTTIMECFG = _TIMER_DTTIMECFG_RESETVALUE;
501 #endif
502 }
503
504 #if defined(TIMER_STATUS_SYNCBUSY)
505 /**
506 * @brief Wait for pending synchronization to finish
507 *
508 * @param[in] timer
509 */
TIMER_SyncWait(TIMER_TypeDef * timer)510 void TIMER_SyncWait(TIMER_TypeDef * timer)
511 {
512 while (((timer->EN & TIMER_EN_EN) != 0U)
513 && ((timer->STATUS & TIMER_STATUS_SYNCBUSY) != 0U)) {
514 /* Wait for synchronization to complete */
515 }
516 }
517 #endif
518
519 /** @} (end addtogroup timer) */
520 #endif /* defined(TIMER_COUNT) && (TIMER_COUNT > 0) */
521