@@ -4,24 +4,67 @@ package machine
4
4
5
5
import (
6
6
"device/rp"
7
- "runtime/volatile"
8
- "unsafe"
9
7
)
10
8
11
- type watchdogType struct {
12
- ctrl volatile.Register32
13
- load volatile.Register32
14
- reason volatile.Register32
15
- scratch [8 ]volatile.Register32
16
- tick volatile.Register32
9
+ // Watchdog provides access to the hardware watchdog available
10
+ // in the RP2040.
11
+ var Watchdog = & watchdogImpl {}
12
+
13
+ const (
14
+ // WatchdogMaxTimeout in milliseconds (approx 8.3s).
15
+ //
16
+ // Nominal 1us per watchdog tick, 24-bit counter,
17
+ // but due to errata two ticks consumed per 1us.
18
+ // See: Errata RP2040-E1
19
+ WatchdogMaxTimeout = (rp .WATCHDOG_LOAD_LOAD_Msk / 1000 ) / 2
20
+ )
21
+
22
+ type watchdogImpl struct {
23
+ // The value to reset the counter to on each Update
24
+ loadValue uint32
17
25
}
18
26
19
- var watchdog = (* watchdogType )(unsafe .Pointer (rp .WATCHDOG ))
27
+ // Configure the watchdog.
28
+ //
29
+ // This method should not be called after the watchdog is started and on
30
+ // some platforms attempting to reconfigure after starting the watchdog
31
+ // is explicitly forbidden / will not work.
32
+ func (wd * watchdogImpl ) Configure (config WatchdogConfig ) error {
33
+ // x2 due to errata RP2040-E1
34
+ wd .loadValue = config .TimeoutMillis * 1000 * 2
35
+ if wd .loadValue > rp .WATCHDOG_LOAD_LOAD_Msk {
36
+ wd .loadValue = rp .WATCHDOG_LOAD_LOAD_Msk
37
+ }
38
+
39
+ rp .WATCHDOG .CTRL .ClearBits (rp .WATCHDOG_CTRL_ENABLE )
40
+
41
+ // Reset everything apart from ROSC and XOSC
42
+ rp .PSM .WDSEL .Set (0x0001ffff &^ (rp .PSM_WDSEL_ROSC | rp .PSM_WDSEL_XOSC ))
43
+
44
+ // Pause watchdog during debug
45
+ rp .WATCHDOG .CTRL .SetBits (rp .WATCHDOG_CTRL_PAUSE_DBG0 | rp .WATCHDOG_CTRL_PAUSE_DBG1 | rp .WATCHDOG_CTRL_PAUSE_JTAG )
46
+
47
+ // Load initial counter
48
+ rp .WATCHDOG .LOAD .Set (wd .loadValue )
49
+
50
+ return nil
51
+ }
52
+
53
+ // Starts the watchdog.
54
+ func (wd * watchdogImpl ) Start () error {
55
+ rp .WATCHDOG .CTRL .SetBits (rp .WATCHDOG_CTRL_ENABLE )
56
+ return nil
57
+ }
58
+
59
+ // Update the watchdog, indicating that the app is healthy.
60
+ func (wd * watchdogImpl ) Update () {
61
+ rp .WATCHDOG .LOAD .Set (wd .loadValue )
62
+ }
20
63
21
64
// startTick starts the watchdog tick.
22
65
// cycles needs to be a divider that when applied to the xosc input,
23
66
// produces a 1MHz clock. So if the xosc frequency is 12MHz,
24
67
// this will need to be 12.
25
- func (wd * watchdogType ) startTick (cycles uint32 ) {
26
- wd . tick .Set (cycles | rp .WATCHDOG_TICK_ENABLE )
68
+ func (wd * watchdogImpl ) startTick (cycles uint32 ) {
69
+ rp . WATCHDOG . TICK .Set (cycles | rp .WATCHDOG_TICK_ENABLE )
27
70
}
0 commit comments