/***************************************************************************//** * @file * @brief Watchdog (WDOG) peripheral API ******************************************************************************* * # License * Copyright 2018 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #ifndef EM_WDOG_H #define EM_WDOG_H #include "em_device.h" #if defined(WDOG_COUNT) && (WDOG_COUNT > 0) #include #ifdef __cplusplus extern "C" { #endif /***************************************************************************//** * @addtogroup wdog * @{ ******************************************************************************/ /******************************************************************************* ******************************* DEFINES *********************************** ******************************************************************************/ /** Default WDOG instance for deprecated functions. */ #if !defined(DEFAULT_WDOG) #if defined(WDOG0) #define DEFAULT_WDOG WDOG0 #elif defined(WDOG) #define DEFAULT_WDOG WDOG #endif #endif /******************************************************************************* ******************************** ENUMS ************************************ ******************************************************************************/ /** Watchdog clock selection. */ #if defined(_WDOG_CTRL_CLKSEL_MASK) typedef enum { wdogClkSelULFRCO = _WDOG_CTRL_CLKSEL_ULFRCO, /**< Ultra low frequency (1 kHz) clock */ wdogClkSelLFRCO = _WDOG_CTRL_CLKSEL_LFRCO, /**< Low frequency RC oscillator */ wdogClkSelLFXO = _WDOG_CTRL_CLKSEL_LFXO /**< Low frequency crystal oscillator */ } WDOG_ClkSel_TypeDef; #endif /** Watchdog period selection. */ typedef enum { wdogPeriod_9 = 0x0, /**< 9 clock periods */ wdogPeriod_17 = 0x1, /**< 17 clock periods */ wdogPeriod_33 = 0x2, /**< 33 clock periods */ wdogPeriod_65 = 0x3, /**< 65 clock periods */ wdogPeriod_129 = 0x4, /**< 129 clock periods */ wdogPeriod_257 = 0x5, /**< 257 clock periods */ wdogPeriod_513 = 0x6, /**< 513 clock periods */ wdogPeriod_1k = 0x7, /**< 1025 clock periods */ wdogPeriod_2k = 0x8, /**< 2049 clock periods */ wdogPeriod_4k = 0x9, /**< 4097 clock periods */ wdogPeriod_8k = 0xA, /**< 8193 clock periods */ wdogPeriod_16k = 0xB, /**< 16385 clock periods */ wdogPeriod_32k = 0xC, /**< 32769 clock periods */ wdogPeriod_64k = 0xD, /**< 65537 clock periods */ wdogPeriod_128k = 0xE, /**< 131073 clock periods */ wdogPeriod_256k = 0xF /**< 262145 clock periods */ } WDOG_PeriodSel_TypeDef; #if defined(_WDOG_CTRL_WARNSEL_MASK) \ || defined(_WDOG_CFG_WARNSEL_MASK) /** Select watchdog warning timeout period as percentage of timeout. */ typedef enum { wdogWarnDisable = 0, wdogWarnTime25pct = 1, wdogWarnTime50pct = 2, wdogWarnTime75pct = 3, } WDOG_WarnSel_TypeDef; #endif #if defined(_WDOG_CTRL_WINSEL_MASK) \ || defined(_WDOG_CFG_WINSEL_MASK) /** Select watchdog illegal window limit. */ typedef enum { wdogIllegalWindowDisable = 0, wdogIllegalWindowTime12_5pct = 1, wdogIllegalWindowTime25_0pct = 2, wdogIllegalWindowTime37_5pct = 3, wdogIllegalWindowTime50_0pct = 4, wdogIllegalWindowTime62_5pct = 5, wdogIllegalWindowTime75_0pct = 6, wdogIllegalWindowTime87_5pct = 7, } WDOG_WinSel_TypeDef; #endif /******************************************************************************* ******************************* STRUCTS *********************************** ******************************************************************************/ /** Watchdog initialization structure. */ typedef struct { /** Enable watchdog when initialization completed. */ bool enable; /** Counter keeps running during debug halt. */ bool debugRun; /** Counter keeps running when in EM2. */ bool em2Run; /** Counter keeps running when in EM3. */ bool em3Run; /** Block EMU from entering EM4. */ bool em4Block; /** Block SW from disabling LFRCO/LFXO oscillators. */ #if defined(_WDOG_CTRL_SWOSCBLOCK_MASK) bool swoscBlock; #endif /** Block SW from modifying the configuration (a reset is needed to reconfigure). */ bool lock; /** Clock source to use for watchdog. */ #if defined(_WDOG_CTRL_CLKSEL_MASK) WDOG_ClkSel_TypeDef clkSel; #endif /** Watchdog timeout period. */ WDOG_PeriodSel_TypeDef perSel; #if defined(_WDOG_CTRL_WARNSEL_MASK) \ || defined(_WDOG_CFG_WARNSEL_MASK) /** Select warning time as % of the watchdog timeout */ WDOG_WarnSel_TypeDef warnSel; #endif #if defined(_WDOG_CTRL_WINSEL_MASK) \ || defined(_WDOG_CFG_WINSEL_MASK) /** Select illegal window time as % of the watchdog timeout */ WDOG_WinSel_TypeDef winSel; #endif #if defined(_WDOG_CTRL_WDOGRSTDIS_MASK) \ || defined(_WDOG_CFG_WDOGRSTDIS_MASK) /** Disable watchdog reset output if true */ bool resetDisable; #endif } WDOG_Init_TypeDef; /** Suggested default configuration for WDOG initialization structure. */ #if defined(_WDOG_CFG_MASK) #define WDOG_INIT_DEFAULT \ { \ true, /* Start watchdog when initialization is done. */ \ false, /* WDOG is not counting during debug halt. */ \ false, /* WDOG is not counting when in EM2. */ \ false, /* WDOG is not counting when in EM3. */ \ false, /* EM4 can be entered. */ \ false, /* Do not lock WDOG configuration. */ \ wdogPeriod_256k, /* Set longest possible timeout period. */ \ wdogWarnDisable, /* Disable warning interrupt. */ \ wdogIllegalWindowDisable, /* Disable illegal window interrupt. */ \ false /* Do not disable reset. */ \ } #elif defined(_WDOG_CTRL_WARNSEL_MASK) \ && defined(_WDOG_CTRL_WDOGRSTDIS_MASK) \ && defined(_WDOG_CTRL_WINSEL_MASK) #define WDOG_INIT_DEFAULT \ { \ true, /* Start watchdog when initialization is done. */ \ false, /* WDOG is not counting during debug halt. */ \ false, /* WDOG is not counting when in EM2. */ \ false, /* WDOG is not counting when in EM3. */ \ false, /* EM4 can be entered. */ \ false, /* Do not block disabling LFRCO/LFXO in CMU. */ \ false, /* Do not lock WDOG configuration. */ \ wdogClkSelLFRCO, /* Select 32.768 kHZ WDOG oscillator. */ \ wdogPeriod_256k, /* Set longest possible timeout period. */ \ wdogWarnDisable, /* Disable warning interrupt. */ \ wdogIllegalWindowDisable, /* Disable illegal window interrupt. */ \ false /* Do not disable reset. */ \ } #else #define WDOG_INIT_DEFAULT \ { \ true, /* Start watchdog when initialization is done. */ \ false, /* WDOG is not counting during debug halt. */ \ false, /* WDOG is not counting when in EM2. */ \ false, /* WDOG is not counting when in EM3. */ \ false, /* EM4 can be entered. */ \ false, /* Do not block disabling LFRCO/LFXO in CMU. */ \ false, /* Do not lock WDOG configuration. */ \ wdogClkSelLFRCO, /* Select 32.768 kHz WDOG oscillator. */ \ wdogPeriod_256k /* Set longest possible timeout period. */ \ } #endif /******************************************************************************* ***************************** PROTOTYPES ********************************** ******************************************************************************/ void WDOGn_Enable(WDOG_TypeDef *wdog, bool enable); void WDOGn_Feed(WDOG_TypeDef *wdog); void WDOGn_Init(WDOG_TypeDef *wdog, const WDOG_Init_TypeDef *init); void WDOGn_Lock(WDOG_TypeDef *wdog); void WDOGn_SyncWait(WDOG_TypeDef *wdog); void WDOGn_Unlock(WDOG_TypeDef *wdog); #if defined(_WDOG_IF_MASK) /***************************************************************************//** * @brief * Clear one or more pending WDOG interrupts. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @param[in] flags * WDOG interrupt sources to clear. Use a set of interrupt flags OR-ed * together to clear multiple interrupt sources. ******************************************************************************/ __STATIC_INLINE void WDOGn_IntClear(WDOG_TypeDef *wdog, uint32_t flags) { #if defined(WDOG_HAS_SET_CLEAR) wdog->IF_CLR = flags; #else wdog->IFC = flags; #endif } /***************************************************************************//** * @brief * Disable one or more WDOG interrupts. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @param[in] flags * WDOG interrupt sources to disable. Use a set of interrupt flags OR-ed * together to disable multiple interrupt. ******************************************************************************/ __STATIC_INLINE void WDOGn_IntDisable(WDOG_TypeDef *wdog, uint32_t flags) { #if defined(WDOG_HAS_SET_CLEAR) wdog->IEN_CLR = flags; #else wdog->IEN &= ~flags; #endif } /***************************************************************************//** * @brief * Enable one or more WDOG interrupts. * * @note * Depending on the use, a pending interrupt may already be set prior to * enabling the interrupt. To ignore a pending interrupt, consider using * WDOG_IntClear() prior to enabling the interrupt. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @param[in] flags * WDOG interrupt sources to enable. Use a set of interrupt flags OR-ed * together to set multiple interrupt. ******************************************************************************/ __STATIC_INLINE void WDOGn_IntEnable(WDOG_TypeDef *wdog, uint32_t flags) { #if defined(WDOG_HAS_SET_CLEAR) wdog->IEN_SET = flags; #else wdog->IEN |= flags; #endif } /***************************************************************************//** * @brief * Get pending WDOG interrupt flags. * * @note * The event bits are not cleared by the use of this function. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @return * Pending WDOG interrupt sources. Returns a set of interrupt flags OR-ed * together for the interrupt sources set. ******************************************************************************/ __STATIC_INLINE uint32_t WDOGn_IntGet(WDOG_TypeDef *wdog) { return wdog->IF; } /***************************************************************************//** * @brief * Get enabled and pending WDOG interrupt flags. * * @details * Useful for handling more interrupt sources in the same interrupt handler. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @return * Pending and enabled WDOG interrupt sources. Returns a set of interrupt * flags OR-ed together for the interrupt sources set. ******************************************************************************/ __STATIC_INLINE uint32_t WDOGn_IntGetEnabled(WDOG_TypeDef *wdog) { uint32_t tmp; tmp = wdog->IEN; /* Bitwise AND of pending and enabled interrupt flags. */ return wdog->IF & tmp; } /***************************************************************************//** * @brief * Set one or more pending WDOG interrupts from SW. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @param[in] flags * WDOG interrupt sources to set to pending. Use a set of interrupt flags * (WDOG_IFS_nnn). ******************************************************************************/ __STATIC_INLINE void WDOGn_IntSet(WDOG_TypeDef *wdog, uint32_t flags) { #if defined(WDOG_HAS_SET_CLEAR) wdog->IF_SET = flags; #else wdog->IFS = flags; #endif } #endif /***************************************************************************//** * @brief * Get enabled status of the watchdog. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @return * True if watchdog is enabled. ******************************************************************************/ __STATIC_INLINE bool WDOGn_IsEnabled(WDOG_TypeDef *wdog) { #if defined(_WDOG_EN_MASK) return (wdog->EN & _WDOG_EN_EN_MASK) == WDOG_EN_EN; #else return (wdog->CTRL & _WDOG_CTRL_EN_MASK) == WDOG_CTRL_EN; #endif } /***************************************************************************//** * @brief * Get locked status of the watchdog. * * @param[in] wdog * Pointer to WDOG peripheral register block. * * @return * True if watchdog is locked. ******************************************************************************/ __STATIC_INLINE bool WDOGn_IsLocked(WDOG_TypeDef *wdog) { #if defined(_WDOG_STATUS_MASK) return (wdog->STATUS & _WDOG_STATUS_LOCK_MASK) == WDOG_STATUS_LOCK_LOCKED; #else return (wdog->CTRL & _WDOG_CTRL_LOCK_MASK) == WDOG_CTRL_LOCK; #endif } /***************************************************************************//** * @brief * Enable/disable the watchdog timer. * * @deprecated * Deprecated function. New code should use @ref WDOGn_Enable(). * This function uses @ref DEFAULT_WDOG. * * @param[in] enable * Set to true to enable watchdog, false to disable. Watchdog cannot be * disabled if watchdog has been locked. ******************************************************************************/ __STATIC_INLINE void WDOG_Enable(bool enable) { WDOGn_Enable(DEFAULT_WDOG, enable); } /***************************************************************************//** * @brief * Feed the watchdog. * * @deprecated * Deprecated function. New code should use @ref WDOGn_Feed(). * This function uses @ref DEFAULT_WDOG. ******************************************************************************/ __STATIC_INLINE void WDOG_Feed(void) { WDOGn_Feed(DEFAULT_WDOG); } /***************************************************************************//** * @brief * Initialize watchdog (assuming the watchdog configuration has not been * locked). * * @deprecated * Deprecated function. New code should use @ref WDOGn_Init(). * This function uses @ref DEFAULT_WDOG. * * @param[in] init * Structure holding watchdog configuration. A default setting * #WDOG_INIT_DEFAULT is available for initialization. ******************************************************************************/ __STATIC_INLINE void WDOG_Init(const WDOG_Init_TypeDef *init) { WDOGn_Init(DEFAULT_WDOG, init); } /***************************************************************************//** * @brief * Lock the watchdog configuration. * * @deprecated * Deprecated function. New code should use @ref WDOGn_Lock(). * This function uses @ref DEFAULT_WDOG. ******************************************************************************/ __STATIC_INLINE void WDOG_Lock(void) { WDOGn_Lock(DEFAULT_WDOG); } /***************************************************************************//** * @brief * Get enabled status of the watchdog. * * @deprecated * Deprecated function. New code should use @ref WDOGn_IsEnabled(). * This function uses @ref DEFAULT_WDOG. * * @return * True if watchdog is enabled. ******************************************************************************/ __STATIC_INLINE bool WDOG_IsEnabled(void) { return WDOGn_IsEnabled(DEFAULT_WDOG); } /***************************************************************************//** * @brief * Get locked status of the watchdog. * * @deprecated * Deprecated function. New code should use @ref WDOGn_IsLocked(). * This function uses @ref DEFAULT_WDOG. * * @return * True if watchdog is locked. ******************************************************************************/ __STATIC_INLINE bool WDOG_IsLocked(void) { return WDOGn_IsLocked(DEFAULT_WDOG); } /** @} (end addtogroup wdog) */ #ifdef __cplusplus } #endif #endif /* defined(WDOG_COUNT) && (WDOG_COUNT > 0) */ #endif /* EM_WDOG_H */