Repository navigation
esp32sim 0.3.0
A fourth chip, WiFi and Bluetooth on all of them, a much wider set of peripherals, and a browser
build that now runs some workloads faster than real time. 137 pull requests since 0.2.0.
Try it without installing anything: https://mikroverk.github.io/esp32sim/
The classic ESP32 (Xtensa LX6)
esp32sim now boots the original dual-core ESP32, from its own mask ROM through the real
bootloader to an unmodified app — selected with --chip esp32.
- The LX6 core, dual-core boot and a reproducible boot golden (#206)
- I2C, LEDC, SPI and RMT adapters (#207), AES, SHA and RSA register adapters (#208),
ADC, DAC and capacitive touch (#210), I2S receive into shared host audio and DMA (#212) - WiFi through the shared station link (#209), with
--wifion the classic CLI (#228), and
TX lengths independent of buffer capacity (#222) - Bluetooth glue for the shared VHCI controller (#211)
- One DRAM reach rule across the classic DMA engines (#225), cached GPIO interrupt status with
IRQs presented on events (#230), correct I2C pin routing at START (#226), an MSB-aligned
SPI1 user-command address (#227) - Boards: LilyGO TTGO T-Display and
esp32dev-loopback, with a MicroPython spot-price
demo on the T-Display (#233)
Status: early. It runs real firmware, including MicroPython, but fewer blocks are modelled than
on the S3.
WiFi on every chip
The station side of the air is now shared code, so the same virtual access point, DHCP, DNS, NTP
and NAT serve all four chips (#125, #193).
- ESP32-C6: end to end — scan, WPA2 join, DHCP lease, pings (#126), plus unstubbed
WiFi/TLS and SHA DMA (#203) - ESP32-C3: station support and a host Ethernet relay (#170)
- ESP32-S3: PHY bring-up completes without a virtual AP present (#223)
- Classic ESP32: joins through the same link (#209, #228)
- WiFi station goldens for S3, C3 and C6 run in CI (#191)
Bluetooth
- A virtual BLE controller for S3, C3 and C6 (#172)
- Opt-in C3 controller-driven advertising (#195) and controller-driven scan and connection
events (#219) — the real, unmodified controller firmware, not a stub
Peripherals
- PWM: LEDC and MCPWM outputs on S3, C3 and C6 (#167); LEDC also on the classic
- Audio: I2S RX microphone input on S3, C3 and C6 (#201), pin-routed microphone sources and
raw-count ADC streams (#202) - ADC: S3 SENS ADC1 one-shot conversions with host analog sources (#165), extended host input
and observation to S3, C3 and C6 (#177) - Camera: live host camera frames fed through the sensor configuration (#190), with host
settings preserved across a guest reboot (#198) - LEDs: GPIO WS2812 pulse decoding with opt-in instruction-sized scheduling (#204), mirrored
RMT frames and finite LED DMA output (#205),TX_STOPas a self-clearing command bit (#161) - GPIO: pin-aware bus attachment and timestamped output (#169), input feedback restored and
C6 SPI routed by pins (#200), digital I2C and timestamped GPIO on the C6 (#174), I2C, SPI2,
RMT and GPIO wired up on the C3 (#173), and a level-triggered interrupt now shows its pin in
STATUSandPCPU_INT(#247) - I2C: runtime addresses, aliases and transfer timing (#221), device removal (#175)
- UART:
RXFIFO_TOUTrises while bytes wait in the FIFO (#160); the S3 and C3 RC clock is
17.5 MHz (#182) - Crypto: C3/C6 SHA DMA (#203)
- Memory: quad PSRAM capacity reported correctly, short cycle limits honoured (#197);
C3/C6 debug areas preserved across a guest reboot (#213) - Interrupts: asserted S3 interrupts survive the APP core leaving reset (#231)
Speed
The browser build went through five rounds of measured optimisation (#85–#120, #129–#157), all
with identical guest work and console hashes between arms.
- fluidbox now runs at 1.52x real time in Chrome — 18.4% less wall time than the previous
round's base; Pocket Tank 12.4% and TinyDraw 5.4% less - The browser scheduler runs 256 instructions per busy core per round instead of 64; native
keeps 64, because Pocket Tank measured 5.4% slower at 256 there (#156, #157) - JIT work: regions that adopt the active hardware loop and follow ROM trampolines, guarded tail
copies with resume, closed leaf callees inlined with static window renaming, register-quad
window addressing, a flat dispatch record and a per-bus flash epoch - Native CLI screens are 2.75–4.64% faster than the previous round with equal work
- Correctness fixes found along the way: CPU instruction semantics and interrupt handling (#94),
a pre-existing TIMG autoreload defect, scheduler accounting (#100), AArch64 memory range
checks (#102), and retained JIT region ownership across cache reindexing (#242)
Full measurements, including everything tried and rejected, are in
docs/experiments.md.
Web and demos
- A landing page, with the emulator page as a workbench, in light and dark (#84)
- The Atech 14 workbench board is drawn with the real module artwork (#217)
- pocket-tank on the page and on Pages (#80, #81), demos from a checkout with per-demo page text
and panel rotation (#79) - A link-preview card, emulated time while loading, split escape sequences in the console (#181)
- Landing-page layout: hero caption, demo thumbnails, the classic ESP32 in the demo list (#237)
Docs and infrastructure
CONTRIBUTING.mdand the checks to run before a pull request (#176, #178)- The mask ROM ELFs are pinned by release and SHA-256, and cached, in CI (#184)
- The README is now a short overview (#249); the experiment history is one catalogue with
evidence (#115) - Release automation: pushing a
v*tag builds macOS arm64, Linux x86_64 and Linux arm64
tarballs, writesSHA256SUMS.txtand attaches them to the tag's release esp32sim --versionreports the release, from each of the three binaries
Install
Download the tarball for your platform below and verify it against
esp32sim-0.3.0-SHA256SUMS.txt. Each one holds esp32sim, esp32sim-c3, esp32sim-c6,
LICENSE and README.md. The classic ESP32 runs through the main binary with --chip esp32.
The mask ROMs are not redistributed; fetch them with tools/fetch-demo-assets.sh --no-linux.
Thanks
@aliceisjustplaying for the performance rounds,
@mfiumara for the classic ESP32, the peripheral models and the
BLE controller, @makoshan for the UART, RMT and ADC fixes, and
@Xorlev for the GPIO interrupt-status fix.