
2026/10/17 22:51
Show HN: Esp32sim – ブラウザ上で ESP32 ファームウェアを実行するツール
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
esp32sim プロジェクトは、Xtensa および RISC-V アーキテクチャの両方をサポートする Rust ベースのエミュレータであり、ESP32 SoC(ESP32、S3、C3、C6)向けに設計されています。MIT ライセンスの下で公開されており、ハードウェアやクラウドへの依存関係を持たずに、実物のマスク ROM、ブートローダー、および未修改されたアプリケーションを実行します。WebAssembly を通じて Web ブラウザ上で効率的に動作するか、またはローカルインスタンスとして動作します。厳格なテスト(JTAG ロックステップおよび命令デコードの検証を含む)により、数千ステップにわたる複数のモデルにおいて発散ゼロの高い精度が確認されていますが、差分テストによって特定のエミュレータのバグが特定され、修正に役立ちました。本ツールは、トレース、ブレークポイント、可視化などの広範なデバッグ機能、仮想ネットワーキング、Cooja-NG との統合をサポートします。複雑なブートローダーや競合条件のクロスプラットフォームデバッグを可能にし、物理ハードウェアやルートアクセスを不要とする点で、IoT 開発を大幅に加速します。今後のアップデートでは、さらなるパフォーマンス向上と Waveshare の製品など追加のボードへのサポート拡大を目指しています。本文
ESP32Sim: Rust 製 ESP32 エミュレーター
ESP32Sim は、Xtensa および RISC-V の両方のアーキテクチャに対応した 4 つの ESP32 SoC(ESP32, ESP32-S3, ESP32-C3, ESP32-C6)のインストラクションレベルエミュレーター です。
- 高忠実度: リアルなマスキング ROM、リアルなブートローダー、未修改されたアプリケーションイメージを起動可能です。
- 精度: 実プロジェクトの完走を実行するに十分な精度でモデル化されています(パッチ適用済みファームウェアやスタブは使用しません)。
- 利便性: クラウド不要、アカウント不要、MIT ライセンスです。
対応 SoC
| 機能 | ESP32-S3 | ESP32-C3 | ESP32-C6 |
|---|---|---|---|
| CPU | 2 × Xtensa LX7 @ 240 MHz | 1 × RISC-V RV32IMC @ 160 MHz | 1 × RISC-V RV32IMAC @ 160 MHz |
| コマンド | | | |
| コアクレート | xtensa-lx7 | riscv-rv32 | riscv-rv32(A 拡張付き) |
| デコーダ検証 | 97 万指令、不一致 0 | 16 万指令、不一致 0 | 12 万指令、不一致 0 |
| ブートシーケンス | ROM → ブートローダー → FreeRTOS → アプリ | ROM → ブートローダー → FreeRTOS → アプリ | ROM → ブートローダー → FreeRTOS → アプリ |
| ボード / ディスプレイ | ST7735, ST7701S 480×480+タッチ、WS2812、カメラ、オーディオ | なし — コンソールのみ | ST7789 172×320(SPI+DMA)、WS2812、802.15.4 エネルギードテクト代替 |
| Wi-Fi | 仮想 AP、WPA2、DHCP/DNS/NTP、HTTPS | 同じ仮想 AP とネットワーク | 同じ仮想 AP とネットワーク(1 つのステーション) |
| 速度 | ブロックインタープリター + AArch64 JIT、約 1.5~2.4 億 insn/s | 純粋なインタープリター — では依然としてリアルタイムを超えている | 同じインタープリター |
| ブラウザ内での動作 | 可能(WebAssembly) | 可能(WebAssembly) | 可能(WebAssembly) |
注: ハードウェア比較は CI で検証されたサンプラーデコーダコーパスとエミュレーターのゴールデン出力に基づくものです。JTAG トレースやタイミングループ再同期後の比較は、サイクルごとの厳密な一致ではなく、例外ハンドリングや遅延ループの再同期を含みます。詳細は テスト範囲、CI ワークフロー を参照してください。
SoC モデルの詳細:
- C3 は S3 の UART、USB-Serial/JTAG、タイマー、GPIO などのモデルを再利用し、独自メモリーマップや PLIC などを追加しています。
- C6 も同様に S3/IP モデルを再利用し、PLIC フロントエンド、L1 キャッシュ、LP ブロックなどを追加しています。
- ブラウザでの動作: https://mikroverk.github.io/esp32sim/ で S3 上の Linux、Touch-LCD-4B パネル、ポケットタンク LLM アクアリウムなどを実演可能です。
プロジェクト構造
esp32sim/ ├── emu-core/ # バスとコアのトレイト、Trap、ClockTree、AArch64 エンコーダー(共有) ├── esp-soc/ # 各チップ向けの Machine: スケジューラー、デバイス、コンソール、Web UI など ├── esp-periph/ # チップが共有する周辺機器 IP(UART, SPI_MEM, GDMA, I2C など) │ ├── xtensa-lx7/ # S3 / C3 用 Xtensa デコーダ、インタープリター、AArch64 JIT、ディスアッセンブラ │ ├── esp32s3/ # S3 SoC: メモリーマップ、キャッシュ MMU、WiFi MAC、各種ボード定義 │ ├── riscv-rv32/ # C3/C6 用 RV32IMAC デコーダとインタープリター │ ├── esp32c3/ # C3 SoC: メモリーマップ、割り込みマトリックス、RNG │ ├── esp32c6/ # C6 SoC: MMU、PLIC、L1 キャッシュ、LP ブロック │ └── tests/ # ゴールデン出力回帰テスト ├── wasm/ # ブラウザ用 WebAssembly モジュール全体(C-ABI ラップ) ├── web/ # ブラウザ UI + wasm 用の emu.js/worker.js ├── hw/ # リアルボードに対する JTAG 差分テストスクリプト、キャプチャーデータ ├── examples/ # hello_world, waveshare-cam, wifi-station など └── tools/ # PIE テーブルジェネレーター、ベンチマークスクリプトなど
ボード設定(ESP32-S3)
SoC モデルはピンレベルイベントを出力し、
BoardModel が解釈します。
(デフォルト): Atech 14 ポートボード(ST7735, WS2812 リング, エンコーダー, ボタン)。--board atech14
: 裸モジュール — コンソールのみ。--board none
: Waveshare ESP32-S3-Touch-LCD-4B(LCD_CAM RGB, GT911 タッチ, コーデック)。LVGL でタッチ動作を実行可能。--board waveshare-lcd4b
: Waveshare ESP32-S3-Touch-AMOLED-1.8 V2。--board waveshare-amoled18-v2
: Waveshare ESP32-S3-CAM-OV5640(カメラ、スピーカー、コーデックなど)。--board waveshare-cam
ファームウェアを完走します。waveshare-autopling
ボード追加の仕組み: トレイトの実装(
gpio_changes, rmt_frame, i2c_devices, camera_frame など)により拡張されます。
関連プロジェクト:
は Pocket Tank 用 SID シンセファームウェアです(atech-firmwareにイメージを収める)。web/wasm/fw/public/
使用例
1. エミュレーターのビルド
cargo build --release
2. デモイメージの実行(S3)
web/wasm/fw/public に配置されたデモイメージ(ATECH シンセなど)を実行します。
./target/release/esp32sim \ --boot rom \ --bootloader web/wasm/fw/public/atech-bootloader.bin \ --ptable web/wasm/fw/public/atech-ptable.bin \ --app web/wasm/fw/public/atech-firmware.bin \ --script web/wasm/fw/public/atech-script1.txt \ --wav out.wav \ --tft-png tft.png \ --max-seconds 5
- ROM ELF:
を使用します。~/.espressif/tools/esp-rom-elfs/*/esp32s3_rev0_rom.elf - 入手方法: ESP-IDF がない場合は、
で ROM ファイルを配置してください。tools/fetch-demo-assets.sh --no-linux - 直接アプリ実行:
で ROM+ブートローダーをスキップ可能です。--boot app
3. ESP-IDF プロジェクトの実行(S3)
通常の IDF プロジェクト(例:
examples/hello_world、IDF 5.5 get-started)を実行します。
H=examples/hello_world/build ./target/release/esp32sim \ --board none \ --boot rom \ --console uart0 \ --bootloader $H/bootloader/bootloader.bin \ --ptable $H/partition_table/partition-table.bin \ --app $H/hello_world.bin \ --elf $H/hello_world.elf \ --elf $H/bootloader/bootloader.elf \ --max-seconds 26
- 動作: ROM バナー、ブートローダーログ、"Hello world!"、カウントダウンが表示されます。RTC ウォッチドッグにより正確なタイミングで再起動します(約リアルタイムの 30 倍速)。
- 停止オプション:
を指定すると初回リセットで停止します。--no-reboot
4. ESP32-C3 の実行
RISC-V コア上での未修改 ESP-IDF ファームウェア実行(ROM → ブートローダー → FreeRTOS)。
H=examples/hello_world-c3/build ./target/release/esp32sim-c3 \ --boot rom \ --flash-mb 4 \ --bootloader $H/bootloader/bootloader.bin \ --ptable $H/partition_table/partition-table.bin \ --app $H/hello_world.bin \ --elf $H/hello_world.elf \ --max-seconds 26
- 結果: コンソール出力が物理的な C3 モジュールと比較され、一致を確認できます。
- 注意:
はサポートされていません。--boot app
5. ESP32-C6 の実行
RV32IMAC コア向けのフロントエンドです。
H=examples/hello_world-c6/build ./target/release/esp32sim-c6 \ --boot rom \ --flash-mb 4 \ --bootloader $H/bootloader/bootloader.bin \ --ptable $H/partition_table/partition-table.bin \ --app $H/hello_world.bin \ --elf $H/hello_world.elf \ --max-seconds 27
- ボード追加:
で LCD ボードを追加可能(SPI2, GDMA, WS2812 など)。--board waveshare-c6-lcd147 - Wi-Fi:
オプションで S3 と同様に仮想 AP を作成できます。--wifi - Cojoa 連携:
オプションで Contiki-NG ノードと交換可能です。--cooja
スクリプト機能(ホスト側アクション)
ホスト側のイベント(ボタン押下、ジョグダイヤル回転など)をスクリプトで定義できます。
1.5 press btn1 150 # GPIO17 を 150ms 低レベルにする 2.2 knob cw 2 # クォーダントダイヤルを 2 ステップ右回し 3.4 press btn2 120 4.0 serial {"action":"set_note","value":"9"} # USB-CDC RX 経由で送信 5.0 stop # エミュレーション終了
Wi-Fi 機能(S3, C3, C6)
未修改の Espressif Wi-Fi ブlobs を使用した仮想アクセスポイント(AP)を起動できます。DHCP、ARP、ICMP、DNS、SNTP などのネットワークスタックが動作します。
- 接続方法:
--wifi ssid=NAME[,psk=PASS,chan=N] - 通信モード: デフォルトでは
でゲストの TCP/UDP をホストソケット経由でリレーします(--net nat
は遮断)。--net none
S3 Wi-Fi 例
エネルギーパネルのようなアプリケーションを実行し、Home Assistant と連携したり HTTPS データを取得できます。
./target/release/esp32sim \ --board waveshare-lcd4b \ --flash-mb 16 \ --psram-mb 8 \ --bootloader $P/bootloader/bootloader.bin \ --ptable $P/partition_table/partition-table.bin \ --app $P/energy_panel.bin \ --console usb \ --wifi "ssid=home,psk=secret" \ --max-seconds 45
C6 Wi-Fi
独自の MAC モデルを持ちます。802.15.4 エネルギーパネルや Wi-Fi ステーションを実行可能です。
B=examples/c6-wifi-station/build-emu ./target/release/esp32sim-c6 \ --boot rom \ --flash-mb 4 \ --board waveshare-c6-lcd147 \ --console usb \ --bootloader $B/bootloader/bootloader.bin \ --ptable $B/partition_table/partition-table.bin \ --app $B/c6_wifi_station.bin \ --elf $B/c6_wifi_station.elf \ --stub bb_init=0 \ # ベースバンドキャリブレーション(必須) --wifi ssid=esp32sim,psk=esp32sim-pass \ --max-seconds 14
C3 Wi-Fi
S3 と同様に仮想 AP を使用します。ローカルビルドなしでも
web/wasm/fw/public/ のイメージで動作可能です。
P=web/wasm/fw/public ./target/release/esp32sim-c3 \ --boot rom \ --flash-mb 4 \ --console usb \ --bootloader $P/c3-wifi-bootloader.bin \ --ptable $P/c3-wifi-ptable.bin \ --app $P/c3-wifi_station.bin \ --wifi ssid=esp32sim,psk=esp32sim-pass \ --max-seconds 14
マルチプロトコル:
は Wi-Fi と 802.15.4 の両方を走査するファームウェアです。examples/c6-radio-dashboard
ブラウザ内での動作(WebAssembly)
-
ビルド:
tools/wasm-build.sh # web/wasm/esp32sim.wasm を生成 tools/fetch-demo-assets.sh # ROM、xterm.js、Linux イメージをフェッチ(--no-linux オプションあり) -
実行方法:
python3 -m http.server -d web 8790 # http://127.0.0.1:8790/?wasm&fw=hello をブラウザで開く
Web Worker による操作:
- Web ページ内でエミュレーターを動作させます。
- ボード選択、ROM ELF ファームウェア読み込み、ボタン「Boot」押しで開始します。
- 対応機种: Chrome 上でのリアルタイム動作確認済み(NAT なし)。
- ESP32-S3: WebAssembly JIT を備える。
- Touch-LCD-4B パネル + SID プレイヤー、Atech ボード、ESP32-C3/C6 の
など。hello_world
ライブデモ: https://mikroverk.github.io/esp32sim/
- S3 上の Linux (ログイン可能)、Pocket Tank、Touch-AMOLED-1.8 の魚ゲームなどを実演しています。
デバッグオプション
| オプション | 説明 |
|---|---|
/ | コード実行の追跡開始位置を指定 |
| 指定アドレスでブレークポイント設定 |
| アドレス変更時に停止(ワード単位) |
| メモリー読み出し表示 |
| PC ヒストグラム表示 |
| 不明なレジスタの最初のアクセスをログ化 |
| 例外発生回数が N を超えた時停止 |
| ST7735 GRAM の生データを PNG に出力 |
| JIT を使用せず、純粋なインタープリターを実行(結果保証あり) |
環境変数:
ESP_EMU_DEBUG, ESP_EMU_DEBUG_WIFI[_FRAMES], ESP_EMU_DEBUG_NET, ESP_EMU_DEBUG_AES, など。
ドキュメントと貢献
- ドキュメント:
: 周辺機器やボードの追加方法。docs/adding.md
: アーキテクチャ概要。docs/architecture.md
,docs/wifi-plan.md
: ネットワーク設計と使い方。docs/networking-howto.md
- 貢献:
- コントリビュート歓迎します。
にプルリクエストのチェックリストと慣習が記述されています。CONTRIBUTING.md
- コントリビュート歓迎します。
由来とライセンス
- 開発元: ESP-IDF レジスタヘッダー、RISC-V 仕様書、C3/C6 テクニカルリファレンスマニュアル、観測されたファームウェアに基づいて作成。QEMU の命令セマンティクス確認のみ参考。
- ライセンス: esp32sim は MIT ライセンス です。著作権は Joakim Eriksson, Alice, Mattia Fiumara にあります。
サードパーティ製コードのライセンス:
- pocket-tank: MIT (ブートローダー、アプリは
下にコミット)。web/wasm/fw/public/ - MicroPython: MIT (公式イメージをフェッチ。ドライバーとフォントは st7789py 使用)。
- マスキング ROM ELFs: Apache-2.0 (espressif/esp-rom-elfs, フェッチ必要)。
- xterm.js: MIT (フェッチ必要)。
- Linux イメージ: GPL-3.0 (svermigo/Linux-on-esp32-S3, フェッチ必要)。
- ESP-IDF ADC キャリブレーションデータ: Apache-2.0。