summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2025-08-27 17:40:55 +1000
committerDamien George <damien@micropython.org>2025-09-10 16:55:19 +1000
commit1aaf6eddd82170209ca90586160ac265b9412229 (patch)
treefe747f4e6457b769ade143877a8cd4c17732d62e
parent371db85c8e9c29ac66d772e051c7a167782e8407 (diff)
tools/mpremote: Don't apply Espressif DTR/RTS quirk to TinyUSB CDC dev.
The DTR quirk workaround from dea949e86 is needed for the Espressif Serial/JTAG device, but not for TinyUSB - in fact DTR must be set for TinyUSB to correctly determine if the serial port is open (and leads to issues with lost bytes otherwise). See discussion in PR #17999. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
-rw-r--r--tools/mpremote/mpremote/transport_serial.py36
1 files changed, 27 insertions, 9 deletions
diff --git a/tools/mpremote/mpremote/transport_serial.py b/tools/mpremote/mpremote/transport_serial.py
index e2490a7ca..a26183680 100644
--- a/tools/mpremote/mpremote/transport_serial.py
+++ b/tools/mpremote/mpremote/transport_serial.py
@@ -36,11 +36,37 @@
# as a command line tool and a library for interacting with devices.
import ast, io, os, re, struct, sys, time
+import serial
+import serial.tools.list_ports
from errno import EPERM
from .console import VT_ENABLED
from .transport import TransportError, TransportExecError, Transport
VID_ESPRESSIF = 0x303A # Espressif Incorporated
+PID_ESPRESSIF_SERIAL_JTAG = 0x1001 # Serial/JTAG peripheral of ESP32-S3,C3,C6
+
+
+def has_espressif_dtr_quirk(devicename):
+ """ESP8266 and ESP32 dev boards use the DTR and RTS lines to trigger reset &
+ reset into bootloader mode. This can causes spurious reset issues on Windows.
+
+ Apply the quirk to any USB/Serial chip on Windows that isn't using the
+ Microsoft CDC-ACM driver, or to the integrated Espressif Serial/JTAG device.
+
+ Don't apply it to Espressif boards running TinyUSB, as TinyUSB uses DTR
+ to determine if the CDC port is open (and there's no spurious reset issue).
+ """
+ portinfo = list(serial.tools.list_ports.grep(devicename)) # type: ignore
+ if not portinfo:
+ return False
+
+ def port_attr(name):
+ return getattr(portinfo[0], name, None)
+
+ return (port_attr("vid"), port_attr("pid")) == (
+ VID_ESPRESSIF,
+ PID_ESPRESSIF_SERIAL_JTAG,
+ ) or port_attr("manufacturer") != "Microsoft"
class SerialTransport(Transport):
@@ -52,9 +78,6 @@ class SerialTransport(Transport):
self.device_name = device
self.mounted = False
- import serial
- import serial.tools.list_ports
-
# Set options, and exclusive if pyserial supports it
serial_kwargs = {
"baudrate": baudrate,
@@ -72,12 +95,7 @@ class SerialTransport(Transport):
elif os.name == "nt":
self.serial = serial.Serial(**serial_kwargs)
self.serial.port = device
- portinfo = list(serial.tools.list_ports.grep(device)) # type: ignore
- if portinfo and (
- getattr(portinfo[0], "vid", 0) == VID_ESPRESSIF
- or getattr(portinfo[0], "manufacturer", "") != "Microsoft"
- ):
- # ESP8266/ESP32 boards use RTS/CTS for flashing and boot mode selection.
+ if has_espressif_dtr_quirk(device):
# DTR False: to avoid using the reset button will hang the MCU in bootloader mode
# RTS False: to prevent pulses on rts on serial.close() that would POWERON_RESET an ESPxx
self.serial.dtr = False # DTR False = gpio0 High = Normal boot