FastLED 3.10.8
Loading...
Searching...
No Matches
watchdog.h
Go to the documentation of this file.
1#pragma once
2
32
33#include "fl/stl/stdint.h"
34#include "fl/stl/noexcept.h"
35#include "fl/stl/compiler_control.h" // FL_NO_RETURN
36#include "fl/stl/span.h"
37#include "fl/stl/function.h"
38#include "fl/stl/string_view.h" // for resetCauseName() return type
39
40namespace fl {
41
54
62 switch (c) {
63 case ResetCause::POWER_ON: return fl::string_view("POWER_ON");
64 case ResetCause::BROWNOUT: return fl::string_view("BROWNOUT");
65 case ResetCause::EXTERNAL_PIN: return fl::string_view("EXTERNAL_PIN");
66 case ResetCause::WATCHDOG: return fl::string_view("WATCHDOG");
67 case ResetCause::SOFTWARE: return fl::string_view("SOFTWARE");
68 case ResetCause::LOCKUP: return fl::string_view("LOCKUP");
69 case ResetCause::DEBUGGER: return fl::string_view("DEBUGGER");
70 case ResetCause::PANIC: return fl::string_view("PANIC");
72 default: return fl::string_view("UNKNOWN");
73 }
74}
75
82struct ResetInfo {
85 fl::u32 rawRegister;
86
89
94
103 fl::size describe(fl::span<char> out, bool verbose = false) const FL_NO_EXCEPT;
104};
105
107using WatchdogTimeoutCallback = void(*)(void* user_data);
108
111 bool valid;
112 fl::u32 pc;
113 fl::u32 lr;
114 fl::u32 psr;
117 const char* fault_type;
118};
119
123class Watchdog {
124public:
125 // Singleton accessor — DECLARATION ONLY. The function-local `static
126 // Watchdog` must live in a `.cpp.hpp` / `.impl.hpp` TU (one definition,
127 // one guard variable) so the Teensy 3.x `__cxa_guard` ABI conflict does
128 // not pull a guarded singleton path into every TU that includes
129 // FastLED.h. See `agents/docs/cpp-standards.md` → "Header rules:
130 // function-local statics with non-trivial constructors are forbidden in
131 // `src/**/*.h`."
133
134 // ========== Tier 0 — universal ==========
135
136 void begin(fl::u32 timeout_ms) FL_NO_EXCEPT;
139
142
148
149 fl::u8 persistRead(fl::size idx) const FL_NO_EXCEPT;
150 void persistWrite(fl::size idx, fl::u8 v) FL_NO_EXCEPT;
151
157
181
184 void setBootloaderEscapeThreshold(fl::u16 threshold) FL_NO_EXCEPT;
185
189
197
201 fl::u32 bootGuardCount() const FL_NO_EXCEPT;
202
210
212
213 // ========== Tier 1 — most platforms ==========
214
215 bool onTimeout(WatchdogTimeoutCallback cb, void* user_data = nullptr) FL_NO_EXCEPT;
218 bool writeCrashLog(fl::span<const fl::u8> payload) FL_NO_EXCEPT;
219 fl::size readCrashLog(fl::span<fl::u8> out) const FL_NO_EXCEPT;
221
222 // ========== Tier 2 — advanced platforms ==========
223
224 bool setWindow(fl::u32 window_min_ms, fl::u32 window_max_ms) FL_NO_EXCEPT;
228
229private:
231 ~Watchdog() FL_NO_EXCEPT = default;
233 Watchdog& operator=(const Watchdog&) FL_NO_EXCEPT = delete;
234
236 fl::u16 mBootloaderEscapeThreshold = 0; // 0 = escape disabled
237};
238
239namespace platforms {
247} // namespace platforms
248
270public:
273
276 explicit ScopedWatchdog(fl::u32 timeout_ms) FL_NO_EXCEPT;
277
281
285 static int activeScopeCount() FL_NO_EXCEPT;
286
288 ScopedWatchdog& operator=(const ScopedWatchdog&) FL_NO_EXCEPT = delete;
289};
290
291} // namespace fl
292
293// ============================================================================
294// FL_WATCHDOG_AUTO(...) — the canonical zero-setup loop()-top guard.
295//
296// Variadic so the same macro covers both the no-argument default (15 000 ms)
297// and the explicit-timeout form:
298//
299// void loop() {
300// FL_WATCHDOG_AUTO(); // 15 000 ms default
301// doWork();
302// }
303//
304// void loop() {
305// FL_WATCHDOG_AUTO(5000); // 5-second timeout
306// doWork();
307// }
308//
309// "AUTO" because this macro does more than just feed: it lazily arms the WDT
310// on first call, prints the prior-boot reset/crash diagnostic, pauses 3 s on
311// a crash so the developer can read the message, and feeds the WDT on both
312// construction AND destruction. Single source-line use; the macro stamps the
313// local variable name from `__LINE__` so two `FL_WATCHDOG_AUTO()` on the same
314// line are a compile error. Two on different lines but simultaneously alive
315// (nested scopes) trigger a one-shot runtime warning — see ScopedWatchdog.
316//
317// Future variants stay grouped under the `FL_WATCHDOG_*` prefix:
318// FL_WATCHDOG_AUTO_QUIET / FL_WATCHDOG_AUTO_VERBOSE — log-level variants
319// FL_WATCHDOG_MANUAL — non-RAII setup helper
320// ============================================================================
321
322#define FL_WATCHDOG__CONCAT_INNER(a, b) a##b
323#define FL_WATCHDOG__CONCAT(a, b) FL_WATCHDOG__CONCAT_INNER(a, b)
324#define FL_WATCHDOG_AUTO(...) \
325 ::fl::ScopedWatchdog FL_WATCHDOG__CONCAT(_fl_wdt_, __LINE__) { __VA_ARGS__ }
326
327// ============================================================================
328// FL_WATCHDOG_* capability macros — defined by the per-platform impl.
329// The noop fallback defines NONE of the boolean flags and defaults numerics to 0.
330// User code may #ifdef on the boolean flags or static_assert on the numerics.
331// ============================================================================
332//
333// #define FL_WATCHDOG_HAS_HARDWARE // 1 wherever a real or emulated WDT runs
334// #define FL_WATCHDOG_PERSIST_BYTES N // small persistent buffer size, >= 8
335// #define FL_WATCHDOG_HAS_PRE_TIMEOUT_IRQ // pre-reset callback honored at HW level
336// #define FL_WATCHDOG_HAS_WINDOW_MODE // setWindow() honored
337// #define FL_WATCHDOG_HAS_CRASH_REPORT // hasCrashReport()/readCrashReport() honored
338// #define FL_WATCHDOG_HAS_BOOTLOADER_REBOOT // rebootIntoBootloader() honored
339// #define FL_WATCHDOG_HAS_BOOT_GUARD // FL_WATCHDOG_BOOT_GUARD() early hook (fl/wdt/boot_guard.h)
340// #define FL_WATCHDOG_HAS_BOOT_GUARD_STORAGE // bootGuardCount()/markBootHealthy() persist
341// #define FL_WATCHDOG_MAX_TIMEOUT_MS N // upper bound, in ms
342//
343// The Tier 0 surface is always callable; Tier 1/2 methods return false on
344// platforms whose impl does not honor them, so user code that checks the
345// return value works portably.
ScopedWatchdog() FL_NO_EXCEPT
Default construct with the library default timeout (15 000 ms).
Definition watchdog.h:272
RAII watchdog guard for the canonical loop()-top use case.
Definition watchdog.h:269
fl::u16 mSafeModeThreshold
Definition watchdog.h:235
void disable() FL_NO_EXCEPT
bool writeCrashLog(fl::span< const fl::u8 > payload) FL_NO_EXCEPT
static Watchdog & instance() FL_NO_EXCEPT
bool shouldEscapeToBootloader() const FL_NO_EXCEPT
True when the escape is enabled and the board has hit the consecutive-watchdog-reset threshold.
fl::u16 bootloaderEscapeThreshold() const FL_NO_EXCEPT
Boot-loop escape hatch: drop to the bootloader instead of looping forever, so an unattended host can ...
fl::size readCrashLog(fl::span< fl::u8 > out) const FL_NO_EXCEPT
fl::u32 bootGuardCount() const FL_NO_EXCEPT
Early-boot loop guard counter (see fl/wdt/boot_guard.h): consecutive boots since the last markBootHea...
void setSafeModeThreshold(fl::u16 threshold) FL_NO_EXCEPT
void begin(fl::u32 timeout_ms) FL_NO_EXCEPT
bool isInSafeMode() const FL_NO_EXCEPT
fl::u16 safeModeThreshold() const FL_NO_EXCEPT
bool lastResetWasWatchdog() const FL_NO_EXCEPT
WatchdogCrashReport readCrashReport() const FL_NO_EXCEPT
fl::u8 persistRead(fl::size idx) const FL_NO_EXCEPT
void persistWrite(fl::size idx, fl::u8 v) FL_NO_EXCEPT
void markBootHealthy() FL_NO_EXCEPT
Tell the early-boot guard this boot is healthy, zeroing its counter.
FL_NO_RETURN void reboot() FL_NO_EXCEPT
void feed() FL_NO_EXCEPT
bool setPauseOnDebug(bool pause) FL_NO_EXCEPT
void setBootloaderEscapeThreshold(fl::u16 threshold) FL_NO_EXCEPT
Set the consecutive-watchdog-reset count that triggers the escape.
fl::u16 mBootloaderEscapeThreshold
Definition watchdog.h:236
ResetInfo lastResetInfo() const FL_NO_EXCEPT
Detailed reset information including platform raw register + subcause id.
fl::u16 consecutiveCrashCount() const FL_NO_EXCEPT
Watchdog() FL_NO_EXCEPT=default
void markCleanShutdown() FL_NO_EXCEPT
ResetCause lastResetCause() const FL_NO_EXCEPT
bool onTimeout(WatchdogTimeoutCallback cb, void *user_data=nullptr) FL_NO_EXCEPT
bool hasCrashReport() const FL_NO_EXCEPT
bool escapeToBootloaderIfLooping() FL_NO_EXCEPT
Reboot into the bootloader if this looks like a boot loop.
bool rebootIntoBootloader() FL_NO_EXCEPT
void clearCrashReport() FL_NO_EXCEPT
bool setWindow(fl::u32 window_min_ms, fl::u32 window_max_ms) FL_NO_EXCEPT
#define FL_NO_RETURN
void watchdogBootGuardReleaseEarlyTimer() FL_NO_EXCEPT
Disable the boot guard's early watchdog timer if it is still running and the sketch never armed the w...
void watchdogBootGuardWrite(fl::u32 boots) FL_NO_EXCEPT
fl::u32 watchdogBootGuardRead() FL_NO_EXCEPT
Boot-guard counter storage, supplied by the platform watchdog impl (or the no-op).
unsigned char u8
Definition stdint.h:131
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
ResetCause
Cause of the previous boot. Call once early in setup().
Definition watchdog.h:43
void(*)(void *user_data) WatchdogTimeoutCallback
ISR-safe C function pointer callback for onTimeout().
Definition watchdog.h:107
@ UNKNOWN
Unknown or unspecified error.
Definition expected.h:49
fl::string_view resetCauseName(ResetCause c) FL_NO_EXCEPT
Return a static-lifetime name for c — zero-cost, no allocation.
Definition watchdog.h:61
Base definition for an LED controller.
Definition crgb.hpp:179
const char * fault_type
Definition watchdog.h:117
Decoded crash report (Tier 2).
Definition watchdog.h:110
ResetCause cause
Normalized cross-platform enum.
Definition watchdog.h:83
fl::u32 rawRegister
Raw value of the platform's reset-cause register.
Definition watchdog.h:85
fl::size describe(fl::span< char > out, bool verbose=false) const FL_NO_EXCEPT
Write a single-line human-readable description into the caller's buffer.
fl::string_view subcauseName() const FL_NO_EXCEPT
Platform-specific subcause name (zero-cost, static string_view).
fl::string_view causeName() const FL_NO_EXCEPT
Cause name (zero-cost, static string_view).
Definition watchdog.h:88
fl::u8 subcauseId
Platform-specific subcause id (0 = none)
Definition watchdog.h:84
Detailed reset information bundling the normalized cause with a platform-specific subcause id and the...
Definition watchdog.h:82