8000 rp2/modmachine: Selectively leave the USB clocks enabled in lightsleep. · micropython/micropython@a84c7a0 · GitHub
[go: up one dir, main page]

Skip to content

Commit a84c7a0

Browse files
projectgusdpgeorge
authored andcommitted
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 <angus@redyak.com.au>
1 parent 93394da commit a84c7a0

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

ports/rp2/modmachine.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// extmod/modmachine.c via MICROPY_PY_MACHINE_INCLUDEFILE.
2929

3030
#include "py/mphal.h"
31+
#include "mp_usbd.h"
3132
#include "modmachine.h"
3233
#include "uart.h"
3334
#include "hardware/clocks.h"
@@ -134,8 +135,17 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
134135
return;
135136
}
136137
#endif
137-
// Disable USB and ADC clocks.
138-
clock_stop(clk_usb);
138+
139+
#if MICROPY_HW_ENABLE_USBDEV
140+
// Only disable the USB clock if a USB host has not configured the device
141+
bool disable_usb = !tud_mounted();
142+
#else
143+
bool disable_usb = true;
144+
#endif
145+
if (disable_usb) {
146+
clock_stop(clk_usb);
147+
}
148+
139149
clock_stop(clk_adc);
140150

141151
// CLK_REF = XOSC
@@ -152,7 +162,9 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
152162

153163
// Disable PLLs.
154164
pll_deinit(pll_sys);
155-
pll_deinit(pll_usb);
165+
if (disable_usb) {
166+
pll_deinit(pll_usb);
167+
}
156168

157169
// Disable ROSC.
158170
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) {
181193
// TODO: Use RTC alarm to wake.
182194
clocks_hw->sleep_en1 = 0;
183195
}
196+
197+
if (!disable_usb) {
198+
clocks_hw->sleep_en0 |= CLOCKS_SLEEP_EN0_CLK_SYS_PLL_USB_BITS;
199+
clocks_hw->sleep_en1 |= CLOCKS_SLEEP_EN1_CLK_USB_USBCTRL_BITS;
200+
}
201+
184202
scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS;
185203
__wfi();
186204
scb_hw->scr &= ~M0PLUS_SCR_SLEEPDEEP_BITS;

0 commit comments

Comments
 (0)
0