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