From 970e037f99c39eb62e7a522ba910bc14f2b05453 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 23 May 2024 09:59:13 +1000 Subject: [PATCH] feat(reset): Automatically reconnect if port disconnects during reset --- esptool/reset.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/esptool/reset.py b/esptool/reset.py index 6223b5d98..dcfd2977e 100644 --- a/esptool/reset.py +++ b/esptool/reset.py @@ -26,6 +26,31 @@ DEFAULT_RESET_DELAY = 0.05 # default time to wait before releasing boot pin after reset +def reconnect(f): + def wrapper(*args): + """ + On targets with native USB, the reset process can cause the port to + disconnect / reconnect during reset. + This will retry reconnections for up to 10 seconds on ports that drop + out during the RTS/DTS reset process. + """ + self = args[0] + for retry in reversed(range(20)): + try: + if not self.port.isOpen(): + self.port.open() + ret = f(*args) + break + except OSError: + if not retry: + raise + self.port.close() + time.sleep(0.5) + return ret + + return wrapper + + class ResetStrategy(object): print_once = PrintOnce() @@ -51,9 +76,11 @@ def __call__(self): def reset(self): pass + @reconnect def _setDTR(self, state): self.port.setDTR(state) + @reconnect def _setRTS(self, state): self.port.setRTS(state) # Work-around for adapters on Windows using the usbser.sys driver: @@ -61,6 +88,7 @@ def _setRTS(self, state): # request is sent with the updated RTS state and the same DTR state self.port.setDTR(self.port.dtr) + @reconnect def _setDTRandRTS(self, dtr=False, rts=False): status = struct.unpack( "I", fcntl.ioctl(self.port.fileno(), TIOCMGET, struct.pack("I", 0))