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