Show HN: Esp32sim – Run ESP32 firmware in the browser
Introducing esp32sim: Browser-Based ESP32 Firmware Execution
The Core Promise: Execute genuine firmware either on your local machine or directly within a web browser. There is
no need for physical hardware, no cloud dependencies, and absolutely no subscription fees.
🚀 Overview
esp32sim is an open-source emulator developed in Rust that provides instruction-level emulation for four distinct Espressif SoCs. It supports both of the primary CPU architectures used by Espressif: Xtensa and RISC-V.
The emulator is designed for high fidelity. It boots the actual mask ROM and the authentic 2nd-stage bootloader. Because it uses unmodified application images, there are no patched binaries or stubs required. The SoC modeling is comprehensive enough to allow full end-to-end project execution.
For the legacy ESP32, the emulator boots the ECO3 ROM using dual LX6 cores, including support for timers, UART, and GPIO. Additionally, using the --board ttgo-tdisplay flag enables support for the LilyGO TTGO T-Display's buttons and ST7789 screen.
📊 Technical Comparison of Supported Chips
| Feature | ESP32-S3 | ESP32-C3 | ESP32-C6 |
|---|---|---|---|
| CPU | Xtensa LX7 @ | RISC-V RV32IMC @ | RISC-V RV32IMAC @ |
| CLI Command | esp32sim | esp32sim-c3 | esp32sim-c6 |
| Core Crate | xtensa-lx7 | riscv-rv32 | riscv-rv32 (+ A extension) |
| Instruction Accuracy | 977k checked, 0 errors | 161k checked, 0 errors | 126k checked, 0 errors |
| Boot Sequence | ROM Bootloader FreeRTOS App | ROM Bootloader FreeRTOS App | ROM Bootloader FreeRTOS App |
| Peripherals/Displays | ST7735, ST7701S ( + touch), WS2812, Audio, Camera | Console only | ST7789 ( SPI+DMA), WS2812, 802.15.4 energy-detect |
| Networking | Virtual AP, WPA2, DHCP/DNS/NTP, NAT, HTTPS | Virtual AP, WPA2, DHCP, NAT (1 station) | Virtual AP, WPA2, DHCP, NAT (1 station, legacy rates) |
| Execution Speed | Block interpreter + AArch64 JIT () | Plain interpreter (faster than real-time for hello_world) | Plain interpreter |
| Wasm Support | Yes | Yes | Yes |
| Hardware Validation | JTAG trace (resynced timing loops) | Console diff (205/208 lines match) | Console diff (203/204 lines match) |
| Development Status | Mature | Draft | Draft |
🛠️ Validation and Testing
The project utilizes a rigorous testing pipeline:
- CI Integration: Runs sampled decoder corpora and "golden" emulator outputs.
- Hardware Comparison: Uses JTAG traces and console diffs. Note that hardware traces are normalized to ignore window exceptions and resynchronize delay loops, meaning it is not a cycle-by-cycle identical match.
- Verification Tools: Includes a dedicated hardware comparator, Xtensa decoder tests, and a specific CI workflow.
🏗️ System Architecture
The emulator is modular, sharing most SoC logic across different chips. For instance, the C3 and C6 reuse the S3's models for GPIO, UART, GDMA, and the SPI flash controller.
Component Breakdown
emu-core/: Contains the fundamentalBusandCoretraits,ClockTree,Traphandling, and the AArch64 encoder.esp-soc/: Manages theMachineandSoctraits. This handles the scheduler, web UI, console, and the virtual WiFi/NAT networking stack.esp-periph/: The library of shared peripheral IP (e.g.,I2C,RMT,I2S,UART,SPI_MEM).xtensa-lx7/: The heavy lifter for S3, featuring:- A basic-block interpreter and AArch64 JIT.
- Support for FPU, MAC16, and PIE SIMD.
- An
objdump-compatible disassembler.
esp32s3/: Specifics for the S3 SoC, including the memory map, cache MMU, and board configs (e.g.,waveshare-lcd4b).riscv-rv32/: The RV32IMAC decoder and interpreter used by C3 and C6.esp32c3/&esp32c6/: Chip-specific memory maps and unique blocks (like the C6's PLIC and LP blocks).
💻 Usage and Demos
You can run the emulator via the command line:
# Run a specific chip
esp32sim --chip esp32s3 <firmware_image>
Try it in your browser:
Visit mikroverk.github.io/esp32sim/ to see:
- Linux running on the S3
- The SID player on the Touch-LCD-4B panel
- The "pocket-tank" LLM aquarium
- C3 and C6 demonstration projects
Current Project Status
- ESP32-S3: Mature
- ESP32-C3: Draft (see
docs/esp32c3.md) - ESP32-C6: Draft (see
docs/esp32c6.md)