Skip to content

Commit

Permalink
esptool: add work-around for RTS control for adapters using usbser.sys
Browse files Browse the repository at this point in the history
The usbser.sys driver used for standard CDC-ACM serial adapters has a known
limitation where it will only send the set-control-line-state request when
DTR is modified instead of when either DTR or RTS are modified.

As a work-around, send no-op DTR writes after RTS writes so the driver will
send the set-control-line-state request with the updated RTS state.
  • Loading branch information
devanlai committed Mar 23, 2018
1 parent ee00d84 commit 8b80fac
Showing 1 changed file with 17 additions and 7 deletions.
24 changes: 17 additions & 7 deletions esptool.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,16 @@ def sync(self):
for i in range(7):
self.command()

def _setDTR(self, state):
self._port.setDTR(state)

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)

def _connect_attempt(self, mode='default_reset', esp32r0_delay=False):
""" A single connection attempt, with esp32r0 workaround options """
# esp32r0_delay is a workaround for bugs with the most common auto reset
Expand All @@ -362,23 +372,23 @@ def _connect_attempt(self, mode='default_reset', esp32r0_delay=False):
# DTR & RTS are active low signals,
# ie True = pin @ 0V, False = pin @ VCC.
if mode != 'no_reset':
self._port.setDTR(False) # IO0=HIGH
self._port.setRTS(True) # EN=LOW, chip in reset
self._setDTR(False) # IO0=HIGH
self._setRTS(True) # EN=LOW, chip in reset
time.sleep(0.1)
if esp32r0_delay:
# Some chips are more likely to trigger the esp32r0
# watchdog reset silicon bug if they're held with EN=LOW
# for a longer period
time.sleep(1.2)
self._port.setDTR(True) # IO0=LOW
self._port.setRTS(False) # EN=HIGH, chip out of reset
self._setDTR(True) # IO0=LOW
self._setRTS(False) # EN=HIGH, chip out of reset
if esp32r0_delay:
# Sleep longer after reset.
# This workaround only works on revision 0 ESP32 chips,
# it exploits a silicon bug spurious watchdog reset.
time.sleep(0.4) # allow watchdog reset to occur
time.sleep(0.05)
self._port.setDTR(False) # IO0=HIGH, done
self._setDTR(False) # IO0=HIGH, done

for _ in range(5):
try:
Expand Down Expand Up @@ -822,9 +832,9 @@ def write_status(self, new_status, num_bytes=2, set_non_volatile=False):
self.run_spiflash_command(SPIFLASH_WRDI)

def hard_reset(self):
self._port.setRTS(True) # EN->LOW
self._setRTS(True) # EN->LOW
time.sleep(0.1)
self._port.setRTS(False)
self._setRTS(False)

def soft_reset(self, stay_in_bootloader):
if not self.IS_STUB:
Expand Down

0 comments on commit 8b80fac

Please sign in to comment.