Skip to content

Commit 0edead4

Browse files
projectgusdpgeorge
authored andcommitted
tools/mpremote: Don't apply Espressif DTR/RTS quirk to TinyUSB CDC dev.
The DTR quirk workaround from dea949e 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 micropython#17999. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent 6940845 commit 0edead4

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

tools/mpremote/mpremote/transport_serial.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,37 @@
3636
# as a command line tool and a library for interacting with devices.
3737

3838
import ast, io, os, re, struct, sys, time
39+
import serial
40+
import serial.tools.list_ports
3941
from errno import EPERM
4042
from .console import VT_ENABLED
4143
from .transport import TransportError, TransportExecError, Transport
4244

4345
VID_ESPRESSIF = 0x303A # Espressif Incorporated
46+
PID_ESPRESSIF_SERIAL_JTAG = 0x1001 # Serial/JTAG peripheral of ESP32-S3,C3,C6
47+
48+
49+
def has_espressif_dtr_quirk(devicename):
50+
"""ESP8266 and ESP32 dev boards use the DTR and RTS lines to trigger reset &
51+
reset into bootloader mode. This can causes spurious reset issues on Windows.
52+
53+
Apply the quirk to any USB/Serial chip on Windows that isn't using the
54+
Microsoft CDC-ACM driver, or to the integrated Espressif Serial/JTAG device.
55+
56+
Don't apply it to Espressif boards running TinyUSB, as TinyUSB uses DTR
57+
to determine if the CDC port is open (and there's no spurious reset issue).
58+
"""
59+
portinfo = list(serial.tools.list_ports.grep(devicename)) # type: ignore
60+
if not portinfo:
61+
return False
62+
63+
def port_attr(name):
64+
return getattr(portinfo[0], name, None)
65+
66+
return (port_attr("vid"), port_attr("pid")) == (
67+
VID_ESPRESSIF,
68+
PID_ESPRESSIF_SERIAL_JTAG,
69+
) or port_attr("manufacturer") != "Microsoft"
4470

4571

4672
class SerialTransport(Transport):
@@ -52,9 +78,6 @@ def __init__(self, device, baudrate=115200, wait=0, exclusive=True, timeout=None
5278
self.device_name = device
5379
self.mounted = False
5480

55-
import serial
56-
import serial.tools.list_ports
57-
5881
# Set options, and exclusive if pyserial supports it
5982
serial_kwargs = {
6083
"baudrate": baudrate,
@@ -72,12 +95,7 @@ def __init__(self, device, baudrate=115200, wait=0, exclusive=True, timeout=None
7295
elif os.name == "nt":
7396
self.serial = serial.Serial(**serial_kwargs)
7497
self.serial.port = device
75-
portinfo = list(serial.tools.list_ports.grep(device)) # type: ignore
76-
if portinfo and (
77-
getattr(portinfo[0], "vid", 0) == VID_ESPRESSIF
78-
or getattr(portinfo[0], "manufacturer", "") != "Microsoft"
79-
):
80-
# ESP8266/ESP32 boards use RTS/CTS for flashing and boot mode selection.
98+
if has_espressif_dtr_quirk(device):
8199
# DTR False: to avoid using the reset button will hang the MCU in bootloader mode
82100
# RTS False: to prevent pulses on rts on serial.close() that would POWERON_RESET an ESPxx
83101
self.serial.dtr = False # DTR False = gpio0 High = Normal boot

0 commit comments

Comments
 (0)