Windows11のWSL2を使う機会が増えたので、自分への覚書として関係するリンクと内容を簡単にまとめます。
開発環境
- Windows11: Pro 24H2
- WSL: v2.3.26.0
- Ubuntu: 22.04.5 LTS
Linuxでのツールチェーンのセットアップ
まずは、上記の手順に従い、ESP-IDFのツールチェーンをセットアップしていきます。
1. 必要なパッケージを導入する
ESP-IDFを使用してコンパイルするために、次のコマンドでパッケージを導入します。
$ sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
2. ESP-IDFを取得する
ESP-IDFをインストールするディレクトリに移動し、次の手順でリポジトリをクローンします。
以下の例の設定
- インストールディレクトリ: ~/esp/
- バージョン: v5.4 (2025/01/04時点の最新版)
ESP-IDFのバージョンについてはこちらを参照してください。
$ mkdir -p ~/esp
$ cd ~/esp
$ git clone -b v5.4 --recursive https://github.com/espressif/esp-idf.git
ESP-IDFは ~/esp/esp-idf にダウンロードされます。
3. 必要なツールを設定する
ESP32をサポートするプロジェクトでは、ESP-IDFの他に、コンパイラ、デバッガー、Python パッケージなど、ESP-IDFで使用されるツールもインストールする必要があります。
以下のコマンドを参考にターゲットとするチップをリストしてスクリプトを実行します。
必要なツールはLinux 上のユーザーホームディレクトリ( ~/.espressif )にインストールされます。
$ cd ~/esp/esp-idf
$ ./install.sh esp32,esp32s2
サポートされているすべてのターゲット用のツールをインストールするには、次のコマンドを実行してください。
$ cd ~/esp/esp-idf
$ ./install.sh all
4. 環境変数を設定する
ツールをコマンドラインから使用するためには、いくつかの環境変数を設定する必要があります。ESP-IDFには、それを実行するスクリプトが用意されていますので、次のコマンドを実行します。
$ . ~/esp/esp-idf/export.sh
※先頭のドットとパスの間のスペースに注意してください。
以下のメッセージが表示されたら、設定完了です。
$ . ~/esp/esp-idf/export.sh
Checking "python3" ...
Python 3.10.12
"python3" has been detected
Activating ESP-IDF 5.4
* Checking python version ... 3.10.12
* Checking python dependencies ... OK
* Deactivating the current ESP-IDF environment (if any) ... OK
* Establishing a new ESP-IDF environment ... OK
* Identifying shell ... bash
* Detecting outdated tools in system ... OK - no outdated tools found
* Shell completion ... Autocompletion code generated
Done! You can now compile ESP-IDF projects.
Go to the project directory and run:
idf.py build
サンプルプロジェクトで動作確認をする
ESP-IDFのプロジェクトを開始する準備が完了しましたので、実際にサンプルプロジェクトをビルドしてターゲット上で実行してみます。
1. サンプルプロジェクトをコピーする
ESP-IDFのexamplesディレクトリからhello_worldプロジェクトをコピーして実行してみます。
get-started/hello_world を~/espにコピーします。
$ cd ~/esp
$ cp -r ~/esp/esp-idf/examples/get-started/hello_world ./
2. WSL2でターゲットボードを接続する
次に、ターゲットボードをコンピューターに接続し、どのシリアルポートでボードが認識されているかを確認します。
USBデバイスの接続のサポートはWSL2ではネイティブに使用できないので、オープンソースの usbipd-winプロジェクトをインストールする必要があります。
以下の記事を参考に、USBに接続されたデバイスをWSL2上のUbuntuで認識させます。
WSLでUSB認識をしよう
USB デバイスを接続する
まずPowerShellを開きWindows11にusbipdをインストールします。
> winget install --interactive --exact dorssel.usbipd-win
次にWSL2上のUbuntuでusbipdの設定をします。Linuxのカーネルバージョンを確認します。
$ uname -r
5.15.167.4-microsoft-standard-WSL2
筆者の環境では5.15ですので、linux-tools-5.15のインストール可能なバージョンを確認します。
$ sudo apt update
$ sudo apt upgrade
$ sudo apt-cache search linux-tools-5.15.*-generic
~省略~
linux-tools-5.15.0-125-generic - Linux kernel version specific tools for version 5.15.0-125
linux-tools-5.15.0-126-generic - Linux kernel version specific tools for version 5.15.0-126
linux-tools-5.15.0-127-generic - Linux kernel version specific tools for version 5.15.0-127
linux-tools-5.15.0-128-generic - Linux kernel version specific tools for version 5.15.0-128
linux-tools-5.15.0-130-generic - Linux kernel version specific tools for version 5.15.0-130
~省略~
今回は一番新しい linux-tools-5.15.0-130-generic をインストールします。
$ sudo apt install linux-tools-5.15.0-130-generic hwdata
$ sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/5.15.0-130-generic/usbip 20
次にPowerShellからUSBデバイスの接続をします。PowerShellを管理者モードで開き、現在接続されているUSBデバイスを確認します。
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
1-5 303a:1001 USB シリアル デバイス (COM10), USB JTAG/serial debug unit Not shared
今回はWindows11のCOM10で認識されていますので、コマンド usbipd bind を使ってデバイスを共有し、WSLに接続できるようにします。
以下のコマンドを実行した後、もう一度 usbipd list でデバイスが共有されていることを確認します。
> usbipd bind --busid 1-5
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
1-5 303a:1001 USB シリアル デバイス (COM10), USB JTAG/serial debug unit Shared
このデバイスのBUSIDである1-5をWSLに認識させます。
> usbipd attach --wsl --busid 1-5
usbipd: info: Using WSL distribution 'Ubuntu-22.04' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Using IP address 172.19.48.1 to reach the host.
Ubuntuで接続された USB デバイスの一覧を表示し、認識されたポート名を確認します。
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 303a:1001 Espressif USB JTAG/serial debug unit
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ dmesg | grep tty
[ 7830.505535] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
先ほど接続したデバイスが表示され、Ubuntu上で ttyACM0 として認識されているのがわかりました。
これにアクセス権限を与えておきます。
$ sudo chmod 777 /dev/ttyACM0
なお、WSLでデバイスを使い終わったら、USBデバイスの接続を物理的に解除するか、PowerShellから次のコマンドを実行して切断します。
usbipd detach --busid <busid>
3. プロジェクトを構成する
hello_worldディレクトリに移動し ESP32S3 をターゲットとして設定し、プロジェクト構成ユーティリティ(menuconfig)を実行します。
$ cd ~/esp/hello_world
$ idf.py set-target esp32s3
Adding "set-target"'s dependency "fullclean" to list of commands with default set of options.
Executing action: fullclean
Build directory '/home/***/esp/hello_world/build' not found. Nothing to clean.
Executing action: set-target
Set Target to: esp32s3, new sdkconfig will be created.
~中略~
-- Configuring done
-- Generating done
-- Build files have been written to: /home/***/esp/hello_world/build
$ idf.py menuconfig
この手順が正しく実行された場合、次のメニューが表示されます。
このメニューを使用して、Wi-Fi ネットワーク名とパスワード、プロセッサ速度、フラッシュの容量などのプロジェクト固有の変数を設定します。今回のプロジェクト(hello_world)はデフォルト構成で実行しますので、デフォルトのまま[Q]で終了します。
4. プロジェクトをビルドする
次のコマンドを実行してプロジェクトをビルドします。このコマンドは、アプリケーションとすべてのESP-IDFコンポーネントをコンパイルし、ブートローダ、パーティション テーブル、およびアプリケーションバイナリを生成します。
$ idf.py build
Executing action: all (aliases: build)
Running ninja in directory /home/***/esp/hello_world/build
Executing "ninja all"...
[0/1] Re-running CMake...
-- git rev-parse returned 'fatal: not a git repository (or any of the parent directories): .git'
-- Could not use 'git describe' to determine PROJECT_VER.
-- Building ESP-IDF components for target esp32s3
~中略~
[1033/1034] Generating binary image from built executable
esptool.py v4.8.1
Creating esp32s3 image...
Merged 2 ELF sections
Successfully created esp32s3 image.
Generated /home/tomorrow56/esp/hello_world/build/hello_world.bin
[1034/1034] cd /home/tomorrow56/esp/hello_world/build/esp-idf/espt...n-table.bin /home/tomorrow56/esp/hello_world/build/hello_world.bin
hello_world.bin binary size 0x327f0 bytes. Smallest app partition is 0x100000 bytes. 0xcd810 bytes (80%) free.
Project build complete. To flash, run:
idf.py flash
or
idf.py -p PORT flash
or
python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 2MB --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/hello_world.bin
or from the "/home/tomorrow56/esp/hello_world/build" directory
python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args"
エラーがなければ、ファームウェアのバイナリ(.bin)ファイルが生成されてビルドが終了します。
5. デバイスにフラッシュする
ESP32S3用にビルドしたバイナリを次のコマンドを実行してデバイスのポート(/dev/ttyACM0)に書き込みます。
$ idf.py -p /dev/ttyACM0 flash
Executing action: flash
Running ninja in directory /home/tomorrow56/esp/hello_world/build
Executing "ninja flash"...
~中略~
Compressed 3072 bytes to 103...
Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.0 seconds (effective 559.3 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
Done
終了までに問題がなければ、ボードが再起動し hello_world アプリケーションが起動します。
6. シリアル出力をモニターする
hello_world が実際に実行されているかどうかを確認するために、IDFモニターアプリケーションを起動します。
$ idf.py -p /dev/ttyACM0 monitor
Executing action: monitor
Running idf_monitor in directory /home/tomorrow56/esp/hello_world
Executing "/home/tomorrow56/.espressif/python_env/idf5.4_py3.10_env/bin/python /home/tomorrow56/esp/esp-idf/tools/idf_monitor.py -p /dev/ttyACM0 -b 115200 --toolchain-prefix xtensa-esp32s3-elf- --target esp32s3 --revision 0 /home/tomorrow56/esp/hello_world/build/hello_world.elf -m '/home/tomorrow56/.espressif/python_env/idf5.4_py3.10_env/bin/python' '/home/tomorrow56/esp/esp-idf/tools/idf.py' '-p' '/dev/ttyACM0'"...
--- esp-idf-monitor 1.5.0 on /dev/ttyACM0 115200
~中略~
Hello world!
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.2, 2MB external flash
Minimum free heap size: 390340 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
ログに"Hello world!"と表示されていれば問題なくプログラムが動いています。
IDFモニターを終了するには、ショートカット(Ctrl+])を使用します。
その他の操作
フラッシュ消去
フラッシュを消去することも可能です。フラッシュ メモリ全体を消去するには、次のコマンドを実行します。
idf.py -p <PORT> erase-flash
OTA データが存在する場合は、消去には次のコマンドを実行します。
idf.py -p <PORT> erase-otadata
上記以外での参考情報(リンク)
Build System
idf.pyのオプションの説明があります。
m5stack のソフトウェアを esp-idf 環境で開発して動かす
5GFXライブラリを導入しサンプルを動かす方法が説明されています。
エクスプローラでWSL2(ubuntu)のディレクトリを開く方法
VSCodeのESP-IDF拡張機能「Espressif IDF」を使ってみる
最終的にやりたいこと
M5Stack NESをM5 Core2に移植する
a Nintendo Entertainment System emulator for M5Stack