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