From a84c7a0ed931667cda44a8e27888f066e085d5eb Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 24 May 2024 15:57:01 +1000 Subject: [PATCH] rp2/modmachine: Selectively leave the USB clocks enabled in lightsleep. Without this change going to lightsleep stops the USB peripheral clock, and can lead to either the device going into a weird state or the host deciding to issue a bus reset. This change only keeps the USB peripheral clocks enabled if the USB device is currently active and a host has configured the device. This means the USB device continues to respond to host transfers and (presumably) will even complete pending endpoint transfers. All other requests are NAKed while still asleep, but the interaction with the host seems to resume correctly on wake Otherwise, if USB is not active or configured by a host, USB clocks are disabled, the same as before. With the change, one can issue a `machine.lightsleep(...)` with USB CDC connected and the USB CDC remains connected during the sleep and resumes when the lightsleep finishes. Tested on a RPi Pico, the power consumption is: - During normal idle at the REPL, about 15.3mA. - During lightsleep, prior to this change, about 1.35mA. - During lightsleep, with this change and USB CDC connected, about 3.7mA. If power consumption should be as low as possible when USB is connected, one can use `machine.USBDevice` to disable the USB before entering lightsleep. As discussed at https://github.com/orgs/micropython/discussions/14401 This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- ports/rp2/modmachine.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index e6a8542d77307..4eebb3d16c64e 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -28,6 +28,7 @@ // extmod/modmachine.c via MICROPY_PY_MACHINE_INCLUDEFILE. #include "py/mphal.h" +#include "mp_usbd.h" #include "modmachine.h" #include "uart.h" #include "hardware/clocks.h" @@ -134,8 +135,17 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) { return; } #endif - // Disable USB and ADC clocks. - clock_stop(clk_usb); + + #if MICROPY_HW_ENABLE_USBDEV + // Only disable the USB clock if a USB host has not configured the device + bool disable_usb = !tud_mounted(); + #else + bool disable_usb = true; + #endif + if (disable_usb) { + clock_stop(clk_usb); + } + clock_stop(clk_adc); // CLK_REF = XOSC @@ -152,7 +162,9 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) { // Disable PLLs. pll_deinit(pll_sys); - pll_deinit(pll_usb); + if (disable_usb) { + pll_deinit(pll_usb); + } // Disable ROSC. rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB; @@ -181,6 +193,12 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) { // TODO: Use RTC alarm to wake. clocks_hw->sleep_en1 = 0; } + + if (!disable_usb) { + clocks_hw->sleep_en0 |= CLOCKS_SLEEP_EN0_CLK_SYS_PLL_USB_BITS; + clocks_hw->sleep_en1 |= CLOCKS_SLEEP_EN1_CLK_USB_USBCTRL_BITS; + } + scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS; __wfi(); scb_hw->scr &= ~M0PLUS_SCR_SLEEPDEEP_BITS; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy