筆者について
name → Koki Teramoto
age → 19
language → ja_JP, en_US
本編
あまり詳細には書きませんが、急遽 ESP32 を開発する環境を整える必要がありまして、、、。個人的に Arduino IDE はそこまで好きではないですしせっかくならということで、Rust で開発できる環境を整える(しかも WSL2)という奇行を記しておきます。
解決しなければならなかった点
表題の目的を達成するためには2つの点を解決しなければいけませんでした。
- そもそも WSL2 にどうやって USB を認識させるのか
- Rust で ESP32 の開発環境を整えることはできるのか
まず前者についてはusbipdというものを利用した方法が Microsoft 公式に進められていましたのでこれを利用して解決できます。
また後者についても、開発元の Espressif が Rust の開発ツールを公開しているそうです。
また、今回は以下のページを参考にさせていただきました。ありがとうございます。
開発環境
$ uname -r
5.15.167.4-microsoft-standard-WSL2+
ちなみに、WSL2 のネットワークモードは NAT である必要があります。ブリッジやミラーでは動きませんのでご注意ください。
まずは USB 問題を解決
まず最初は USB 問題を解決しましょう。usbipdをインストールしていきます。これのついでですし USB メモリも認識できるようにカーネルのリビルドもささっとやっちゃいましょう。最初は Windows にて。
winget install --interactive --exact dorssel.usbipd-win
続いて Ubuntu 上にて。
sudo apt updata
sudo apt upgrade
sudo apt install linux-tools-generic hwdata
なお、参照元にはsudo update-alternativesをしなければいけないと書いていますが、筆者環境においてはおきませんでした。さて、このタイミングで Windows 機と ESP32 を接続しましょう。
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
2-3 8087:0029 Intel(R) Wireless Bluetooth(R) Not shared
2-4 0411:023b USB Mass Storage Device Shared
4-1 10c4:ea60 CP2102 USB to UART Bridge Controller Attached
Persisted:
GUID DEVICE
usbipd: warning: Unknown USB filter 'edevmon' may be incompatible with this software; 'bind --force' may be required.
この場合、4-1 が BUSID となるので、こちら覚えておきましょう。
sudo usbipd bound --busid 4-1
usbipd attach --wsl --busid 4-1
ちなみに、この時の bound については管理者権限で実行しないと怒られます。また、筆者環境においては既に Powershell でsudoが使えますが、使えない方は適宜管理者権限で PowerShell を開く等回避策をお願いします。
$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 004: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
(おまけ)USB メモリを認識させる方法
USB メモリは実はこれだけではだめで、USB メモリを使いたい場合はカーネルのリビルドが必要です。まずはバージョンを確認。
$ uname -r
5.15.90.1-microsoft-standard-WSL2+
次にビルドに必要なライブラリをインストールしてください。
sudo apt install -y build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool bc dwarves fdisk
続いてリポジトリをクローンします。なお、リポジトリには各リポジトリがあるのですがさすがにこれ全部はダウンロードできないのでシングルブランチでクローンしてください。この時のブランチはlinux-msft-wsl-VERSIONで、VERSIONは適宜上のバージョン番号に置き換えてください。上の場合は
git clone -b linux-msft-wsl-5.15.90.1 --single-branch https://github.com/microsoft/WSL2-Linux-Kernel.git
続いてビルド前の設定をします。
cd WSL2-Linux-Kernel
zcat /proc/config.gz > .config
make menuconfig
ここで、 Device Drivers > USB support より、USB Serial Converter supportと USB Muss Storage supportをスペースでアスタリスクをつけ Save してください。そしたらビルドです(この時のオプション等は参考元通りにさせていただきました、ありがとうございます)。
export N_CPU_UNITS=`getconf _NPROCESSORS_ONLN`
sudo make -j $N_CPU_UNITS && sudo make modules_install -j $N_CPU_UNITS && sudo make install -j $N_CPU_UNITS
ビルドが終わればカーネルが vmlinux という名前で置かれています。これを Windowst 側のどっか適当なとこにおいて config に設定します(僕の場合は名前変えてます)。
[wsl2]
kernel=C:\\tools\\wsl\\5.15.167.4
networkingMode=NAT
vmSwitch=External
dhcp=true
ここまで来たら、USB メモリが認識されるようになるはずなので、各自マウントをしてください。フォーマット形式によっては追加でパッケージのインストールが必要になるかもしれません。
Rust の開発環境
まず、Rust は事前にインストールできていることが前提です。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
ちなみに、筆者の Rust のバージョンは以下の通りです。
$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home: /home/koki/.rustup
installed toolchains
--------------------
stable-x86_64-unknown-linux-gnu (active, default)
active toolchain
----------------
name: stable-x86_64-unknown-linux-gnu
active because: it's the default toolchain
installed targets:
x86_64-unknown-linux-gnu
まずはパッケージのインストールです。
sudo apt 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
cargo install cargo-generate
cargo install ldproxy
cargo install espup --locked
cargo install espflash
cargo install cargo-espflash
espup install
ここまで終わったらツールチェーンが追加されているはずです。
$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home: /home/koki/.rustup
installed toolchains
--------------------
stable-x86_64-unknown-linux-gnu (active, default)
esp
active toolchain
----------------
name: stable-x86_64-unknown-linux-gnu
active because: it's the default toolchain
installed targets:
riscv32imac-unknown-none-elf
riscv32imafc-unknown-none-elf
riscv32imc-unknown-none-elf
x86_64-unknown-linux-gnu
さて、それでは開発環境にはりいましょう。これは都度実行しましょう。
. ~/export-esp.sh
ここまでこれば、開発環境の整備は終わりです!
実際にプログラムを実行してみる
ということで、テストプロジェクトを作ります。
cargo generate esp-rs/esp-idf-template cargo
プロントに従って設定したらいいです。Configure advanced template options?は falseで大丈夫です。終わったらディレクトリに移行しましょう。すると、以下のようなファイルがみられるはずです。
fn main() {
esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
log::info!("Hello, world!");
}
ふむふむ、こんな感じなんですね。ということでこれをこのまま実行しましょう。
cargo run --release
これでログに表示されたら完璧です!
ちなみに、500[ms]ごとに HelloWorld を表示する方法
以下、プログラムです。
use esp_idf_hal::delay::Ets;
use esp_idf_hal::delay::FreeRtos;
use std::thread;
use std::time::Duration;
fn main() {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
thread::sleep(Duration::from_millis(0));
FreeRtos::delay_ms(0);
Ets::delay_ms(0);
loop {
log::info!("Hello, world!");
FreeRtos::delay_ms(500);
}
}
あと、これに伴い依存関係も調整する必要があります。
[dependencies]
log = "0.4"
esp-idf-svc = "0.51"
esp-idf-hal = "0.45.2"
最後に
今回はとりあえず開発環境を整えましたが、全然 Rust の勉強も ESP32 の勉強もしてないので、今後も継続して勉強していきたいと思います。
