6.4 KiB
| layout | title | date | categories | tags | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| post | Recovering an ESP32 DevKit from Reverse Polarity on the 3V3 Pin | 2026-03-07 |
|
|
Writeup generated with AI
What started as an accidental reverse polarity event on an ESP32-U DevKit board turned into a surprisingly successful recovery. This post documents the full diagnostic process and the steps that ultimately brought the board back to life running Tasmota.
The Incident
Reverse polarity was applied directly to the 3V3 pin of an ESP32-U DevKit board. This is arguably worse than reversing the 5V input, because it bypasses the onboard LDO regulator entirely — the reversed voltage goes straight onto the 3.3V rail feeding the ESP32 and all other components directly.
Initial Symptoms
- The USB-to-UART bridge was alive and enumerating correctly (expected, as it is powered from the 5V USB rail, upstream of the LDO)
- The board was unresponsive to flashing attempts
- 0V measured on the 3V3 pin while powered from USB
Diagnosis
Ruling out a shorted rail
Measuring resistance between GND and 3V3 with the board unpowered showed 750Ω — a healthy value indicating no shorted decoupling capacitors or blown ESD diodes on the rail. This was an encouraging sign pointing to the LDO as the failed component rather than the ESP32 itself.
LDO thermal shutdown
The AMS1117-3.3 LDO on ESP32 DevKit boards includes built-in thermal shutdown protection. The reverse polarity event likely caused excessive current through the LDO, triggering thermal shutdown. After sufficient cooling time during the resistance measurements, the LDO recovered on its own and 3V3 was restored — consistent with thermal shutdown behaviour rather than permanent damage.
Flash chip diagnosis
With power restored, flashing still failed with:
Warning: Failed to communicate with the flash chip, read/write operations will fail.
Using esptool with the --no-stub flag also failed, and flash-id returned 0xff/0xffff — indicating no response on the SPI bus from the ROM bootloader.
However, running flash-id with the stub flasher returned a valid response:
Manufacturer: 68
Device: 4016
Detected flash size: 4MB
Manufacturer 0x68 is Boya Micro (BY25Q32) — a legitimate, working flash chip. The discrepancy between ROM bootloader and stub was due to different SPI bus initialisation methods; the stub's optimised driver worked where the ROM's did not.
Recovery Steps
1. Erasing the flash in chunks
A full erase-flash operation failed mid-way with:
A fatal error occurred: Packet content transfer stopped (received 9 bytes).
This was consistent with marginal LDO stability under sustained load. Erasing in smaller regions worked reliably:
esptool erase-region 0x3D0000 0x20000
2. Reflashing Tasmota
Direct reflash via esptool succeeded:
esptool --baud 115200 write-flash 0x0 tasmota32-FR.bin
3. Diagnosing the safeboot loop
After reflashing, the device booted but the web interface was unresponsive (IP pinged but empty HTTP answer from http://192.168.4.1/). Serial console output revealed:
Project tasmota - Tasmota Version 15.3.0(release-safeboot)-3.3.7(2026-02-19T13:53:54)
WARNING This version does not support persistent settings
The erase operations had wiped the OTA selection flag at 0xe000, causing the bootloader to fall back to the safeboot partition instead of the main firmware.
The safeboot firmware is a special trimmed down version of Tasmota used during OTA upgrades. It specifically does not include the initial configuration web page.
4. Full PlatformIO reflash
A complete PlatformIO rebuild and reflash restored all partition components including the OTA flag:
| Offset | File |
|---|---|
0x1000 |
bootloader.bin |
0x8000 |
partitions.bin |
0xe000 |
boot_app0.bin ← OTA selection flag |
0x10000 |
tasmota32-safeboot.bin |
0xe0000 |
firmware.bin ← main firmware |
This restored normal boot into the full tasmota32-FR firmware.
How the Tasmota32 Safeboot System Works
The Tasmota32 dual-partition safeboot architecture is worth understanding:
- On every normal boot, the OTA flag at
0xe000points the bootloader to the main firmware at0xe0000 - If the device reboots 4 times in quick succession (crash loop), Tasmota automatically switches the OTA flag to the safeboot partition as a recovery mechanism
- Safeboot can also be triggered manually via
Restart 99from the Tasmota console - From the safeboot web interface, you can OTA flash a new main firmware, which resets the OTA flag back to normal
The safeboot partition is intentionally minimal (~300–400KB) — it includes only a web server, OTA flash capability, basic WiFi AP, and a stripped console. It has no persistent settings, no MQTT, and most Tasmota commands are unavailable.
Outcome
The board made a full recovery with no permanent damage:
- ESP32 SoC: intact
- Flash chip: intact
- LDO: recovered from thermal shutdown
- Tasmota: running normally
Lessons Learned
- Reverse polarity on the 3V3 pin is more dangerous than on the 5V pin as it bypasses the LDO entirely
- The AMS1117 thermal shutdown can mimic permanent failure but recover after cooling
- Always use the stub flasher (
esptoolwithout--no-stub) for flash communication — the ROM bootloader SPI initialisation can fail where the stub succeeds - Partial flash erase operations can corrupt the OTA selection flag, causing unexpected safeboot behaviour
- A full PlatformIO reflash is the safest way to restore a complete and correct partition layout
- Consider adding reverse polarity protection (Schottky diode or P-channel MOSFET) on power inputs in future designs
Alternate exit path from Safeboot
I could have reset the safeboot flag using:
esptool write-flash 0xe000 ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin
This just rewrites the OTA selection flag directly, telling the bootloader to boot the main firmware partition — without touching anything else. A full reflash would not have been necessary. From within the safeboot console, there isn't a direct command to flip the flag — that's intentional, since the whole point of safeboot is to force you through the OTA web interface to upload known-good firmware before returning to normal boot.