New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32 Reset To Bootloader Issues on Windows #136

Closed
negativekelvin opened this Issue Oct 18, 2016 · 26 comments

Comments

Projects
None yet
8 participants
@negativekelvin

negativekelvin commented Oct 18, 2016

On windows, it seems like there are timing issues with the reset to bootloader functions using the DTR and RTS circuit for esp32 because setDTR and setRTS are sent separately. Possible fix:

            # issue reset-to-bootloader:
            # RTS = either CH_PD or nRESET (both active low = chip in reset)
            # DTR = GPIO0 (active low = boot to flasher)
            self._port._dtr_state = False
            self._port._rts_state = True
            self._port._reconfigure_port()
            time.sleep(0.05)
            self._port._dtr_state = True
            self._port._rts_state = False
            self._port._reconfigure_port()
            time.sleep(0.05)
            self._port.setDTR(False)

I haven't scoped this or tested it because my v1 board has the transistor bug.

@negativekelvin negativekelvin changed the title from Reset To Bootloader Issues on Windows to ESP32 Reset To Bootloader Issues on Windows Oct 18, 2016

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Oct 18, 2016

Member

Thanks @negativekelvin. I don't know if you're following the forum thread, but I'm guessing you are.
http://esp32.com/viewtopic.php?f=2&t=334&p=1503#p1497

