Hi RMandR,
We use the toolchain within Ubuntu guest on Windows host. We use VirtualBox virtualization (with usb virtualization).
In our environment we did not manage to get the auto-program logic to work reliable. Latencies introduced by usb virtualization caused the logic to fail in our case. Changing capacitor values did not help either.
esptool.py uses pyserial. Unfortunately, with pyserial there is no way to toggle both used control signals (RTS and DTR) together in one step.
Using fcntl and termios, I found a way to get the stuff to work very reliable for me. Unfortunately this only works on Linux. With my limited python competence I did not manage to make the changed script compatible to the other platforms (where fcntl and termios don't exist). Anyway, maybe someone capable is out there, so I leave the few changes I made to esptool.py here.
... additional imports
Code: Select all
# Values to set DTR together with RTS in one call
TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
TIOCM_DTR_SET_RTS_CLEAR = 0x002
TIOCM_DTR_SET_RTS_CLEAR_str = struct.pack('I', TIOCM_DTR_SET_RTS_CLEAR)
TIOCM_DTR_CLEAR_RTS_SET = 0x004
TIOCM_DTR_CLEAR_RTS_SET_str = struct.pack('I', TIOCM_DTR_CLEAR_RTS_SET)
Code: Select all
# detect platform
plat = sys.platform.lower()
if plat[:5] == 'linux':
self._is_linux = True
else:
self._is_linux = False
Code: Select all
def _setDTR_and_inverted_RTS(self, state):
""" Set DTR to state and RTS to NOT state """
# PySerial can not set multiple signals in one call, as it should be
# for the auto-program logic to work best.
# In some cases (like running esptool within a virtual machine) latencies
# can cause the ESP chip to fail entering download boot.
# fcntl.ioctl() is used to set DTR and RTS in one call. This is platform specific.
if (self._is_linux):
if state:
fcntl.ioctl(self._port.fileno(), self.TIOCMSET, self.TIOCM_DTR_SET_RTS_CLEAR_str)
else:
fcntl.ioctl(self._port.fileno(), self.TIOCMSET, self.TIOCM_DTR_CLEAR_RTS_SET_str)
else:
self._port.setDTR(state)
self._port.setRTS( not state)
Original mechanism in esptool.py:
Code: Select all
if mode != 'no_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._setDTR(True) # IO0=LOW
self._setRTS(False) # EN=HIGH, chip out of reset
if esp32r0_delay:
Changed to:
Code: Select all
if mode != 'no_reset':
self._setDTR_and_inverted_RTS( False) # IO0=HIGH, 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._setDTR_and_inverted_RTS( True) # IO0=LOW, EN=HIGH, chip out of reset
if esp32r0_delay:
Best,
Markus