From cde28db20e58395b7606ea20c4b9eb4bd9e58009 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Mon, 12 Jan 2026 01:33:04 +0100 Subject: [PATCH] rp2: perform lazy block init to save power This changes the machine init process for the rp2040/rp2350 to only unreset aka make available the minimum needed peripherals in order to try to save power use. I2C, SPI, and other devices unreset themselves as needed as used. Signed-off-by: deadprogram --- src/machine/machine_rp2.go | 7 +------ src/machine/machine_rp2_2040.go | 9 ++------- src/machine/machine_rp2_2350.go | 8 ++------ src/machine/machine_rp2_adc.go | 8 ++++---- src/machine/machine_rp2_i2c.go | 7 ++----- src/machine/machine_rp2_spi.go | 7 ++----- src/machine/machine_rp2_uart.go | 6 ++---- 7 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/machine/machine_rp2.go b/src/machine/machine_rp2.go index edf49c53a..4fca43ae9 100644 --- a/src/machine/machine_rp2.go +++ b/src/machine/machine_rp2.go @@ -49,15 +49,10 @@ func machineInit() { bits := ^uint32(initDontReset) resetBlock(bits) - // Remove reset from peripherals which are clocked only by clkSys and - // clkRef. Other peripherals stay in reset until we've configured clocks. - bits = ^uint32(initUnreset) - unresetBlockWait(bits) - clocks.init() // Peripheral clocks should now all be running - unresetBlockWait(RESETS_RESET_Msk) + unresetBlockWait(initUnreset) // DBGPAUSE pauses the timer when a debugger is connected. This prevents // sleep functions from ever returning, so disable it. diff --git a/src/machine/machine_rp2_2040.go b/src/machine/machine_rp2_2040.go index 78336a3b7..46f9b5bd5 100644 --- a/src/machine/machine_rp2_2040.go +++ b/src/machine/machine_rp2_2040.go @@ -15,13 +15,8 @@ const ( _NUMIRQ = 32 rp2350ExtraReg = 0 RESETS_RESET_Msk = 0x01ffffff - initUnreset = rp.RESETS_RESET_ADC | - rp.RESETS_RESET_RTC | - rp.RESETS_RESET_SPI0 | - rp.RESETS_RESET_SPI1 | - rp.RESETS_RESET_UART0 | - rp.RESETS_RESET_UART1 | - rp.RESETS_RESET_USBCTRL + initUnreset = rp.RESETS_RESET_IO_BANK0 | + rp.RESETS_RESET_TIMER initDontReset = rp.RESETS_RESET_IO_QSPI | rp.RESETS_RESET_PADS_QSPI | rp.RESETS_RESET_PLL_USB | diff --git a/src/machine/machine_rp2_2350.go b/src/machine/machine_rp2_2350.go index efb39a64b..ef3f6aa3e 100644 --- a/src/machine/machine_rp2_2350.go +++ b/src/machine/machine_rp2_2350.go @@ -16,12 +16,8 @@ const ( _NUMIRQ = 51 notimpl = "rp2350: not implemented" RESETS_RESET_Msk = 0x1fffffff - initUnreset = rp.RESETS_RESET_ADC | - rp.RESETS_RESET_SPI0 | - rp.RESETS_RESET_SPI1 | - rp.RESETS_RESET_UART0 | - rp.RESETS_RESET_UART1 | - rp.RESETS_RESET_USBCTRL + initUnreset = rp.RESETS_RESET_IO_BANK0 | + rp.RESETS_RESET_TIMER0 initDontReset = rp.RESETS_RESET_USBCTRL | rp.RESETS_RESET_SYSCFG | rp.RESETS_RESET_PLL_USB | diff --git a/src/machine/machine_rp2_adc.go b/src/machine/machine_rp2_adc.go index e0d6a459a..71cf5aeec 100644 --- a/src/machine/machine_rp2_adc.go +++ b/src/machine/machine_rp2_adc.go @@ -19,10 +19,10 @@ var adcAref uint32 // InitADC resets the ADC peripheral. func InitADC() { - rp.RESETS.RESET.SetBits(rp.RESETS_RESET_ADC) - rp.RESETS.RESET.ClearBits(rp.RESETS_RESET_ADC) - for !rp.RESETS.RESET_DONE.HasBits(rp.RESETS_RESET_ADC) { - } + // reset ADC controller + resetBlock(rp.RESETS_RESET_ADC) + unresetBlockWait(rp.RESETS_RESET_ADC) + // enable ADC rp.ADC.CS.Set(rp.ADC_CS_EN) adcAref = 3300 diff --git a/src/machine/machine_rp2_i2c.go b/src/machine/machine_rp2_i2c.go index 54a5e5357..50e2e8a27 100644 --- a/src/machine/machine_rp2_i2c.go +++ b/src/machine/machine_rp2_i2c.go @@ -259,10 +259,7 @@ func (i2c *I2C) init(config I2CConfig) error { //go:inline func (i2c *I2C) reset() { resetVal := i2c.deinit() - rp.RESETS.RESET.ClearBits(resetVal) - // Wait until reset is done. - for !rp.RESETS.RESET_DONE.HasBits(resetVal) { - } + unresetBlockWait(resetVal) } // deinit sets reset bit for I2C. Must call reset to reenable I2C after deinit. @@ -276,7 +273,7 @@ func (i2c *I2C) deinit() (resetVal uint32) { resetVal = rp.RESETS_RESET_I2C1 } // Perform I2C reset. - rp.RESETS.RESET.SetBits(resetVal) + resetBlock(resetVal) return resetVal } diff --git a/src/machine/machine_rp2_spi.go b/src/machine/machine_rp2_spi.go index 75e4f86b7..f3fb256f6 100644 --- a/src/machine/machine_rp2_spi.go +++ b/src/machine/machine_rp2_spi.go @@ -212,10 +212,7 @@ func (spi *SPI) setFormat(mode uint8) { //go:inline func (spi *SPI) reset() { resetVal := spi.deinit() - rp.RESETS.RESET.ClearBits(resetVal) - // Wait until reset is done. - for !rp.RESETS.RESET_DONE.HasBits(resetVal) { - } + unresetBlockWait(resetVal) } //go:inline @@ -227,7 +224,7 @@ func (spi *SPI) deinit() (resetVal uint32) { resetVal = rp.RESETS_RESET_SPI1 } // Perform SPI reset. - rp.RESETS.RESET.SetBits(resetVal) + resetBlock(resetVal) return resetVal } diff --git a/src/machine/machine_rp2_uart.go b/src/machine/machine_rp2_uart.go index 872418a76..5961d3a86 100644 --- a/src/machine/machine_rp2_uart.go +++ b/src/machine/machine_rp2_uart.go @@ -148,10 +148,8 @@ func initUART(uart *UART) { } // reset UART - rp.RESETS.RESET.SetBits(resetVal) - rp.RESETS.RESET.ClearBits(resetVal) - for !rp.RESETS.RESET_DONE.HasBits(resetVal) { - } + resetBlock(resetVal) + unresetBlockWait(resetVal) } // handleInterrupt should be called from the appropriate interrupt handler for