rp2/modmachine: Implement lightsleep for RP2350.

This isn't fully working, the CPU often wakes up early.  That will be fixed
when a newer version of pico-sdk is released.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Peter Harper 2024-05-22 15:24:24 +01:00 committed by Damien George
parent c90d996c9d
commit d1423ef7a2

View File

@ -162,6 +162,9 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
}
clock_stop(clk_adc);
#if PICO_RP2350
clock_stop(clk_hstx);
#endif
// CLK_REF = XOSC
clock_configure(clk_ref, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, 0, xosc_hz, xosc_hz);
@ -170,7 +173,9 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF, 0, xosc_hz, xosc_hz);
// CLK_RTC = XOSC / 256
#if PICO_RP2040
clock_configure(clk_rtc, 0, CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC, xosc_hz, xosc_hz / 256);
#endif
// CLK_PERI = CLK_SYS
clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, xosc_hz, xosc_hz);
@ -190,38 +195,63 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
#endif
xosc_dormant();
} else {
uint32_t sleep_en0 = clocks_hw->sleep_en0;
uint32_t sleep_en1 = clocks_hw->sleep_en1;
bool timer3_enabled = irq_is_enabled(3);
clocks_hw->sleep_en0 = CLOCKS_SLEEP_EN0_CLK_RTC_RTC_BITS;
const uint32_t alarm_num = 3;
const uint32_t irq_num = TIMER_ALARM_IRQ_NUM(timer_hw, alarm_num);
if (use_timer_alarm) {
// Make sure ALARM3/IRQ3 is enabled on _this_ core
timer_hw->inte |= 1 << 3;
if (!timer3_enabled) {
irq_set_enabled(3, true);
irq_set_enabled(irq_num, true);
}
hw_set_bits(&timer_hw->inte, 1u << alarm_num);
// Use timer alarm to wake.
clocks_hw->sleep_en0 = 0x0;
#if PICO_RP2040
clocks_hw->sleep_en1 = CLOCKS_SLEEP_EN1_CLK_SYS_TIMER_BITS;
timer_hw->alarm[3] = timer_hw->timerawl + delay_ms * 1000;
#elif PICO_RP2350
clocks_hw->sleep_en1 = CLOCKS_SLEEP_EN1_CLK_REF_TICKS_BITS | CLOCKS_SLEEP_EN1_CLK_SYS_TIMER0_BITS;
#else
#error Unknown processor
#endif
timer_hw->intr = 1u << alarm_num; // clear any IRQ
timer_hw->alarm[alarm_num] = timer_hw->timerawl + delay_ms * 1000;
} else {
// TODO: Use RTC alarm to wake.
clocks_hw->sleep_en1 = 0;
clocks_hw->sleep_en0 = 0x0;
clocks_hw->sleep_en1 = 0x0;
}
if (!disable_usb) {
clocks_hw->sleep_en0 |= CLOCKS_SLEEP_EN0_CLK_SYS_PLL_USB_BITS;
#if PICO_RP2040
clocks_hw->sleep_en1 |= CLOCKS_SLEEP_EN1_CLK_USB_USBCTRL_BITS;
#elif PICO_RP2350
clocks_hw->sleep_en1 |= CLOCKS_SLEEP_EN1_CLK_SYS_USBCTRL_BITS;
#else
#error Unknown processor
#endif
}
#if PICO_ARM
// Configure SLEEPDEEP bits on Cortex-M CPUs.
#if PICO_RP2040
scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS;
#elif PICO_RP2350
scb_hw->scr |= M33_SCR_SLEEPDEEP_BITS;
#else
#error Unknown processor
#endif
#endif
// Go into low-power mode.
__wfi();
scb_hw->scr &= ~M0PLUS_SCR_SLEEPDEEP_BITS;
if (!timer3_enabled) {
irq_set_enabled(3, false);
irq_set_enabled(irq_num, false);
}
clocks_hw->sleep_en0 = sleep_en0;
clocks_hw->sleep_en1 = sleep_en1;
clocks_hw->sleep_en0 |= ~(0u);
clocks_hw->sleep_en1 |= ~(0u);
}
// Enable ROSC.