github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_rp2040_watchdog.go (about)

     1  //go:build rp2040
     2  
     3  package machine
     4  
     5  import (
     6  	"device/rp"
     7  )
     8  
     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
    25  }
    26  
    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  }
    63  
    64  // startTick starts the watchdog tick.
    65  // cycles needs to be a divider that when applied to the xosc input,
    66  // produces a 1MHz clock. So if the xosc frequency is 12MHz,
    67  // this will need to be 12.
    68  func (wd *watchdogImpl) startTick(cycles uint32) {
    69  	rp.WATCHDOG.TICK.Set(cycles | rp.WATCHDOG_TICK_ENABLE)
    70  }