Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@projectgus
Copy link
Contributor

@projectgus projectgus commented Nov 6, 2025

Summary

Necessary if runtime USBDevice has been active on ESP32-S3 along with the default USB-CDC REPL. Without this fix, two things happen after a soft reset:

  • The USB host sees the device disappear and not come back.
  • Inside MicroPython, the CDC driver thinks it's still connected and active but eventually the TX FIFO fills up and significantly slows down stdout (visible on boards with a separate UART REPL).

Testing

Note this PR needs to be cherry-picked onto #18332 if PSRAM is enabled.

  1. mpremote a0 run pr18332.py - where the file has the sample code from esp32/boards: Configure S2/S3 PSRAM boards to use USB in IRQ mode. #18332
  2. If using the USB-CDC interface for mpremote run then mpremote will error out as it disconnects to change USB device config.
  3. mpremote a0
  4. Use Ctrl-C and Ctrl-B to stop the sample code and drop to an interactive REPL.
  5. Type Ctrl-D to soft reset.

Without fix: USB-CDC disappears along with the keyboard device, never comes back. Connecting to the UART REPL and interacting with it will eventually slow UART TX down to a trickle (quickest way to trigger is print("a"*500).)

With fix: USB-CDC disappears and re-enumerates again as plain USB-CDC device.

Related bugs

There is still a related bug here, because calling TinyUSB tud_disconnect() on ESP32-S3 doesn't trigger any DCD_EVENT_UNPLUGGED or DCD_EVENT_BUS_RESET event. This means that the USB device driver state goes out of sync (i.e. TinyUSB thinks it's still connected).

This PR avoids this in soft reset because the host will reconfigure the USB device and the state will correct itself, but there's still a problem if Python code does something like this:

  1. mpremote a0 run pr18332.py
  2. (errors out as expected)
  3. mpremote a0
  4. Ctrl-C, Ctrl-B to get interactive REPL.
  5. import machine; u = machine.USBDevice(); u.active(0)

In this situation the USB device disappears from the host as expected, but the issue with very slow stdout will happen as the CDC device driver still thinks it's connected and configured.

I've opened a Discussion on the TinyUSB repo to try and find out the expected behaviour: hathach/tinyusb#3331

This work was funded through GitHub Sponsors.

Necessary if USBDevice has been active with USB-CDC, so the USB-CDC state
resets successfully from the host.

There is still a bug here, because calling tud_disconnect() doesn't cause
any UNPLUG or BUS_RESET events to arrive from TinyUSB - which means the USB
device state stays out of sync until we call mp_usbd_init() again...

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <[email protected]>

#if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE
// matches mp_usbd_deinit() above, ensure we have USB-CDC after soft reset
mp_usbd_init();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it makes sense to move this to the top of the soft reset loop, after mp_init()? And then remove the call to mp_usbd_init() from usb.c:usb_init()?

That would then match most of the other ports (eg rp2) in the way they call mp_usbd_init and mp_usbd_deinit.

@dpgeorge dpgeorge added this to the release-1.27.0 milestone Nov 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants