aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/machine/machine_stm32_iwdg.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/machine/machine_stm32_iwdg.go')
-rw-r--r--src/machine/machine_stm32_iwdg.go66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/machine/machine_stm32_iwdg.go b/src/machine/machine_stm32_iwdg.go
new file mode 100644
index 000000000..1139d5461
--- /dev/null
+++ b/src/machine/machine_stm32_iwdg.go
@@ -0,0 +1,66 @@
+//go:build stm32
+
+package machine
+
+import "device/stm32"
+
+var (
+ Watchdog = &watchdogImpl{}
+)
+
+const (
+ // WatchdogMaxTimeout in milliseconds (32.768s)
+ //
+ // Timeout is based on 12-bit counter with /256 divider on
+ // 32.768kHz clock. See 21.3.3 of RM0090 for table.
+ WatchdogMaxTimeout = ((0xfff + 1) * 256 * 1024) / 32768
+)
+
+const (
+ // Enable access to PR, RLR and WINR registers (0x5555)
+ iwdgKeyEnable = 0x5555
+ // Reset the watchdog value (0xAAAA)
+ iwdgKeyReset = 0xaaaa
+ // Start the watchdog (0xCCCC)
+ iwdgKeyStart = 0xcccc
+ // Divide by 256
+ iwdgDiv256 = 6
+)
+
+type watchdogImpl struct {
+}
+
+// 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 {
+
+ // Enable configuration of IWDG
+ stm32.IWDG.KR.Set(iwdgKeyEnable)
+
+ // Unconditionally divide by /256 since we don't really need accuracy
+ // less than 8ms
+ stm32.IWDG.PR.Set(iwdgDiv256)
+
+ timeout := config.TimeoutMillis
+ if timeout > WatchdogMaxTimeout {
+ timeout = WatchdogMaxTimeout
+ }
+
+ // Set reload value based on /256 divider
+ stm32.IWDG.RLR.Set(((config.TimeoutMillis*32768 + (256 * 1024) - 1) / (256 * 1024)) - 1)
+ return nil
+}
+
+// Starts the watchdog.
+func (wd *watchdogImpl) Start() error {
+ stm32.IWDG.KR.Set(iwdgKeyStart)
+ return nil
+}
+
+// Update the watchdog, indicating that `source` is healthy.
+func (wd *watchdogImpl) Update() {
+ stm32.IWDG.KR.Set(iwdgKeyReset)
+}