Arduino's old esptool works (with DTR/RTS), IDF v6.0.1 esptool fails — plus RS-485 issue and broken IDF environment
Posted: Mon May 25, 2026 7:57 am
Arduino's old esptool works (with DTR/RTS), IDF v6.0.1 esptool fails — plus RS-485 issue and broken IDF environment
Hardware & Software Context
My ESP32 is stuck in ota_1 with a broken firmware that fails HTTPS OTA (hardcoded https://... URL, cert bundle enabled) and then loops forever.
I need to erase the otadata partition (0xe000, 8KB) so that the bootloader falls back to ota_0, which contains a working Arduino firmware that accepts OTA over WiFi.
Alternatively, flashing a corrected firmware via serial would also solve the problem.
Key Observations — Three Different Behaviors
Scenario A: USB‑UART with auto‑reset circuit (DTR/RTS) + Arduino's old esptool v3.0‑dev
Result: SUCCESS
I soldered an auto‑reset circuit (DTR → EN, RTS → GPIO0 via capacitor) onto my custom PCB. With this circuit connected, Arduino's old esptool successfully detects the chip and flashes firmware.
Command:
Output:
Conclusion: With DTR/RTS, the ROM bootloader, auto‑reset, and old esptool all work correctly.
Scenario B: RS‑485 link (MAX485 chip, TX/RX only, NO DTR/RTS) + Arduino's old esptool v3.0‑dev
Result: FAILS — serial port error
When I disconnect the auto‑reset circuit and connect via USB‑to‑RS‑485 adapter → MAX485 → ESP32 (TX/RX/GND only), even the Arduino esptool fails:
Error:
Scenario C: USB‑UART with the SAME auto‑reset circuit (DTR/RTS) + IDF v6.0.1 esptool (v5.3.dev3)
Result: FAILS — No serial data received
Using the exact same hardware as A (the auto‑reset circuit that worked perfectly for Arduino), the new esptool always fails:
Command:
Error: No serial data received or The chip stopped responding.
I have tried many combinations with the same result:
I also opened a raw serial terminal (115200‑8N1) and manually typed the exact SYNC frame from the Espressif Serial Protocol documentation, but again, after the chip prints waiting for download, it never replies to the manually sent SYNC frame. No SLIP packet, not even an error.
This is the core mystery: The ROM bootloader is clearly functional, the auto‑reset circuit is functional, and the USB‑UART adapter is functional — but the new tool cannot talk to the chip, while the old tool can. Why does the new esptool fail to get any response when the old one succeeds on the same hardware? Could there be a timing or electrical difference in how esptool v3 vs v5 asserts the TX line, or a hidden requirement (like a break condition or line‑idle state) before the ROM bootloader starts listening?
I have a multimeter available and am willing to take measurements on my custom PCB under guidance from the forum.
Second Problem: IDF v6.0.1 Environment Completely Broken After Restart
After closing PowerShell, I can no longer start an IDF v6.0.1 terminal. This prevents me from using esptool or idf.py at all.
Symptoms
The generated script uses $env:'_IDF.PY_COMPLETE'. PowerShell 7.5+ cannot parse the dot inside single quotes after $env:. The fix is ${env:_IDF.PY_COMPLETE}.
Environment Details
Hardware & Software Context
- Chip: ESP32-D0WD-V3 (revision 3), custom self‑designed PCB
- PC connection methods:
- USB‑to‑UART adapter with auto‑reset circuit (DTR/RTS connected to EN/GPIO0)
- USB‑to‑RS‑485 adapter → MAX485 chip → ESP32 (TX/RX/GND only, no DTR/RTS)
- OS: Windows 10 (also tried on Windows 11), PowerShell 7.5.5
- Arduino IDE: uses bundled esptool v3.0‑dev (from esp32 hardware package)
- ESP-IDF: v6.0.1, installed offline via EIM (Espressif IDE Manager)
- IDF path: D:\AllSoftware\esp_idfv6.0.1_anzhuangweizhi\v6.0.1\esp-idf
- Tools path: C:\Espressif\tools
- Test equipment available: digital multimeter
My ESP32 is stuck in ota_1 with a broken firmware that fails HTTPS OTA (hardcoded https://... URL, cert bundle enabled) and then loops forever.
I need to erase the otadata partition (0xe000, 8KB) so that the bootloader falls back to ota_0, which contains a working Arduino firmware that accepts OTA over WiFi.
Alternatively, flashing a corrected firmware via serial would also solve the problem.
Key Observations — Three Different Behaviors
Scenario A: USB‑UART with auto‑reset circuit (DTR/RTS) + Arduino's old esptool v3.0‑dev
Result: SUCCESS
I soldered an auto‑reset circuit (DTR → EN, RTS → GPIO0 via capacitor) onto my custom PCB. With this circuit connected, Arduino's old esptool successfully detects the chip and flashes firmware.
Command:
Code: Select all
& $env:USERPROFILE\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\3.0.0\esptool.exe --chip esp32 write_flash --flash_mode dio --flash_freq 80m --flash_size 4MB 0x10000 "D:\Temp\arduino_build_875046\sketch.bin"
While the old esptool was running, I monitored the serial lines. The ROM bootloader's waiting for download prompt appeared, followed by a series of SLIP packets. I could see the SYNC frame being sent and the chip responding. Notably, I captured the GET_SECURITY_INFO command (0x14) being sent and acknowledged multiple times by the chip, appearing as the raw hex sequence C0 00 14 00 00 00 00 00 00 C0 in the serial monitor:Serial port COM5
Connecting.....
Chip is ESP32-D0WD-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 14:2b:2f:d8:ef:ac
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Compressed 1484048 bytes to 890752...
Wrote 1484048 bytes (890752 compressed) at 0x00010000 in 78.9 seconds (effective 150.5 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
Code: Select all
C0 00 14 00 00 00 00 00 00 C0
C0 00 14 00 00 00 00 00 00 C0
C0 00 14 00 00 00 00 00 00 C0
... (repeated successfully)
Scenario B: RS‑485 link (MAX485 chip, TX/RX only, NO DTR/RTS) + Arduino's old esptool v3.0‑dev
Result: FAILS — serial port error
When I disconnect the auto‑reset circuit and connect via USB‑to‑RS‑485 adapter → MAX485 → ESP32 (TX/RX/GND only), even the Arduino esptool fails:
Error:
Note: This "port does not exist" error is expected behavior — the RS‑485 link is a separate hardware design issue, likely involving manual RX/TX enable control and/or proper termination. I understand this.esptool.py v3.0-dev
Serial port COM5
Traceback (most recent call last):
File "esptool.py", line 3682, in <module>
...
serial.serialutil.SerialException: could not open port 'COM5': WindowsError(2, '\xcf\xb5\xcd\xb3\xd5\xd2\xb2\xbb\xb5\xbd\xd6\xb8\xb6\xa8\xb5\xc4\xce\xc4\xbc\xfe\xa1\xa3')
Failed to execute script esptool
The selected serial port does not exist or the board is not connected
Scenario C: USB‑UART with the SAME auto‑reset circuit (DTR/RTS) + IDF v6.0.1 esptool (v5.3.dev3)
Result: FAILS — No serial data received
Using the exact same hardware as A (the auto‑reset circuit that worked perfectly for Arduino), the new esptool always fails:
Command:
Code: Select all
python -m esptool --port COM5 --baud 115200 erase_region 0xe000 0x2000
I have tried many combinations with the same result:
- --before default_reset
- --before no-reset
- --before no-reset-no-sync
- --no-stub (combined with the above)
- --connect-attempts 15
- --trace --verbose
Code: Select all
TRACE +0.000 --- Cmd GET_SECURITY_INFO (0x14) | data_len 0 | wait_response 1 | timeout 3.000 | data ---
TRACE +0.000 Write 10 bytes: c00014000000000000c0
TRACE +3.011 No serial data received.
This is the core mystery: The ROM bootloader is clearly functional, the auto‑reset circuit is functional, and the USB‑UART adapter is functional — but the new tool cannot talk to the chip, while the old tool can. Why does the new esptool fail to get any response when the old one succeeds on the same hardware? Could there be a timing or electrical difference in how esptool v3 vs v5 asserts the TX line, or a hidden requirement (like a break condition or line‑idle state) before the ROM bootloader starts listening?
I have a multimeter available and am willing to take measurements on my custom PCB under guidance from the forum.
Second Problem: IDF v6.0.1 Environment Completely Broken After Restart
After closing PowerShell, I can no longer start an IDF v6.0.1 terminal. This prevents me from using esptool or idf.py at all.
Symptoms
- Double‑clicking the desktop shortcut IDF_v6.0.1_PowerShell opens a PowerShell window that immediately shows red errors and closes.
- Running C:\Espressif\tools\Microsoft.v6.0.1.PowerShell_profile.ps1 manually produces:
Code: Select all
ParserError: C:\Espressif\tools\Microsoft.v6.0.1.PowerShell_profile.ps1:82 Line | 82 | $previous = $env:'_IDF.PY_COMPLETE' | ~~~~~ | Variable reference is not valid. ':' was not followed by a valid variable | name character. Consider using ${} to delimit the name. - All export/install scripts flash a window and exit immediately: export.bat, export.ps1, install.bat, install.ps1
The generated script uses $env:'_IDF.PY_COMPLETE'. PowerShell 7.5+ cannot parse the dot inside single quotes after $env:. The fix is ${env:_IDF.PY_COMPLETE}.
Environment Details
- ESP-IDF version: v6.0.1
- EIM version: v0.12.5
- OS: Windows 10 / 11
- PowerShell version: v7.5.5
- Script path: C:\Espressif\tools\Microsoft.v6.0.1.PowerShell_profile.ps1
- Why does the new esptool (v5.3) fail to get any response from the ROM bootloader on the same hardware where the old esptool (v3.0) succeeds?
Are there known differences in how esptool v3 and v5 drive the serial lines, handle timing, or perform the pre‑connection setup that could cause this? Could this be a Windows driver interaction specific to newer esptool versions? - Is there a workaround to erase the otadata partition without a working IDF environment?
For example, can I use the old Arduino esptool to write a dummy 8KB 0xFF file at 0xe000 to simulate an erase? Is that safe? - How can I repair the broken IDF v6.0.1 environment?
Is the PowerShell profile syntax error a known issue with EIM v0.12.5 and PowerShell 7.5+? Can I safely edit the script to use ${env:_IDF.PY_COMPLETE}, or should I downgrade PowerShell?