1 /***************************************************************************//**
2  * @file
3  * @brief Watchdog (WDOG) 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_WDOG_H
32 #define EM_WDOG_H
33 
34 #include "em_device.h"
35 #if defined(WDOG_COUNT) && (WDOG_COUNT > 0)
36 
37 #include <stdbool.h>
38 #include "sl_common.h"
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /***************************************************************************//**
45  * @addtogroup wdog
46  * @{
47  ******************************************************************************/
48 
49 /*******************************************************************************
50  *******************************   DEFINES   ***********************************
51  ******************************************************************************/
52 
53 /** Default WDOG instance for deprecated functions. */
54 #if !defined(DEFAULT_WDOG)
55 #if defined(WDOG0)
56 #define DEFAULT_WDOG WDOG0
57 #elif defined(WDOG)
58 #define DEFAULT_WDOG WDOG
59 #endif
60 #endif
61 
62 /*******************************************************************************
63  ********************************   ENUMS   ************************************
64  ******************************************************************************/
65 
66 /** Watchdog clock selection. */
67 #if defined(_WDOG_CTRL_CLKSEL_MASK)
68 typedef enum {
69   wdogClkSelULFRCO = _WDOG_CTRL_CLKSEL_ULFRCO,   /**< Ultra low frequency (1 kHz) clock */
70   wdogClkSelLFRCO  = _WDOG_CTRL_CLKSEL_LFRCO,    /**< Low frequency RC oscillator */
71   wdogClkSelLFXO   = _WDOG_CTRL_CLKSEL_LFXO      /**< Low frequency crystal oscillator */
72 } WDOG_ClkSel_TypeDef;
73 #endif
74 
75 /** Watchdog period selection. */
76 typedef enum {
77   wdogPeriod_9    = 0x0, /**< 9 clock periods */
78   wdogPeriod_17   = 0x1, /**< 17 clock periods */
79   wdogPeriod_33   = 0x2, /**< 33 clock periods */
80   wdogPeriod_65   = 0x3, /**< 65 clock periods */
81   wdogPeriod_129  = 0x4, /**< 129 clock periods */
82   wdogPeriod_257  = 0x5, /**< 257 clock periods */
83   wdogPeriod_513  = 0x6, /**< 513 clock periods */
84   wdogPeriod_1k   = 0x7, /**< 1025 clock periods */
85   wdogPeriod_2k   = 0x8, /**< 2049 clock periods */
86   wdogPeriod_4k   = 0x9, /**< 4097 clock periods */
87   wdogPeriod_8k   = 0xA, /**< 8193 clock periods */
88   wdogPeriod_16k  = 0xB, /**< 16385 clock periods */
89   wdogPeriod_32k  = 0xC, /**< 32769 clock periods */
90   wdogPeriod_64k  = 0xD, /**< 65537 clock periods */
91   wdogPeriod_128k = 0xE, /**< 131073 clock periods */
92   wdogPeriod_256k = 0xF  /**< 262145 clock periods */
93 } WDOG_PeriodSel_TypeDef;
94 
95 #if defined(_WDOG_CTRL_WARNSEL_MASK) \
96   || defined(_WDOG_CFG_WARNSEL_MASK)
97 /** Select Watchdog warning timeout period as percentage of timeout. */
98 typedef enum {
99   wdogWarnDisable   = 0, /**< Watchdog warning period is disabled. */
100   wdogWarnTime25pct = 1, /**< Watchdog warning period is 25% of the timeout. */
101   wdogWarnTime50pct = 2, /**< Watchdog warning period is 50% of the timeout. */
102   wdogWarnTime75pct = 3, /**< Watchdog warning period is 75% of the timeout. */
103 } WDOG_WarnSel_TypeDef;
104 #endif
105 
106 #if defined(_WDOG_CTRL_WINSEL_MASK) \
107   || defined(_WDOG_CFG_WINSEL_MASK)
108 /**  Select Watchdog illegal window limit. */
109 typedef enum {
110   wdogIllegalWindowDisable     = 0, /**< Watchdog illegal window disabled. */
111   wdogIllegalWindowTime12_5pct = 1, /**< Window timeout is 12.5% of the timeout. */
112   wdogIllegalWindowTime25_0pct = 2, /**< Window timeout is 25% of the timeout. */
113   wdogIllegalWindowTime37_5pct = 3, /**< Window timeout is 37.5% of the timeout. */
114   wdogIllegalWindowTime50_0pct = 4, /**< Window timeout is 50% of the timeout. */
115   wdogIllegalWindowTime62_5pct = 5, /**< Window timeout is 62.5% of the timeout. */
116   wdogIllegalWindowTime75_0pct = 6, /**< Window timeout is 75% of the timeout. */
117   wdogIllegalWindowTime87_5pct = 7, /**< Window timeout is 87.5% of the timeout. */
118 } WDOG_WinSel_TypeDef;
119 #endif
120 
121 /*******************************************************************************
122  *******************************   STRUCTS   ***********************************
123  ******************************************************************************/
124 
125 /** Watchdog initialization structure. */
126 typedef struct {
127   /** Enable Watchdog when initialization completed. */
128   bool                   enable;
129 
130   /** Counter keeps running during debug halt. */
131   bool                   debugRun;
132 
133 #if defined(_WDOG_CTRL_CLRSRC_MASK) \
134   || defined(_WDOG_CFG_CLRSRC_MASK)
135   /** Select WDOG clear source:
136    *  False: Write to the clear bit will clear the WDOG counter
137    *  True: Rising edge on the PRS Source 0 will clear the WDOG counter
138    *  */
139   bool                   clrSrc;
140 #endif
141 
142 #if defined(_WDOG_CFG_EM1RUN_MASK)
143   /** Counter keeps running when in EM1. Available for series2. */
144   bool                   em1Run;
145 #endif
146 
147   /** Counter keeps running when in EM2. */
148   bool                   em2Run;
149 
150   /** Counter keeps running when in EM3. */
151   bool                   em3Run;
152 
153   /** Block EMU from entering EM4. */
154   bool                   em4Block;
155 
156 #if defined(_WDOG_CFG_MASK)
157   /** When set, a PRS Source 0 missing event will trigger a WDOG reset. */
158   bool                   prs0MissRstEn;
159 
160   /** When set, a PRS Source 1 missing event will trigger a WDOG reset. */
161   bool                   prs1MissRstEn;
162 #endif
163 
164   /** Block SW from disabling LFRCO/LFXO oscillators. */
165 #if defined(_WDOG_CTRL_SWOSCBLOCK_MASK)
166   bool                   swoscBlock;
167 #endif
168 
169   /** Block SW from modifying the configuration (a reset is needed to reconfigure). */
170   bool                   lock;
171 
172   /** Clock source to use for Watchdog. */
173 #if defined(_WDOG_CTRL_CLKSEL_MASK)
174   WDOG_ClkSel_TypeDef    clkSel;
175 #endif
176 
177   /** Watchdog timeout period. */
178   WDOG_PeriodSel_TypeDef perSel;
179 
180 #if defined(_WDOG_CTRL_WARNSEL_MASK) \
181   || defined(_WDOG_CFG_WARNSEL_MASK)
182   /** Select warning time as % of the Watchdog timeout */
183   WDOG_WarnSel_TypeDef   warnSel;
184 #endif
185 
186 #if defined(_WDOG_CTRL_WINSEL_MASK) \
187   || defined(_WDOG_CFG_WINSEL_MASK)
188   /** Select illegal window time as % of the Watchdog timeout */
189   WDOG_WinSel_TypeDef    winSel;
190 #endif
191 
192 #if defined(_WDOG_CTRL_WDOGRSTDIS_MASK) \
193   || defined(_WDOG_CFG_WDOGRSTDIS_MASK)
194   /** Disable Watchdog reset output if true */
195   bool                   resetDisable;
196 #endif
197 } WDOG_Init_TypeDef;
198 
199 /** Suggested default configuration for WDOG initialization structure. */
200 #if defined(_WDOG_CFG_MASK) && defined(_WDOG_CFG_EM1RUN_MASK)
201 #define WDOG_INIT_DEFAULT                                                                     \
202   {                                                                                           \
203     true,                     /* Start Watchdog when initialization is done. */               \
204     false,                    /* WDOG is not counting during debug halt. */                   \
205     false,                    /* The clear bit will clear the WDOG counter. */                \
206     false,                    /* WDOG is not counting when in EM1. */                         \
207     false,                    /* WDOG is not counting when in EM2. */                         \
208     false,                    /* WDOG is not counting when in EM3. */                         \
209     false,                    /* EM4 can be entered. */                                       \
210     false,                    /* PRS Source 0 missing event will not trigger a WDOG reset. */ \
211     false,                    /* PRS Source 1 missing event will not trigger a WDOG reset. */ \
212     false,                    /* Do not lock WDOG configuration. */                           \
213     wdogPeriod_256k,          /* Set longest possible timeout period. */                      \
214     wdogWarnDisable,          /* Disable warning interrupt. */                                \
215     wdogIllegalWindowDisable, /* Disable illegal window interrupt. */                         \
216     false                     /* Do not disable reset. */                                     \
217   }
218 #elif defined(_WDOG_CFG_MASK)
219 #define WDOG_INIT_DEFAULT                                                                     \
220   {                                                                                           \
221     true,                     /* Start Watchdog when initialization is done. */               \
222     false,                    /* WDOG is not counting during debug halt. */                   \
223     false,                    /* The clear bit will clear the WDOG counter. */                \
224     false,                    /* WDOG is not counting when in EM2. */                         \
225     false,                    /* WDOG is not counting when in EM3. */                         \
226     false,                    /* EM4 can be entered. */                                       \
227     false,                    /* PRS Source 0 missing event will not trigger a WDOG reset. */ \
228     false,                    /* PRS Source 1 missing event will not trigger a WDOG reset. */ \
229     false,                    /* Do not lock WDOG configuration. */                           \
230     wdogPeriod_256k,          /* Set longest possible timeout period. */                      \
231     wdogWarnDisable,          /* Disable warning interrupt. */                                \
232     wdogIllegalWindowDisable, /* Disable illegal window interrupt. */                         \
233     false                     /* Do not disable reset. */                                     \
234   }
235 #elif defined(_WDOG_CTRL_WARNSEL_MASK)   \
236   && defined(_WDOG_CTRL_WDOGRSTDIS_MASK) \
237   && defined(_WDOG_CTRL_WINSEL_MASK)
238 #define WDOG_INIT_DEFAULT                                                       \
239   {                                                                             \
240     true,                     /* Start Watchdog when initialization is done. */ \
241     false,                    /* WDOG is not counting during debug halt. */     \
242     false,                    /* The clear bit will clear the WDOG counter. */  \
243     false,                    /* WDOG is not counting when in EM2. */           \
244     false,                    /* WDOG is not counting when in EM3. */           \
245     false,                    /* EM4 can be entered. */                         \
246     false,                    /* Do not block disabling LFRCO/LFXO in CMU. */   \
247     false,                    /* Do not lock WDOG configuration. */             \
248     wdogClkSelLFRCO,          /* Select 32.768 kHZ WDOG oscillator. */          \
249     wdogPeriod_256k,          /* Set longest possible timeout period. */        \
250     wdogWarnDisable,          /* Disable warning interrupt. */                  \
251     wdogIllegalWindowDisable, /* Disable illegal window interrupt. */           \
252     false                     /* Do not disable reset. */                       \
253   }
254 #else
255 #define WDOG_INIT_DEFAULT                                                       \
256   {                                                                             \
257     true,                     /* Start Watchdog when initialization is done. */ \
258     false,                    /* WDOG is not counting during debug halt. */     \
259     false,                    /* WDOG is not counting when in EM2. */           \
260     false,                    /* WDOG is not counting when in EM3. */           \
261     false,                    /* EM4 can be entered. */                         \
262     false,                    /* Do not block disabling LFRCO/LFXO in CMU. */   \
263     false,                    /* Do not lock WDOG configuration. */             \
264     wdogClkSelLFRCO,          /* Select 32.768 kHz WDOG oscillator. */          \
265     wdogPeriod_256k           /* Set longest possible timeout period. */        \
266   }
267 #endif
268 
269 /*******************************************************************************
270  *****************************   PROTOTYPES   **********************************
271  ******************************************************************************/
272 
273 void WDOGn_Enable(WDOG_TypeDef *wdog, bool enable);
274 void WDOGn_Feed(WDOG_TypeDef *wdog);
275 void WDOGn_Init(WDOG_TypeDef *wdog, const WDOG_Init_TypeDef *init);
276 void WDOGn_Lock(WDOG_TypeDef *wdog);
277 void WDOGn_SyncWait(WDOG_TypeDef *wdog);
278 void WDOGn_Unlock(WDOG_TypeDef *wdog);
279 
280 #if defined(_WDOG_IF_MASK)
281 /***************************************************************************//**
282  * @brief
283  *   Clear one or more pending WDOG interrupts.
284  *
285  * @param[in] wdog
286  *   Pointer to the WDOG peripheral register block.
287  *
288  * @param[in] flags
289  *   WDOG interrupt sources to clear. Use a set of interrupt flags OR-ed
290  *   together to clear multiple interrupt sources.
291  ******************************************************************************/
WDOGn_IntClear(WDOG_TypeDef * wdog,uint32_t flags)292 __STATIC_INLINE void WDOGn_IntClear(WDOG_TypeDef *wdog, uint32_t flags)
293 {
294 #if defined(WDOG_HAS_SET_CLEAR)
295   wdog->IF_CLR = flags;
296 #else
297   wdog->IFC = flags;
298 #endif
299 }
300 
301 /***************************************************************************//**
302  * @brief
303  *   Disable one or more WDOG interrupts.
304  *
305  * @param[in] wdog
306  *   Pointer to the WDOG peripheral register block.
307  *
308  * @param[in] flags
309  *   WDOG interrupt sources to disable. Use a set of interrupt flags OR-ed
310  *   together to disable multiple interrupt.
311  ******************************************************************************/
WDOGn_IntDisable(WDOG_TypeDef * wdog,uint32_t flags)312 __STATIC_INLINE void WDOGn_IntDisable(WDOG_TypeDef *wdog, uint32_t flags)
313 {
314 #if defined(WDOG_HAS_SET_CLEAR)
315   wdog->IEN_CLR = flags;
316 #else
317   wdog->IEN &= ~flags;
318 #endif
319 }
320 
321 /***************************************************************************//**
322  * @brief
323  *   Enable one or more WDOG interrupts.
324  *
325  * @note
326  *   Depending on the use, a pending interrupt may already be set prior to
327  *   enabling the interrupt. To ignore a pending interrupt, consider using
328  *   WDOG_IntClear() prior to enabling the interrupt.
329  *
330  * @param[in] wdog
331  *   Pointer to the WDOG peripheral register block.
332  *
333  * @param[in] flags
334  *   WDOG interrupt sources to enable. Use a set of interrupt flags OR-ed
335  *   together to set multiple interrupt.
336  ******************************************************************************/
WDOGn_IntEnable(WDOG_TypeDef * wdog,uint32_t flags)337 __STATIC_INLINE void WDOGn_IntEnable(WDOG_TypeDef *wdog, uint32_t flags)
338 {
339 #if defined(WDOG_HAS_SET_CLEAR)
340   wdog->IEN_SET = flags;
341 #else
342   wdog->IEN |= flags;
343 #endif
344 }
345 
346 /***************************************************************************//**
347  * @brief
348  *   Get pending WDOG interrupt flags.
349  *
350  * @note
351  *   The event bits are not cleared by the use of this function.
352  *
353  * @param[in] wdog
354  *   Pointer to the WDOG peripheral register block.
355  *
356  * @return
357  *   Pending WDOG interrupt sources. Returns a set of interrupt flags OR-ed
358  *   together for the interrupt sources set.
359  ******************************************************************************/
WDOGn_IntGet(WDOG_TypeDef * wdog)360 __STATIC_INLINE uint32_t WDOGn_IntGet(WDOG_TypeDef *wdog)
361 {
362   return wdog->IF;
363 }
364 
365 /***************************************************************************//**
366  * @brief
367  *   Get enabled and pending WDOG interrupt flags.
368  *
369  * @details
370  *   Useful for handling more interrupt sources in the same interrupt handler.
371  *
372  * @param[in] wdog
373  *   Pointer to the WDOG peripheral register block.
374  *
375  * @return
376  *   Pending and enabled WDOG interrupt sources. Returns a set of interrupt
377  *   flags OR-ed together for the interrupt sources set.
378  ******************************************************************************/
WDOGn_IntGetEnabled(WDOG_TypeDef * wdog)379 __STATIC_INLINE uint32_t WDOGn_IntGetEnabled(WDOG_TypeDef *wdog)
380 {
381   uint32_t tmp;
382 
383   tmp = wdog->IEN;
384 
385   /* Bitwise AND of pending and enabled interrupt flags. */
386   return wdog->IF & tmp;
387 }
388 
389 /***************************************************************************//**
390  * @brief
391  *   Set one or more pending WDOG interrupts from SW.
392  *
393  * @param[in] wdog
394  *   Pointer to the WDOG peripheral register block.
395  *
396  * @param[in] flags
397  *   WDOG interrupt sources to set to pending. Use a set of interrupt flags
398  *   (WDOG_IFS_nnn).
399  ******************************************************************************/
WDOGn_IntSet(WDOG_TypeDef * wdog,uint32_t flags)400 __STATIC_INLINE void WDOGn_IntSet(WDOG_TypeDef *wdog, uint32_t flags)
401 {
402 #if defined(WDOG_HAS_SET_CLEAR)
403   wdog->IF_SET = flags;
404 #else
405   wdog->IFS = flags;
406 #endif
407 }
408 #endif
409 
410 /***************************************************************************//**
411  * @brief
412  *   Get enabled status of the Watchdog.
413  *
414  * @param[in] wdog
415  *   Pointer to the WDOG peripheral register block.
416  *
417  * @return
418  *   True if Watchdog is enabled.
419  ******************************************************************************/
WDOGn_IsEnabled(WDOG_TypeDef * wdog)420 __STATIC_INLINE bool WDOGn_IsEnabled(WDOG_TypeDef *wdog)
421 {
422 #if defined(_WDOG_EN_MASK)
423   return (wdog->EN & _WDOG_EN_EN_MASK) == WDOG_EN_EN;
424 #else
425   return (wdog->CTRL & _WDOG_CTRL_EN_MASK) == WDOG_CTRL_EN;
426 #endif
427 }
428 
429 /***************************************************************************//**
430  * @brief
431  *   Get locked status of the Watchdog.
432  *
433  * @param[in] wdog
434  *   Pointer to the WDOG peripheral register block.
435  *
436  * @return
437  *   True if Watchdog is locked.
438  ******************************************************************************/
WDOGn_IsLocked(WDOG_TypeDef * wdog)439 __STATIC_INLINE bool WDOGn_IsLocked(WDOG_TypeDef *wdog)
440 {
441 #if defined(_WDOG_STATUS_MASK)
442   return (wdog->STATUS & _WDOG_STATUS_LOCK_MASK) == WDOG_STATUS_LOCK_LOCKED;
443 #else
444   return (wdog->CTRL & _WDOG_CTRL_LOCK_MASK) == WDOG_CTRL_LOCK;
445 #endif
446 }
447 
448 /** @} (end addtogroup wdog) */
449 
450 #ifdef __cplusplus
451 }
452 #endif
453 
454 #endif /* defined(WDOG_COUNT) && (WDOG_COUNT > 0) */
455 #endif /* EM_WDOG_H */
456