ESP32 Firmware Won’t Flash or Boot in PICSimLab? The QIO/QOUT Limit
Your ESP32 project flashes — or appears to — and then the simulated board will not boot: it loops, stalls, or shows nothing, even though the same firmware runs on a real DevKitC. With PICSimLab’s QEMU-based ESP32 boards there is one documented limitation behind most of these failures, and it is in the build settings, not in your code.
Symptoms
- Flashing with esptool seems to complete, but the ESP32-DevKitC board in PICSimLab never starts the program.
- The firmware boots on real ESP32 hardware but not in the simulator (or the reverse confusion: an old image boots, a newly built one does not).
- Boot problems started right after changing flash settings, switching board definitions, or moving from the Arduino IDE default profile to a custom partition/flash configuration.
Why it happens
PICSimLab’s ESP32 boards — only two exist, the ESP32-DevKitC and the ESP32-C3-DevKitC-02 — run on the qemu-esp32 backend. The official documentation carries an explicit warning for this backend, worth quoting in full: “Qemu ESP32 don’t support the QIO and QOUT flash modes, use only DIO or DOUT flash modes.” An image built for QIO or QOUT flash access asks the emulated flash to behave in a way QEMU does not implement, so the bootloader cannot read the application correctly and the board never reaches your code. On real hardware the same image is perfectly fine, which is exactly why this failure is so confusing.
The second part of the picture is the flashing path itself. Per the official documentation, you flash PICSimLab’s ESP32-DevKitC as if it were a real ESP32 board, using the Arduino IDE or the ESP-IDF esptool.py over the serial connection. That means the desktop serial prerequisite applies here too: the simulated serial port reaches your tools through a virtual null-modem pair (com0com on Windows, tty0tty on Linux, format 8N1) — if that path is broken, flashing fails before flash modes even matter. All files and builds are listed on our Download page.
Fix
- Set the flash mode to DIO (or DOUT). In the Arduino IDE, choose the DIO flash mode in the board settings for your ESP32 target; in ESP-IDF, set the flash mode to DIO or DOUT in the project configuration (
menuconfig→ serial flasher config). Do not use QIO or QOUT for any image you intend to run in PICSimLab. - Rebuild completely after changing the mode. A flash-mode change only takes effect in a fresh build. Clean and rebuild the project so the bootloader and application image are regenerated with the new mode — flashing only the application partition from a QIO build keeps the broken combination alive.
- Select the matching board in PICSimLab. Use ESP32-DevKitC for classic ESP32 firmware and ESP32-C3-DevKitC-02 for ESP32-C3 firmware; the two are different chips (the C3 is a RISC-V part) and their images are not interchangeable.
- Flash over the serial path, esptool-style. With the virtual serial pair in place (PICSimLab on one end, your flashing tool pointed at the other end), flash the rebuilt image with the Arduino IDE upload or the IDF/esptool.py flow, exactly as you would for a real board. If the port itself will not connect, fix that first with our virtual serial ports guide.
- Start the simulation and watch the boot. Reset the board after flashing completes. A DIO/DOUT image should now run through the bootloader into your application.
- Sanity-check with a minimal program. If a full project still will not boot, flash the smallest blink-style example built with DIO mode. If the minimal image boots, the remaining problem is inside the full project’s configuration (partition or flash settings are the first suspects); if even the minimal DIO image fails, re-check steps 3–4.
Still stuck?
For what the two QEMU ESP32 boards do and do not cover, see the ESP32-DevKitC board page. Confirm your toolchain basics against the Download page (PICSimLab itself) and the serial path in the virtual serial ports guide, and re-read the worked serial example in the PIC16F877A UART tutorial — the pair/8N1 discipline is identical. If a clean DIO build flashed over a verified serial path still will not boot on the correct ESP32 board in v0.9.3, report it — board, flash mode, and the esptool output included — on the project’s tracker: github.com/lcgamboa/picsimlab/issues.
