1717//! - The WDOG peripheral supports discrete timeouts. This port chooses the closest period
1818//! that is less than or equal to the requested value. Valid selections for
1919//! MEMFAULT_WATCHDOG_SW_TIMEOUT_SECS range from 1s - 128s.
20-
2120#include "memfault/ports/watchdog.h"
2221
22+ // non-module includes below
23+ #include "em_cmu.h"
24+ #include "em_wdog.h"
2325#include "memfault/config.h"
2426#include "memfault/core/debug_log.h"
2527
26- #include "em_wdog.h"
27- #include "em_cmu.h"
28-
2928#if defined(WDOG0 )
30- #define MEMFAULT_WDOG WDOG0
31- #define MEMFAULT_WDOG_IRQn WDOG0_IRQn
29+ #define MEMFAULT_WDOG WDOG0
30+ #define MEMFAULT_WDOG_IRQn WDOG0_IRQn
3231
33- #ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
34- # error "Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG0_IRQHandler"
35- #endif
32+ #ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
33+ #error \
34+ "Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG0_IRQHandler"
35+ #endif
3636
3737#elif defined(WDOG )
38- #define MEMFAULT_WDOG WDOG
39- #define MEMFAULT_WDOG_IRQn WDOG_IRQn
38+ #define MEMFAULT_WDOG WDOG
39+ #define MEMFAULT_WDOG_IRQn WDOG_IRQn
4040
41- #ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
42- # error "Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG_IRQHandler"
43- #endif
41+ #ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
42+ #error \
43+ "Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG_IRQHandler"
44+ #endif
4445
4546#else
46- # error "Could not find an available WDOG to use"
47+ # error "Could not find an available WDOG to use"
4748#endif
4849
4950#define MEMFAULT_EM_WDOG_FREQ_HZ 1000
5556
5657#define MEMFAULT_EM_WDOG_MAX_TIMEOUT_MS (MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS(wdogPeriod_256k))
5758
59+ // clang-format off
5860static void prv_build_configuration (WDOG_Init_TypeDef * cfg , uint32_t persel ) {
5961 * cfg = (WDOG_Init_TypeDef ) {
6062 .enable = true,
@@ -70,8 +72,6 @@ static void prv_build_configuration(WDOG_Init_TypeDef *cfg, uint32_t persel) {
7072#if defined(_WDOG_CTRL_CLKSEL_MASK )
7173 // use internal 1kHz clock for largest range
7274 .clkSel = wdogClkSelULFRCO ,
73- #else
74- #error "Port doesn't support WDOG Variant - cannot configure clock"
7575#endif
7676 .perSel = persel ,
7777
@@ -91,41 +91,44 @@ static void prv_build_configuration(WDOG_Init_TypeDef *cfg, uint32_t persel) {
9191#endif
9292 };
9393}
94+ // clang-format on
9495
9596static int prv_configure_watchdog_with_timeout (uint32_t timeout_ms ) {
96-
9797 // NB: An interrupt can be configured to fire at 25%, 50%, or 75% of the watchdog cycle
9898 // configured. We'll use this interrupt as our "software watchdog" and configure it to be at
9999 // the 50% interval
100- const size_t sw_wdog_max_ms = MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS (MEMFAULT_EM_WDOG_MAX_TIMEOUT_MS );
100+ const size_t sw_wdog_max_ms =
101+ MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS (MEMFAULT_EM_WDOG_MAX_TIMEOUT_MS );
101102 if (timeout_ms > sw_wdog_max_ms ) {
102- MEMFAULT_LOG_ERROR ("Requested wdog timeout (%d) exceeds max supported (%d)" ,
103- (int )timeout_ms , ( int ) sw_wdog_max_ms );
103+ MEMFAULT_LOG_ERROR ("Requested wdog timeout (%d) exceeds max supported (%d)" , ( int ) timeout_ms ,
104+ (int )sw_wdog_max_ms );
104105 return -1 ;
105106 }
106107
107108 uint32_t persel = wdogPeriod_9 ;
108109 while (persel <= wdogPeriod_256k ) {
109110 const uint32_t warning_timeout_ms =
110- MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS (MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS (persel ));
111+ MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS (MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS (persel ));
111112 if (warning_timeout_ms > timeout_ms ) {
112113 break ;
113114 }
114115 persel ++ ;
115116 }
116117
117118 // choose the closest timeout without going over the desired max
118- persel = (persel == 0 ) ? 0 : persel - 1 ;
119+ persel = (persel == 0 ) ? 0 : persel - 1 ;
119120
120121 const size_t actual_timeout_ms = MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS (persel );
121122 MEMFAULT_LOG_DEBUG ("Configuring SW Watchdog. SW Timeout=%dms HW Timeout=%dms" ,
122123 (int )MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS (actual_timeout_ms ),
123124 actual_timeout_ms );
124125
125126 // Low energy clock must be on to use the watchdog
126- if ((CMU -> HFBUSCLKEN0 & CMU_HFBUSCLKEN0_LE ) == 0 ) {
127- CMU -> HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_LE ;
128- }
127+ #if defined(_SILICON_LABS_32B_SERIES_2 )
128+ CMU_ClockEnable (cmuClock_WDOG0 , true);
129+ #else // !defined(_SILICON_LABS_32B_SERIES_2)
130+ CMU_ClockEnable (cmuClock_HFLE , true);
131+ #endif // defined(_SILICON_LABS_32B_SERIES_2)
129132
130133 if (WDOGn_IsLocked (MEMFAULT_WDOG )) {
131134 MEMFAULT_LOG_ERROR ("Watchdog is locked and cannot be reconfigured" );
@@ -137,13 +140,18 @@ static int prv_configure_watchdog_with_timeout(uint32_t timeout_ms) {
137140 NVIC_DisableIRQ (MEMFAULT_WDOG_IRQn );
138141 NVIC_ClearPendingIRQ (MEMFAULT_WDOG_IRQn );
139142
143+ // Series 2 chips select the watchdog source via the CMU
144+ #if defined(_SILICON_LABS_32B_SERIES_2 )
145+ CMU_ClockSelectSet (cmuClock_WDOG0 , cmuSelect_ULFRCO );
146+ #endif // defined(_SILICON_LABS_32B_SERIES_2)
147+
140148 WDOG_Init_TypeDef cfg ;
141149 prv_build_configuration (& cfg , persel );
142150 WDOGn_Init (MEMFAULT_WDOG , & cfg );
143151
144152 // enable the warning interrupt. This will be used to capture a coredump rather than just letting
145153 // the hardware watchdog immediately reboot the system
146- const uint32_t warn_int_mask = 0x2 ; // "WARN Interrupt Enable"
154+ const uint32_t warn_int_mask = 0x2 ; // "WARN Interrupt Enable"
147155 WDOGn_IntClear (MEMFAULT_WDOG , warn_int_mask );
148156 WDOGn_IntEnable (MEMFAULT_WDOG , warn_int_mask );
149157
@@ -154,7 +162,6 @@ static int prv_configure_watchdog_with_timeout(uint32_t timeout_ms) {
154162
155163 // finally, with everything setup, start the watchdog!
156164 WDOGn_Enable (MEMFAULT_WDOG , true);
157- WDOGn_SyncWait (MEMFAULT_WDOG );
158165 return 0 ;
159166}
160167
@@ -182,6 +189,6 @@ int memfault_software_watchdog_feed(void) {
182189 // Enteriung EM2 or EM3 power states while this is in progress will
183190 // cause the operation to be aborted. WDOGn_SyncWait() can be used to
184191 // block until the operation is complete!
185- WDOG_Feed ( );
192+ WDOGn_Feed ( MEMFAULT_WDOG );
186193 return 0 ;
187194}
0 commit comments