I considered this solution as well (although I didn't test it either.) The problem is, I'm not comfortable relying on the private interface of pyserial. At minimum, it's necessary to check it hasn't changed over any previous supported pyserial versions. But even if it works with all those, if the private interface changes in the future then it could break esptool without warning.

A hacky but somewhat safer way would be to check all these properties exist with hasattr() before calling them, and fail back to the public API instead. But this is still super hacky.

The safest, most maintainable, fix that I can think of is probably to call the win32 GetCommState/SetCommState API functions directly. This is a stable public API, and the only private part of pyserial it needs to touch is the port handle. I still don't like that idea, but it seems least likely to suddenly break.

Member

projectgus commented Oct 18, 2016

Thanks @negativekelvin. I don't know if you're following the forum thread, but I'm guessing you are.
http://esp32.com/viewtopic.php?f=2&t=334&p=1503#p1497

I considered this solution as well (although I didn't test it either.) The problem is, I'm not comfortable relying on the private interface of pyserial. At minimum, it's necessary to check it hasn't changed over any previous supported pyserial versions. But even if it works with all those, if the private interface changes in the future then it could break esptool without warning.

A hacky but somewhat safer way would be to check all these properties exist with hasattr() before calling them, and fail back to the public API instead. But this is still super hacky.

The safest, most maintainable, fix that I can think of is probably to call the win32 GetCommState/SetCommState API functions directly. This is a stable public API, and the only private part of pyserial it needs to touch is the port handle. I still don't like that idea, but it seems least likely to suddenly break.

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Oct 18, 2016

Member

Or to submit a patch to pyserial, some variant of the existing apply_settings() that applies all settings as an "atomic" operation.

Member

projectgus commented Oct 18, 2016

Or to submit a patch to pyserial, some variant of the existing apply_settings() that applies all settings as an "atomic" operation.

@negativekelvin

This comment has been minimized.

Show comment
Hide comment
@negativekelvin

negativekelvin Oct 18, 2016

Yes, that makes sense. I don't know if those properties and methods are very likely to change, so yes I like the check and fall back strategy until pyserial can support it.

negativekelvin commented Oct 18, 2016

Yes, that makes sense. I don't know if those properties and methods are very likely to change, so yes I like the check and fall back strategy until pyserial can support it.

@negativekelvin

This comment has been minimized.

Show comment
Hide comment
@negativekelvin

negativekelvin Oct 18, 2016

However it also looks like _reconfigure_port() only updates the RTS/DTR lines on windows, not other platforms. So would have to add a platform check before calling.

negativekelvin commented Oct 18, 2016

However it also looks like _reconfigure_port() only updates the RTS/DTR lines on windows, not other platforms. So would have to add a platform check before calling.

@bvernoux

This comment has been minimized.

Show comment
Hide comment
@bvernoux

bvernoux Oct 18, 2016

For full details on this issue I have done a full analysis of the problem on Win7 see
http://esp32.com/viewtopic.php?f=2&p=1511#p1511

I also confirm that by modifying esptool.py
from

            self._port.setDTR(False)
            self._port.setRTS(True)
            time.sleep(0.05)
            self._port.setDTR(True)
            self._port.setRTS(False)
            time.sleep(0.05)
            self._port.setDTR(False)

to

            self._port.setDTR(False)    # GPIO0 -> 1
            self._port.setRTS(True  )   # RST -> 0
            self._port.setDTR(True  )   # GPIO0 -> 0
            time.sleep(0.05)
            self._port.setRTS(False )   # RST -> 1
            time.sleep(0.1) 

That fix the problem on win7 (thanks to rudi post http://esp32.com/viewtopic.php?f=13&p=1512#p1512)

bvernoux commented Oct 18, 2016

For full details on this issue I have done a full analysis of the problem on Win7 see
http://esp32.com/viewtopic.php?f=2&p=1511#p1511

I also confirm that by modifying esptool.py
from

            self._port.setDTR(False)
            self._port.setRTS(True)
            time.sleep(0.05)
            self._port.setDTR(True)
            self._port.setRTS(False)
            time.sleep(0.05)
            self._port.setDTR(False)

to

            self._port.setDTR(False)    # GPIO0 -> 1
            self._port.setRTS(True  )   # RST -> 0
            self._port.setDTR(True  )   # GPIO0 -> 0
            time.sleep(0.05)
            self._port.setRTS(False )   # RST -> 1
            time.sleep(0.1) 

That fix the problem on win7 (thanks to rudi post http://esp32.com/viewtopic.php?f=13&p=1512#p1512)

@bvernoux bvernoux referenced this issue Oct 19, 2016

Closed

DTR #130

@bvernoux

This comment has been minimized.

Show comment
Hide comment
@bvernoux

bvernoux Oct 20, 2016

In fact after analysis of rudi patch it is pure luck (thanks to watchdog and glitch on EN signal)
For more details on Rudi patch see Saleae Logic 1.2.10 capture:

I have simplified it like that
esptool.py modifications (MyPatch):
from

            self._port.setRTS(True)
            time.sleep(0.05)
            self._port.setDTR(True)
            self._port.setRTS(False)
            time.sleep(0.05)
            self._port.setDTR(False)

to

            self._port.setDTR(False) # EN=0 and IO0=0
            time.sleep(0.05)
            self._port.setRTS(False) # EN=1 and IO0=1(glitch on IO0 during 1ms)
            self._port.setDTR(True)  # EN=1 and IO0=0

The main problem is the glitch on IO0 during 1.1ms which does not allow to enter download mode as IO0 is sampled by ESP32 during this glitch but we are lucky that we have a reset by watchdog after 0.385s (with message RTCWDT_RTC_RESET) which then boot in download mode because EN=1 and IO0=0

For more details see Saleae Logic 1.2.10 capture of MyPatch:

For information MyPatch is a bit faster (300ms) compared to Rudi version and keep EN to 0 during at least 50ms(and not 3.5ms like Rudi which in fact is a glitch) and after multiple test my patch never fail with Win7 64bits and also under VirtualBox with Xubuntu 14.04
If other can give feedback it will be great

bvernoux commented Oct 20, 2016

In fact after analysis of rudi patch it is pure luck (thanks to watchdog and glitch on EN signal)
For more details on Rudi patch see Saleae Logic 1.2.10 capture:

I have simplified it like that
esptool.py modifications (MyPatch):
from

            self._port.setRTS(True)
            time.sleep(0.05)
            self._port.setDTR(True)
            self._port.setRTS(False)
            time.sleep(0.05)
            self._port.setDTR(False)

to

            self._port.setDTR(False) # EN=0 and IO0=0
            time.sleep(0.05)
            self._port.setRTS(False) # EN=1 and IO0=1(glitch on IO0 during 1ms)
            self._port.setDTR(True)  # EN=1 and IO0=0

The main problem is the glitch on IO0 during 1.1ms which does not allow to enter download mode as IO0 is sampled by ESP32 during this glitch but we are lucky that we have a reset by watchdog after 0.385s (with message RTCWDT_RTC_RESET) which then boot in download mode because EN=1 and IO0=0

For more details see Saleae Logic 1.2.10 capture of MyPatch:

For information MyPatch is a bit faster (300ms) compared to Rudi version and keep EN to 0 during at least 50ms(and not 3.5ms like Rudi which in fact is a glitch) and after multiple test my patch never fail with Win7 64bits and also under VirtualBox with Xubuntu 14.04
If other can give feedback it will be great

@negativekelvin

This comment has been minimized.

Show comment
Hide comment
@negativekelvin

negativekelvin Oct 21, 2016

@bvernoux are you able to capture the waveforms for the method using reconfigure_port in the first post on windows?

negativekelvin commented Oct 21, 2016

@bvernoux are you able to capture the waveforms for the method using reconfigure_port in the first post on windows?

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Oct 21, 2016

Member

I just tried a different fix for this issue (1f5d9d2) which should be equivalent to calling _reconfigure_port, and I thought would definitely correct the issue.

Unfortunately the timing seems to be the same (trace attached), even when both DTR & RTS are set in the same Windows API call. Which I think means the CP2102 Windows driver is doing this, and there's no way to change that pulse in software.

2016-10-21-143743_1680x981_scrot

Member

projectgus commented Oct 21, 2016

I just tried a different fix for this issue (1f5d9d2) which should be equivalent to calling _reconfigure_port, and I thought would definitely correct the issue.

Unfortunately the timing seems to be the same (trace attached), even when both DTR & RTS are set in the same Windows API call. Which I think means the CP2102 Windows driver is doing this, and there's no way to change that pulse in software.

2016-10-21-143743_1680x981_scrot

@negativekelvin

This comment has been minimized.

Show comment
Hide comment
@negativekelvin

negativekelvin Oct 21, 2016

That is disappointing. Time to ask silicon labs?

negativekelvin commented Oct 21, 2016

That is disappointing. Time to ask silicon labs?

@negativekelvin

This comment has been minimized.

Show comment
Hide comment
@negativekelvin

negativekelvin Oct 21, 2016

we are lucky that we have a reset by watchdog after 0.385s

What is the cause of this?

negativekelvin commented Oct 21, 2016

we are lucky that we have a reset by watchdog after 0.385s

What is the cause of this?

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Oct 21, 2016

Member

we are lucky that we have a reset by watchdog after 0.385s
What is the cause of this?

It's a silicon bug, that will be fixed at some point.

A solution that seems to work reliably is to add a ~2.2uF capacitor (I think 470nF-2.2uF range should be suitable) to the EN pin (between EN and GND), so it rises slower (there is a ~12K pullup on this pin.) This is not super desirable, as it requires a hardware change, but it works.

Member

projectgus commented Oct 21, 2016

we are lucky that we have a reset by watchdog after 0.385s
What is the cause of this?

It's a silicon bug, that will be fixed at some point.

A solution that seems to work reliably is to add a ~2.2uF capacitor (I think 470nF-2.2uF range should be suitable) to the EN pin (between EN and GND), so it rises slower (there is a ~12K pullup on this pin.) This is not super desirable, as it requires a hardware change, but it works.

@bvernoux

This comment has been minimized.

Show comment
Hide comment
@bvernoux

bvernoux Oct 28, 2016

I confirm adding a 2.2uF capacitor on EN (connected between EN and GND) fix the problem
esp32-devkitc_fix_boot_download_esptool_with_2_2uf_capacitor_on_en

bvernoux commented Oct 28, 2016

I confirm adding a 2.2uF capacitor on EN (connected between EN and GND) fix the problem
esp32-devkitc_fix_boot_download_esptool_with_2_2uf_capacitor_on_en

@krzychb

This comment has been minimized.

Show comment
Hide comment
@krzychb

krzychb Nov 5, 2016

@projectgus and all - thank you guys!
No more fiddling with EN / Boot buttons.
Life is much easier with this simple hack 😄
Krzysztof

img_2448

krzychb commented Nov 5, 2016

@projectgus and all - thank you guys!
No more fiddling with EN / Boot buttons.
Life is much easier with this simple hack 😄
Krzysztof

img_2448

@ladyada

This comment has been minimized.

Show comment
Hide comment
@ladyada

ladyada Nov 13, 2016

hiya - got bit by this bug, and found a few things helped. capacitor helps but easier to change the second time.sleep(0.05) to time.sleep(0.5) e.g. https://github.com/adafruit/arduino-esp32/blob/master/tools/esptool.py#L279
that along with a formal 'reset' procedure to swat the ESP32 back into 'user mode'
https://github.com/adafruit/arduino-esp32/blob/master/tools/esptool.py#L296
has made developing code work great on win7 + CP210x... plz re-consider the wontfix? there's a lot of those DevKitC's in the world now :) i can test on mac/linux too

ladyada commented Nov 13, 2016

hiya - got bit by this bug, and found a few things helped. capacitor helps but easier to change the second time.sleep(0.05) to time.sleep(0.5) e.g. https://github.com/adafruit/arduino-esp32/blob/master/tools/esptool.py#L279
that along with a formal 'reset' procedure to swat the ESP32 back into 'user mode'
https://github.com/adafruit/arduino-esp32/blob/master/tools/esptool.py#L296
has made developing code work great on win7 + CP210x... plz re-consider the wontfix? there's a lot of those DevKitC's in the world now :) i can test on mac/linux too

@bvernoux

This comment has been minimized.

Show comment
Hide comment
@bvernoux

bvernoux Nov 13, 2016

For information it is already fixed in actual branch even without the capacitor => thanks to an ESP32 silicon bug with reset by watchdog after 0.385s
I do not see why this modification will improve anything.
Do you have a sigrok capture to show the difference with this patch ?

bvernoux commented Nov 13, 2016

For information it is already fixed in actual branch even without the capacitor => thanks to an ESP32 silicon bug with reset by watchdog after 0.385s
I do not see why this modification will improve anything.
Do you have a sigrok capture to show the difference with this patch ?

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Nov 14, 2016

Member

Hi @bvernoux,

For information it is already fixed in actual branch even without the capacitor

I don't believe this is fixed in any branch at the moment, without adding either a capacitor or the time.sleep(0.5) modification that @ladyada mentions.

Hi @ladyada,

plz re-consider the wontfix? there's a lot of those DevKitC's in the world now :)

The problem I see is because the 0.5s delay happens to rely on a silicon bug, which is already fixed in the forthcoming chip revision. When the updated chips come out, the bug will bite everyone again (if the capacitor on EN hasn't been changed in the board design) and it will also take longer any time esptool.py fails to connect, due to the extra delays.

There are perhaps some other ways to work around this, either a command line option like --variant or --board to let people specify they have the gen1 silicon, or a long-standing suggestion (#27) to read back the "header" message that the chip prints in order to detect boot mode failures earlier.

Member

projectgus commented Nov 14, 2016

Hi @bvernoux,

For information it is already fixed in actual branch even without the capacitor

I don't believe this is fixed in any branch at the moment, without adding either a capacitor or the time.sleep(0.5) modification that @ladyada mentions.

Hi @ladyada,

plz re-consider the wontfix? there's a lot of those DevKitC's in the world now :)

The problem I see is because the 0.5s delay happens to rely on a silicon bug, which is already fixed in the forthcoming chip revision. When the updated chips come out, the bug will bite everyone again (if the capacitor on EN hasn't been changed in the board design) and it will also take longer any time esptool.py fails to connect, due to the extra delays.

There are perhaps some other ways to work around this, either a command line option like --variant or --board to let people specify they have the gen1 silicon, or a long-standing suggestion (#27) to read back the "header" message that the chip prints in order to detect boot mode failures earlier.

@ladyada

This comment has been minimized.

Show comment
Hide comment
@ladyada

ladyada Nov 14, 2016

yah ok - i didn't realize it was a silicon issue on the esp32 (thought it was cp210x) in which case... i agree y'all should keep as wontfix.
i will update the devkitc product page to tell people to add a capacitor if they're having upload probs on windows

ladyada commented Nov 14, 2016

yah ok - i didn't realize it was a silicon issue on the esp32 (thought it was cp210x) in which case... i agree y'all should keep as wontfix.
i will update the devkitc product page to tell people to add a capacitor if they're having upload probs on windows

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Nov 14, 2016

Member

yah ok - i didn't realize it was a silicon issue on the esp32 (thought it was cp210x) in which case... i agree y'all should keep as wontfix.

Just to be sure we're on the same page, the silicon issue on esp32 is what allows the extra time.sleep(0.5) delay to work as a workaround (the chip resets twice due to an unexpected WDT), rather than the cause of this bug. The cause of this bug is an interaction between the reset circuit timing and Windows driver behaviour (probably CP210x-specific but I haven't confirmed this.)

i will update the devkitc product page to tell people to add a capacitor if they're having upload probs on windows

That would be awesome, thanks very much. :)

Member

projectgus commented Nov 14, 2016

yah ok - i didn't realize it was a silicon issue on the esp32 (thought it was cp210x) in which case... i agree y'all should keep as wontfix.

Just to be sure we're on the same page, the silicon issue on esp32 is what allows the extra time.sleep(0.5) delay to work as a workaround (the chip resets twice due to an unexpected WDT), rather than the cause of this bug. The cause of this bug is an interaction between the reset circuit timing and Windows driver behaviour (probably CP210x-specific but I haven't confirmed this.)

i will update the devkitc product page to tell people to add a capacitor if they're having upload probs on windows

That would be awesome, thanks very much. :)

@ladyada

This comment has been minimized.

Show comment
Hide comment
@ladyada

ladyada Nov 14, 2016

ahh ok yes reading thru more carefully i understand the double-bug interaction! too funny - ok thanks!

ladyada commented Nov 14, 2016

ahh ok yes reading thru more carefully i understand the double-bug interaction! too funny - ok thanks!

@rojer

This comment has been minimized.

Show comment
Hide comment
@rojer

rojer Dec 23, 2016

Contributor

just found my way to this issue. not before spending some time banging my head against the wall, though :)

the workaround seems fine, i just want to confirm: devkit hardware will be revised to increase the capacitor value, right? hopefully, in time for new chip revision which fixes the glitch.

Contributor

rojer commented Dec 23, 2016

just found my way to this issue. not before spending some time banging my head against the wall, though :)

the workaround seems fine, i just want to confirm: devkit hardware will be revised to increase the capacitor value, right? hopefully, in time for new chip revision which fixes the glitch.

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Dec 27, 2016

Member

Yes, newer Espressif DevKits will fix this issue via increased capacitance on the EN pin.

Member

projectgus commented Dec 27, 2016

Yes, newer Espressif DevKits will fix this issue via increased capacitance on the EN pin.

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Jan 10, 2017

Member

esptool v2.0 (current master, and the version in esp-idf) has a new --after esp32r0 option which will work around this issue for ESP32 original revision chips.

