ESP32 DevkitC only resettable via ESP-Prog (JTAG)

I am hoping someone here may have a clue…

I got one ESP32 DevkitC V4 here that refuses to boot on RESET(EN) pressed. All that happens is a boot loop:

flash read err, 1000
ets_main.c 371
ets Jun  8 2016 00:22:57

... (repeating without end)

But when I press RESET on the attached ESP-prog JTAG module, the ESP32 does cleanly reset and boot.
I seem to have sorted out all burnt fuses/power supply/wiring/misused PIN issues I read about, so I am at a loss here.
I would try to flash the boot loader, but am having problems to get the matching one. The Espressif servers are providing the AT package only and I do not know if that will fit. Same applies to the NodeMCU flasher found in the net.

Any ideas, anyone?

Then I wouldn’t have anything else to add, this is also what I find in Nodemcu-32s (aka. ESP-WROOM-32) crash: flash read err, 1000 ets_main.c 371 · Issue #2202 · letscontrolit/ESPEasy · GitHub and flash read err, 1000 (IDFGH-807) · Issue #113 · espressif/esp-idf · GitHub.

Weird that a normal reset fixes it though. Does pressing reset on the dev-board itself lead to the same thing? After the firmware is programmed and you remove the espprog cable connections entirely, does the board boot normally? (This would immediately indicate that it’s a problem with the bootstrapping GPIO pins used for selecting the flash voltage of 1.8V or 3.3V).

Could also be a weird timing thing since in the issue I’ve read that some flash chips need longer for initialization than expected. If you reset in after some initialize-command was issued, the bootloader restarts and gives the flash chip more time to execute the previously issued command, maybe. But then it also shouldn’t make a difference which reset button is pressed…

Otherwise I’d suggest to open a new issue on Issues · espressif/esp-idf · GitHub to get the expert’s opinion on this.

You made my day - sort of :grin:

Removing the ESP-prog wiring actually brought the ESP32 back to normal, it reacts on RESET now as supposed to.

But the problem now is a different one: The JTAG TDI line is on GPIO12 unfortunately, so there should be a way to tell the ESP-prog to set the correct flash voltage upon RESET?

By the way, the links to Github you gave are most useful - I learned that the boot loader is in the AT packet from Espressif and may be flashed separately. I was chasing this information for days, but somehow missed the page you found.

Thank you so much again!

The only thing I know in regards to that is that it can be controlled during flashing with the openocd config. The esp32.cfg file checks

if { [info exists ESP32_FLASH_VOLTAGE] } {
} else {
$_TARGETNAME_0 esp32 flashbootstrap $_FLASH_VOLTAGE

That value is e.g. set by other high-level config files, e.g. board/esp32-wrover-kit-3.3v.cfg

# Source the JTAG interface configuration file
source [find interface/ftdi/esp32_devkitj_v1.cfg]
# Source the ESP32 configuration file
source [find target/esp32.cfg]

so it may be the case that when you flash the ESP32 with a certain (wrong) config file, then openocd will tell the FTDI chip to output a high or low voltage on that bootstrapping pin when the reset-for-flash is done. No idea if the FTDI holds the correct GPIO value afterwards, too.

Since you can press the hardware reset button at anytime the FTDI chip shouldn’t be able to notice it (or it would suprise me) and thus it shouldn’t be able to react specifically to it, too.

You should be able to change the used cfg file that is originally in the board

with some board_debug.openocd_board = xyz.cfg line in the platformio.ini or maybe add upload_flags = -c "set ESP32_FLASH_VOLTAGE 3.3". The “Verbose Upload” will show you the true openocd invocation then for adjustment.

Actually I found a cfg file exactly named for my board:

  "build": {
      "ldscript": "esp32_out.ld"
    "core": "esp32",
    "extra_flags": "-DARDUINO_ESP32_DEV",
    "f_cpu": "240000000L",
    "f_flash": "40000000L",
    "flash_mode": "dio",
    "mcu": "esp32",
    "variant": "esp32"
  "connectivity": [
  "debug": {
    "openocd_board": "esp-wroom-32.cfg"
  "frameworks": [
  "name": "AZ-Delivery ESP-32 Dev Kit C V4",
  "upload": {
    "flash_size": "4MB",
    "maximum_ram_size": 532480,
    "maximum_size": 16777216,
    "require_upload_port": true,
    "speed": 460800
  "url": "",
  "vendor": "AZ-Delivery"

The referred esp-wroom-32.cfg for openOCD has

echo "WARNING: boards/esp-wroom-32.cfg is deprecated, and may be removed in a future release."
source [find target/esp32.cfg]

So it looks like the voltage is already defined as 3.3V.

If nothing else is overwritten for the board or upload command in the platformio.ini, that should be correct. The ESP-IDF people should know more about the openocd / FTDI / reset behavior.

I was hinted to to have a fixed flash voltage set forever, but I am shying away from that for now :wink: