diff options
| -rw-r--r-- | tools/mpremote/mpremote/transport_serial.py | 60 |
1 files changed, 24 insertions, 36 deletions
diff --git a/tools/mpremote/mpremote/transport_serial.py b/tools/mpremote/mpremote/transport_serial.py index a26183680..eccdd4c1e 100644 --- a/tools/mpremote/mpremote/transport_serial.py +++ b/tools/mpremote/mpremote/transport_serial.py @@ -42,31 +42,8 @@ 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" +VID_SILICON_LABS = 0x10C4 class SerialTransport(Transport): @@ -90,19 +67,27 @@ class SerialTransport(Transport): delayed = False for attempt in range(wait + 1): try: - if device.startswith("rfc2217://"): - self.serial = serial.serial_for_url(device, **serial_kwargs) - elif os.name == "nt": - self.serial = serial.Serial(**serial_kwargs) - self.serial.port = device - 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 - self.serial.rts = False # RTS False = EN High = MCU enabled + self.serial = serial.serial_for_url(device, do_not_open=True, **serial_kwargs) + if os.name == "nt": + portinfo = list(serial.tools.list_ports.grep(device)) # type: ignore + if portinfo and getattr(portinfo[0], "vid", None) == VID_SILICON_LABS: + # Silicon Labs CP210x driver on Windows has a quirk + # where after a power on reset it will set DTR and RTS + # at different times when the port is opened (it doesn't + # happen on subsequent openings). + # + # To avoid issues with spurious reset on Espressif boards we clear DTR and RTS, + # open the port, and then set them in an order which prevents triggering a reset. + self.serial.dtr = False + self.serial.rts = False + self.serial.open() + self.serial.dtr = True + self.serial.rts = True + + # On all other host/driver combinations we keep the default + # behaviour (pyserial will set DTR and RTS automatically on open) + if not self.serial.isOpen(): self.serial.open() - else: - self.serial = serial.Serial(device, **serial_kwargs) break except OSError: if wait == 0: @@ -121,6 +106,9 @@ class SerialTransport(Transport): print("") def close(self): + # ESP Windows quirk: Prevent target from resetting when Windows clears DTR before RTS + self.serial.rts = False + self.serial.dtr = False self.serial.close() def read_until( |
