diff options
Diffstat (limited to 'src/machine/machine_rp2_watchdog.go')
-rw-r--r-- | src/machine/machine_rp2_watchdog.go | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/machine/machine_rp2_watchdog.go b/src/machine/machine_rp2_watchdog.go new file mode 100644 index 000000000..f776c5ca4 --- /dev/null +++ b/src/machine/machine_rp2_watchdog.go @@ -0,0 +1,62 @@ +//go:build rp2040 || rp2350 + +package machine + +import ( + "device/rp" +) + +// Watchdog provides access to the hardware watchdog available +// in the RP2040. +var Watchdog = &watchdogImpl{} + +const ( + // WatchdogMaxTimeout in milliseconds (approx 8.3s). + // + // Nominal 1us per watchdog tick, 24-bit counter, + // but due to errata two ticks consumed per 1us. + // See: Errata RP2040-E1 + WatchdogMaxTimeout = (rp.WATCHDOG_LOAD_LOAD_Msk / 1000) / 2 +) + +type watchdogImpl struct { + // The value to reset the counter to on each Update + loadValue uint32 +} + +// Configure the watchdog. +// +// This method should not be called after the watchdog is started and on +// some platforms attempting to reconfigure after starting the watchdog +// is explicitly forbidden / will not work. +func (wd *watchdogImpl) Configure(config WatchdogConfig) error { + // x2 due to errata RP2040-E1 + wd.loadValue = config.TimeoutMillis * 1000 * 2 + if wd.loadValue > rp.WATCHDOG_LOAD_LOAD_Msk { + wd.loadValue = rp.WATCHDOG_LOAD_LOAD_Msk + } + + rp.WATCHDOG.CTRL.ClearBits(rp.WATCHDOG_CTRL_ENABLE) + + // Reset everything apart from ROSC and XOSC + rp.PSM.WDSEL.Set(0x0001ffff &^ (rp.PSM_WDSEL_ROSC | rp.PSM_WDSEL_XOSC)) + + // Pause watchdog during debug + rp.WATCHDOG.CTRL.SetBits(rp.WATCHDOG_CTRL_PAUSE_DBG0 | rp.WATCHDOG_CTRL_PAUSE_DBG1 | rp.WATCHDOG_CTRL_PAUSE_JTAG) + + // Load initial counter + rp.WATCHDOG.LOAD.Set(wd.loadValue) + + return nil +} + +// Starts the watchdog. +func (wd *watchdogImpl) Start() error { + rp.WATCHDOG.CTRL.SetBits(rp.WATCHDOG_CTRL_ENABLE) + return nil +} + +// Update the watchdog, indicating that the app is healthy. +func (wd *watchdogImpl) Update() { + rp.WATCHDOG.LOAD.Set(wd.loadValue) +} |