The option can also be selected under "make menuconfig" in esp-idf.

Member

projectgus commented Jan 10, 2017

esptool v2.0 (current master, and the version in esp-idf) has a new --after esp32r0 option which will work around this issue for ESP32 original revision chips.

The option can also be selected under "make menuconfig" in esp-idf.

@MartyMacGyver

This comment has been minimized.

Show comment
Hide comment
@MartyMacGyver

MartyMacGyver Jan 23, 2017

Contributor

I've been investigating this and I think there's a more permanent solution that'd be effective and not too burdensome. Interestingly, the esp32r0 workaround doesn't seem to help at all for this yet it sounds like a similar issue if not the same one.

A long discussion follows with technical details I've gleaned, but the bottom line is that holding the chip in reset longer does the trick. The code change to esptool.py is a one-liner:

...
self._port.setDTR(False)  # IO0=HIGH
self._port.setRTS(True)   # EN=LOW, chip in reset
time.sleep(2.0)  # Sleep longer
self._port.setDTR(True)   # IO0=LOW
self._port.setRTS(False)  # EN=HIGH, chip out of reset
time.sleep(0.5)  # Sleep longer
...

This has the advantage of working on both current boards (and 2 seconds isn't long to wait relative to everything else). If it were a default it'd work smoothly with the Arduino-ESP32 as well - not sure how one is supposed to get --before esp32r0 to work there - is it a config option there (the reset-on-disconnect thing is of related interest but for other discussions).

Note: for the hard-reset bit, while I see the --before esp32r0 option, I don't see it in --after. Not sure if there is any problem with board reset (as long as DTS is in the right state) so maybe that was a typo?


The Core Board v2 and ESP-WROVER-KIT act differently upon serial disconnect, and downloads negotiation works slightly differently for each.

Previous discussions about this include:
espressif/esp-idf#59
#136
espressif/arduino-esp32#127 (comment)
http://esp32.com/viewtopic.php?f=13&t=334

Tested on Windows with the latest serial drivers via RealTerm:
Si Labs CP210x driver v6.7.4.261 (non-enumerating) for the Core Board v2
FTDI driver v2.12.24.0 (enumeration disabled) for the ESP-WROVER-KIT

Note: interestingly, clear/set can be positive logic (clear = 0/low/false, set = 1/high/true), or the inverse (active low). In esptool.py the active low mode is used - here, I used active high notation.

For the ESP-WROVER-KIT, to get to download mode, it's pretty simple:

  • Start with RTS and DTR set
  • Do the following in quick succession (no long pause between the steps):
    • clear DTR (holds reset low)
    • set DTR
    • clear RTS (enters download mode)
    • set RTS (can immediately do this)
    • toggle DTR clear+set to reset in run mode

The Core Board v2 is different though - it needs about 2 seconds delay between clearing DTR and setting it:

  • Start with RTS and DTR set
  • Do the following in quick succession (except as noted):
    • clear DTR (holds reset low)
    • wait 2 seconds
    • set DTR
    • clear RTS (enters download mode)
    • set RTS (can immediately do this)
    • toggle DTR clear+set to reset in run mode

The boot up sequence differs slightly too - on the Core Board v2 that long pause causes a flash error.

ESP-WROVER-KIT

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x16 (SPI_FAST_FLASH_BOOT)
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x6 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_FEO_V2))
waiting for download

Core Board v2

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
Falling back to built-in command interpreter.
OK
>ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download

Also peculiar: if DTR and RTS are both cleared, the EN switch on the ESP-WROVER-KIT won't work at all (this is not the case on the Core Board v2).

(As an aside, on both devices, if RTS is set, setting DTR (from cleared) resets the board. If DTR is clear, clearing RTS (from set) also resets the board.)

The only obvious difference between the two RTS/DTR circuits in the corresponding schematics is that the Core Board v2 specs 12kohm resistors between the CP2102 bridge and the bases of the S8050 transistors, while the ESP-WROVER-KIT specs 1kohm resistors between the FT2232HL bridge and the bases of the S8050 transistors. (The BOOT and EN switch circuits appear to be identical on both.)

Note: I have no shunts bridging the CTS/RTS headers on the WROVER board. It doesn't appear it would have a positive effect.

Contributor

MartyMacGyver commented Jan 23, 2017

I've been investigating this and I think there's a more permanent solution that'd be effective and not too burdensome. Interestingly, the esp32r0 workaround doesn't seem to help at all for this yet it sounds like a similar issue if not the same one.

A long discussion follows with technical details I've gleaned, but the bottom line is that holding the chip in reset longer does the trick. The code change to esptool.py is a one-liner:

...
self._port.setDTR(False)  # IO0=HIGH
self._port.setRTS(True)   # EN=LOW, chip in reset
time.sleep(2.0)  # Sleep longer
self._port.setDTR(True)   # IO0=LOW
self._port.setRTS(False)  # EN=HIGH, chip out of reset
time.sleep(0.5)  # Sleep longer
...

This has the advantage of working on both current boards (and 2 seconds isn't long to wait relative to everything else). If it were a default it'd work smoothly with the Arduino-ESP32 as well - not sure how one is supposed to get --before esp32r0 to work there - is it a config option there (the reset-on-disconnect thing is of related interest but for other discussions).

Note: for the hard-reset bit, while I see the --before esp32r0 option, I don't see it in --after. Not sure if there is any problem with board reset (as long as DTS is in the right state) so maybe that was a typo?


The Core Board v2 and ESP-WROVER-KIT act differently upon serial disconnect, and downloads negotiation works slightly differently for each.

Previous discussions about this include:
espressif/esp-idf#59
#136
espressif/arduino-esp32#127 (comment)
http://esp32.com/viewtopic.php?f=13&t=334

Tested on Windows with the latest serial drivers via RealTerm:
Si Labs CP210x driver v6.7.4.261 (non-enumerating) for the Core Board v2
FTDI driver v2.12.24.0 (enumeration disabled) for the ESP-WROVER-KIT

Note: interestingly, clear/set can be positive logic (clear = 0/low/false, set = 1/high/true), or the inverse (active low). In esptool.py the active low mode is used - here, I used active high notation.

For the ESP-WROVER-KIT, to get to download mode, it's pretty simple:

  • Start with RTS and DTR set
  • Do the following in quick succession (no long pause between the steps):
    • clear DTR (holds reset low)
    • set DTR
    • clear RTS (enters download mode)
    • set RTS (can immediately do this)
    • toggle DTR clear+set to reset in run mode

The Core Board v2 is different though - it needs about 2 seconds delay between clearing DTR and setting it:

  • Start with RTS and DTR set
  • Do the following in quick succession (except as noted):
    • clear DTR (holds reset low)
    • wait 2 seconds
    • set DTR
    • clear RTS (enters download mode)
    • set RTS (can immediately do this)
    • toggle DTR clear+set to reset in run mode

The boot up sequence differs slightly too - on the Core Board v2 that long pause causes a flash error.

ESP-WROVER-KIT

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x16 (SPI_FAST_FLASH_BOOT)
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x6 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_FEO_V2))
waiting for download

