Skip to content

Commit

Permalink
feat(reset): Apply recconections to the whole reset sequence, not lin…
Browse files Browse the repository at this point in the history
…e transitions
  • Loading branch information
radimkarnis committed Jun 13, 2024
1 parent 9dc5dfb commit d49837e
Showing 1 changed file with 24 additions and 39 deletions.
63 changes: 24 additions & 39 deletions esptool/reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,69 +26,54 @@
DEFAULT_RESET_DELAY = 0.05 # default time to wait before releasing boot pin after reset


def reconnect(f):
def wrapper(*args):
class ResetStrategy(object):
print_once = PrintOnce()

def __init__(self, port, reset_delay=DEFAULT_RESET_DELAY):
self.port = port
self.reset_delay = reset_delay

def __call__(self):
"""
On targets with native USB, the reset process can cause the port to
On targets with USB modes, 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.
This will retry reconnections on ports that
drop out during the reset sequence.
"""
self = args[0]
for retry in reversed(range(20)):
for retry in reversed(range(3)):
try:
if not self.port.isOpen():
self.port.open()
ret = f(*args)
self.reset()
break
except OSError:
if not retry:
except OSError as e:
# ENOTTY for TIOCMSET; EINVAL for TIOCMGET
if e.errno in [errno.ENOTTY, errno.EINVAL]:
self.print_once(
"WARNING: Chip was NOT reset. Setting RTS/DTR lines is not "
f"supported for port '{self.port.name}'. Set --before and --after "
"arguments to 'no_reset' and switch to bootloader manually to "
"avoid this warning."
)
break
elif not retry:
raise
self.port.close()
time.sleep(0.5)
return ret

return wrapper


class ResetStrategy(object):
print_once = PrintOnce()

def __init__(self, port, reset_delay=DEFAULT_RESET_DELAY):
self.port = port
self.reset_delay = reset_delay

def __call__(self):
try:
self.reset()
except OSError as e:
# ENOTTY for TIOCMSET; EINVAL for TIOCMGET
if e.errno in [errno.ENOTTY, errno.EINVAL]:
self.print_once(
"WARNING: Chip was NOT reset. Setting RTS/DTR lines is not "
f"supported for port '{self.port.name}'. Set --before and --after "
"arguments to 'no_reset' and switch to bootloader manually to "
"avoid this warning."
)
else:
raise

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:
# generate a dummy change to DTR so that the set-control-line-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))
Expand Down

0 comments on commit d49837e

Please sign in to comment.