Writes a merged image to an ESP32 over Web Serial, the way
esptool.py write_flash 0x0 image.bin does and with the same code underneath —
esptool-js, which resets the board into download mode, uploads its stub loader and verifies
what it wrote. Needs a Chromium-based browser over https:// or
http://localhost; nothing has to be done to the board first.
Firmware
A merged image starts at 0. An application on its own usually starts at 0x10000.
No image loaded.
Device
No board connected.
Idle.
Notes
The board is put into download mode for you. Starting it again afterwards is another matter:
on a board whose USB-C goes straight to the SoC — a XIAO or a QT Py, as against a devkit with a
bridge chip — nothing the host can send restarts it, so press RESET when the
write is done. Either way the port goes with the restart.
If it will not enter download mode by itself: hold BOOT, tap
RESET, release BOOT — or, on a XIAO with no reset button, hold BOOT while
plugging the cable in. Then connect and pick the port that appears.
Flashing erases only what it writes. A merged image covers bootloader, partition table and
application, so nothing of the old firmware is left behind.
What was written is read back and compared by MD5 before the board is started.
A board that stops appearing altogether after an interrupted write is not dead: its
bootloader is rejecting the half-written application and restarting faster than the host can
enumerate it. Hold BOOT, tap RESET, and plug into the machine
rather than a hub. The ROM bootloader is in silicon and cannot be overwritten.
A board running firmware that presents its own USB serial port — CircuitPython, for one —
usually cannot be reset into download mode by the host at all, and needs its buttons.