Core Board v2

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
Falling back to built-in command interpreter.
OK
>ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download

Also peculiar: if DTR and RTS are both cleared, the EN switch on the ESP-WROVER-KIT won't work at all (this is not the case on the Core Board v2).

(As an aside, on both devices, if RTS is set, setting DTR (from cleared) resets the board. If DTR is clear, clearing RTS (from set) also resets the board.)

The only obvious difference between the two RTS/DTR circuits in the corresponding schematics is that the Core Board v2 specs 12kohm resistors between the CP2102 bridge and the bases of the S8050 transistors, while the ESP-WROVER-KIT specs 1kohm resistors between the FT2232HL bridge and the bases of the S8050 transistors. (The BOOT and EN switch circuits appear to be identical on both.)

Note: I have no shunts bridging the CTS/RTS headers on the WROVER board. It doesn't appear it would have a positive effect.

@MartyMacGyver

This comment has been minimized.

Show comment
Hide comment
@MartyMacGyver

MartyMacGyver Jan 23, 2017

Contributor

One other thing... I'm using non-enumerating drivers here. I strongly recommend people stay far away from the enumerating drivers (or disable enumeration for the ports using it), particularly in Windows, if they don't have a reason to be using it (typically emulating a mouse).

If the mouse filter gets spurious data (as is quite likely even from a factory fresh device during reset/boot-up) you could get a blue screen. Longer discussion here.

The default driver Windows installs for the CP2102 is enumerating - the one I used to test all this is the same one but non-enumerating. That alone could compound everything above as there is that extra layer of introspection for enumeration purposes (and they do act differently... it's annoying. My fix above should work in either case, though the risk of BSOD would remain with enumeration).

Contributor

MartyMacGyver commented Jan 23, 2017

One other thing... I'm using non-enumerating drivers here. I strongly recommend people stay far away from the enumerating drivers (or disable enumeration for the ports using it), particularly in Windows, if they don't have a reason to be using it (typically emulating a mouse).

If the mouse filter gets spurious data (as is quite likely even from a factory fresh device during reset/boot-up) you could get a blue screen. Longer discussion here.

The default driver Windows installs for the CP2102 is enumerating - the one I used to test all this is the same one but non-enumerating. That alone could compound everything above as there is that extra layer of introspection for enumeration purposes (and they do act differently... it's annoying. My fix above should work in either case, though the risk of BSOD would remain with enumeration).

MartyMacGyver added a commit to MartyMacGyver/esptool that referenced this issue Jan 23, 2017

Resolve serial flash issues for legacy devices
Attempts normal connection, then attempts legacy connection
Improves legacy connection compatibility

Resolves issue espressif#136

MartyMacGyver added a commit to MartyMacGyver/esptool that referenced this issue Jan 23, 2017

Resolve serial flash issues for legacy devices
Attempts normal connection, then attempts legacy connection
Improves legacy connection compatibility

Resolves issue espressif#136
@grisevg

This comment has been minimized.

Show comment
Hide comment
@grisevg

grisevg Jan 26, 2017

This is not windows specific. Same issue on macOS with cp210x drivers: espressif/esp-idf#305

grisevg commented Jan 26, 2017

This is not windows specific. Same issue on macOS with cp210x drivers: espressif/esp-idf#305

MartyMacGyver added a commit to MartyMacGyver/esptool that referenced this issue Jan 27, 2017

Resolve serial flash issues for esp32r0 devices
Attempts normal connection, then attempts connection with esp32r0-related delays
Improves esp32r0 connection compatibility

Resolves issue espressif#136

MartyMacGyver added a commit to MartyMacGyver/esptool that referenced this issue Jan 28, 2017

Resolve serial flash issues for esp32r0 devices
Attempts normal connection, then attempts connection with esp32r0-related delays
Improves esp32r0 connection compatibility

Resolves issue espressif#136

MartyMacGyver added a commit to MartyMacGyver/esptool that referenced this issue Jan 30, 2017

Resolve serial flash issues for boards with reset circuit bugs
Improves connection compatibility - Attempts normal connection, then
attempts connection with an extended reset delay and a delay that triggers
a watchdog timeout (esp32r0-only) to more reliably enter download mode.

Fallback design - initial connect is without workarounds - if that fails, the
extra delays are used.

Resolves issue espressif#136

MartyMacGyver added a commit to MartyMacGyver/esptool that referenced this issue Jan 30, 2017

Resolve serial flash issues for boards with reset circuit bugs
Improves connection compatibility - Attempts normal connection, then
attempts connection with an extended reset delay and a delay that triggers
a watchdog timeout (esp32r0-only) to more reliably enter download mode.

Fallback design - initial connect is without workarounds - if that fails, the
extra delays are used.

Resolves issue espressif#136

MartyMacGyver added a commit to MartyMacGyver/esptool that referenced this issue Feb 22, 2017

Resolve serial flash issues for boards with reset circuit bugs
Improves connection compatibility - Attempts normal connection, then
attempts connection with an extended reset delay and a delay that triggers
a watchdog timeout (esp32r0-only) to more reliably enter download mode.

Fallback design - initial connect is without workarounds - if that fails, the
extra delays are used.

Resolves issue espressif#136

projectgus added a commit that referenced this issue Mar 2, 2017

ESP32 serial bug tweak: Combine latency_delay & esp32r0_delay
The latency_delay workaround appears to be an extension of esp32r0_delay, as the
longer reset period helps the esp32r0 watchdog bug trigger more reliably.

Ref #172 #136

@projectgus projectgus removed the wontfix label Mar 2, 2017

@projectgus

This comment has been minimized.

Show comment
Hide comment
@projectgus

projectgus Mar 2, 2017

Member

Thanks to @MartyMacGyver and everyone else who helped diagnose this, we seem to have a reliable fix now which doesn't require any special command line arguments.

This fix should propagate to the ESP-IDF & Arduino esptool.py versions, soon.

Also, new development board hardware should no longer exhibit the underlying bug in the first place (provided 100nF or more of capacitance is present on the EN pin, with a 10K or higher pullup on that pin).

Please open an issue if this fix doesn't appear to fix auto-reset on your board (either reopen this issue, or if you have more specifics to provide then please open a new one instead.) Thanks.

Member

projectgus commented Mar 2, 2017

Thanks to @MartyMacGyver and everyone else who helped diagnose this, we seem to have a reliable fix now which doesn't require any special command line arguments.

This fix should propagate to the ESP-IDF & Arduino esptool.py versions, soon.

Also, new development board hardware should no longer exhibit the underlying bug in the first place (provided 100nF or more of capacitance is present on the EN pin, with a 10K or higher pullup on that pin).

Please open an issue if this fix doesn't appear to fix auto-reset on your board (either reopen this issue, or if you have more specifics to provide then please open a new one instead.) Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment