取り組み:ESP32-C3のRust用評価ボードを入手できたので、TutorialをやってRustを理解する
課題:WSL上のUbuntuからRust用評価ボードへのUSB経由接続がうまくいかない
対応:Ubuntuからの書き込み不可問題を回避するため、ターゲットボードをM5 Stamp C3に変更、書き込みが成功、デモのWiFi接続+LチカまではOK
詳細:
輸出管理をクリアして、ESP32C3が搭載されたRust用評価ボード(ESP32-C3-DevKit-RUST)が届いた。
Espressifが提供しているEmbedded Rust Tutorialをやってみる。
参照している資料:Embedded Rust on Espressif / Checking the hardware
https://espressif-trainings.ferrous-systems.com/02_1_hardware.html
前回Rustの環境をWSL上で構築した。Tutorialに従うと、次はボードの接続確認である。WSL上のUbuntu からボードが見えるようにしたいのでmoutする必要あり。(この手順を書いてくれている記事があるのでそれを参照)。PowerShellで以下を実行してデバイス一覧を取得
> usbipd wsl list BUSID VID:PID DEVICE STATE 3-2 8087:07da インテル(R) ワイヤレス Bluetooth(R) Not attached 4-1 303a:1001 USB シリアル デバイス (COM17), USB JTAG/serial debug unit Not attached 4-3 046d:c058 USB 入力デバイス Not attached
評価ボードのBUSIDは 4-1と分かる。attachコマンドでWSLにマウントさせるが、権限不足で怒られる
> usbipd wsl attach --busid 4-1 usbipd: error: Access denied; this operation requires administrator privileges. usbipd: info: The first time attaching a device to WSL requires elevated privileges; subsequent attaches will succeed with standard user privileges.
PowerShellを管理者権限で立ち上げてコマンド実行。権限エラーは出ないが、warningが出ている。
> usbipd wsl attach --busid 4-1 usbipd: warning: USB filter 'USBPcap' is known to be incompatible with this software; 'bind --force' will be required.
Ubuntu側でlsusbを実行してマウント?されたかを確認
$ 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
ボードは見えたと判断して、サンプルコードを動かしてみる。
Tutorialに従って、Git上のサンプルコード一式をローカルPCに複製する
git clone "https://github.com/ferrous-systems/espressif-trainings.git"
Hello boardをやってみる
参照資料:Embedded Rust on Espressif / Hello, board!
cd intro/hardware-check cp cfg.toml.example cfg.toml vi cfg.toml cargo build
以下のエラーになった
error: "/home/<user_id>/.rustup/toolchains/nightly-2022-03-10-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/Cargo.lock" does not exist, unable to build with the standard library, try: rustup component add rust-src --toolchain nightly-2022-03-10-x86_64-unknown-linux-gnu
エラー文言を読むと、不足するコンポーネントを加えろよと言ってる感じがする
前回開発環境を入れたつもりだったが、必要なモジュール?が入っていなかったのか?と解釈して再度インストール
Embedded Rust on Espressif / Software を見ながら再度入れる
rustup install nightly-2022-03-10 rustup component add rust-src --toolchain nightly-2022-03-10 cargo install cargo-espflash ldproxy sudo apt install llvm-dev libclang-dev clang
再度ビルドしてみる
$cargo build
ビルドは開始された。自分のPCが非力なせいか、めちゃくちゃ遅い(仮想環境上のUbuntuを使っているせいもあるがあまりにも遅すぎる)。コンパイル型言語なので実行は早いだろうけど、バイナリが生成されるまでにめちゃくちゃ時間がかかる。これでTry&Errorはかなり辛い。Rustを使いたかったら高性能なPCが必要ということか。
しかもビルドでエラーになった。Tutorialの通りにやってるのに。。unstableなライブラリを使おうとしているということ??
Compiling ignore v0.4.20 error[E0658]: use of unstable library feature 'scoped_threads' --> /home/xxxx/.cargo/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.20/src/walk.rs:1285:9 | 1285 | std::thread::scope(|s| { | ^^^^^^^^^^^^^^^^^^ | = note: see issue #93203 <https://github.com/rust-lang/rust/issues/93203> for more information = help: add `#![feature(scoped_threads)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'scoped_threads' --> /home/xxxxx/.cargo/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.20/src/walk.rs:1299:32 | 1299 | handles.push(s.spawn(|| worker.run())); | ^^^^^ | = note: see issue #93203 <https://github.com/rust-lang/rust/issues/93203> for more information = help: add `#![feature(scoped_threads)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'scoped_threads' --> /home/xxxxx/.cargo/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.20/src/walk.rs:1302:24 | 1302 | handle.join().unwrap(); | ^^^^ | = note: see issue #93203 <https://github.com/rust-lang/rust/issues/93203> for more information = help: add `#![feature(scoped_threads)]` to the crate attributes to enable For more information about this error, try `rustc --explain E0658`. error: could not compile `ignore` due to 3 previous errors warning: build failed, waiting for other jobs to finish... error: build failed
nightly versionを使っているなら、冒頭に#![feature(hoge)]と追加しろと。。
If you're using a nightly version of rustc, just add the corresponding feature to be able to use it: ``` #![feature(repr128)]
Issueが発行されていて、それによると、workaroundで対応しろと
[bug] use of unstable library feature 'scoped_threads' in `ignore` crate · Issue #6050 · tauri-apps/tauri · GitHub
cargo update -p ignore --precise 0.4.18
ignoreコンポーネント(?)は、0.4.18を指定するという意味か?
再度ビルド。。。ここから進まない。
Building [======================> ] 224/239: esp-idf-svc(build.rs), esp-idf-hal(build.rs), esp-idf-sys(build.r...
一晩放置したが、Ubuntu 環境自体がちょっとおかしくなった。SWAPしまくったせいか? 再度Ubuntuを立ち上げてビルドしてなんとかバイナリはできた。次は書き込みということで、すでにマウントしているので、以下で書き込む
$ cargo espflash --release --monitor /dev/ttyACM0 New version of cargo-espflash is available: v2.0.0-rc.3 Serial port: /dev/ttyACM0 Connecting... Error: espflash::serial_error × Failed to open serial port /dev/ttyACM0 ├─▶ Error while connecting to device ├─▶ IO error while using serial port: Permission denied ╰─▶ Permission denied
/dev/ttyACM0のパーミッションエラーが出ている。sudoで権限を切り替えるか、/dev/ttyACM0に書き込み権限を与えるか・・・ sudoして実行パスとか変わるのを避けたいので、/dev/ttyACM0を誰でも書ける権限に変更
sudo chmod og+rw /dev/ttyACM0
再度実行、権限の問題は解消したが、ずっと待ち状態である。ボードをBOOTモードにしないといけない?
$ cargo espflash --release --monitor /dev/ttyACM0 New version of cargo-espflash is available: v2.0.0-rc.3 Serial port: /dev/ttyACM0 Connecting... Matched SerialPortType::Unknown
書き込もうとして文鎮になったという記事あり・・・ うーん。。
Cargo run bricks ESP32-C3 - Embedded - The Rust Programming Language Forum
espflashのサブコマンドで、board-infoというのがあり、それをやってみるがやはり無応答になる。Unknownと返してくるのが何かパラメータ解釈できないということなのか。。ソースを見ないと原因が分からん。書き込みだけだったら、Windowsの素の環境でもいいのではと思えるが、buildのcontextとか怒られるとまたややこしそうだ
SUBCOMMANDS: board-info Display information about the connected board and exit without flashing help Print this message or the help of the given subcommand(s) partition-table Operations for partitions tables save-image Save the image to disk instead of flashing to device serial-monitor Open the serial monitor without flashing $ cargo-espflash espflash /dev/ttyACM0 board-info New version of cargo-espflash is available: v2.0.0-rc.3 ✔ Use serial port '/dev/ttyACM0'? · yes Serial port: /dev/ttyACM0 Connecting... Matched SerialPortType::Unknown
詳しくは調べられていないけど、WSLからUSB Serialを扱いたい場合はカーネルをビルドしろという記事もある。。うーんどうしたものか。素のWindowsでやるか、Macに環境を作るか。そもそもなんでUbuntuなんだったっけ・・・環境構築がLinuxで標準的だからトラブルも少なかろうと選んだ記憶が・・
CP210Xとは何なのか(ドライバ?)分かっていないが、CP210Xを有効にするためにカーネルビルドしろとあったが、自分の場合、CP210Xはすでに有効である。だから、USB Serialは使えるはずなのだが。。 USB Serialのドライバが正しく機能していないのだろうか。
$ gzip -dc /proc/config.gz | grep CONFIG_USB_SERIAL_CP210X CONFIG_USB_SERIAL_CP210X=y
少なくとも書き込みコマンドを実行すると評価ボードのLEDが一旦消えるのでUbuntuからはUSB経由で制御できていると思われるのだが。
CP210xとは、 USB - UART ブリッジのデバイスであった。今使ってる評価ボードにCP201Xが使われていないとこれは意味がないので、回路図で、USB-UARTブリッジがどうなっているのか確認が必要だ。ボードの実装パーツみてもブリッジ用のLSIは不在で、USBの変換は、ESP32本体でやっているような印象なのだが。
TeraTermによる属性表示は以下
Device Friendly Name: USB シリアル デバイス (COM17) Device Instance ID: USB\VID_303A&PID_1001&MI_00\7&11EFCA92&0&0000 Device Manufacturer: Microsoft Provider Name: Microsoft Driver Date: 6-21-2006 Driver Version: 10.0.19041.2130
/dev/ttyXXXのパラメータを確認する方法
# stty -a < /dev/ttyUSB0
USB-SerialのICを介さず、ESP32C3がUSBの信号を直接受ける回路がまずいのかと思い、同じESP32C3を搭載している、M5Stamp C3に繋いでみた。C3はUSB-Serial変換用IC; CH9102を介してマイコンと接続されている。結果、M5 Stamp C3にはファームを焼くことができた。
$ cargo espflash --release --monitor /dev/ttyACM0 New version of cargo-espflash is available: v2.0.0-rc.3 Serial port: /dev/ttyACM0 Connecting... Matched SerialPortType::Unknown Finished release [optimized] target(s) in 22.19s Chip type: ESP32-C3 (revision 3) Crystal frequency: 40MHz Flash size: 4MB Features: WiFi MAC address: 7c:df:a1:a2:bb:d8 App/part. size: 670000/1048576 bytes, 63.90% [00:00:01] ######################################## 12/12 segment 0x0 [00:00:00] ######################################## 1/1 segment 0x8000 [00:00:42] ######################################## 391/391 segment 0x10000 Flashing has completed! Commands: CTRL+R Reset chip CTRL+C Exit ESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fcd6100,len:0x16b4 load:0x403ce000,len:0x930 0x403ce000 - _iram_end at ??:?? load:0x403d0000,len:0x2d28 0x403d0000 - _iram_end at ??:?? SHA-256 comparison failed: Calculated: 975a71a5818324ff5de2ef93a833fdae997b5d9528ed55e78c9c569b491ea994 Expected: f3cfb3504e9d254ef83d279dbe0bbcc8ce640d9caa06ce39a148ace3335de6ed Attempting to boot anyway... entry 0x403ce000 0x403ce000 - _iram_end at ??:??
結構進んだものの、WiFi接続でエラーになる。
5G帯だとNGで、2.4Gだと接続できた*1。ボードが違ってるけど、LEDの接続は同じだったようで、テストプログラムを実行するとNetPixel風のLEDが緑・青と点灯する。
初めて使うボード、コンパイル環境だったので結構手間がかかったけど、main 関数を確認すると、WiFiの接続とLEDの点灯、デバッグ文字列出力だけのシンプルなコードだった。これだけのコードに、あれだけのファイルのビルドをやったというのはどうしたなのか??なぜあんなに大量のライブラリが必要だったのか?? Espressif では標準ライブラリをサポートできているので、、使う使わないに関わらず関連ライブラリはすべてビルドするということなのか??
fn main() -> anyhow::Result<()> { use bsc::led::RGB8; esp_idf_sys::link_patches(); esp_idf_svc::log::EspLogger::initialize_default(); info!("Hello, world!"); // Start the LED off yellow let mut led = bsc::led::WS2812RMT::new()?; led.set_pixel(RGB8::new(50, 50, 0))?; // The constant `CONFIG` is auto-generated by `toml_config`. let app_config = CONFIG; // Connect to the Wi-Fi network let _wifi = match bsc::wifi::wifi(app_config.wifi_ssid, app_config.wifi_psk) { Ok(inner) => inner, Err(err) => { // Red! led.set_pixel(RGB8::new(50, 0, 0))?; anyhow::bail!("could not connect to Wi-Fi network: {:?}", err) } }; loop { // Blue! led.set_pixel(RGB8::new(0, 0, 50))?; // Wait... std::thread::sleep(std::time::Duration::from_secs(1)); info!("Hello, world!"); // Green! led.set_pixel(RGB8::new(0, 50, 0))?; // Wait... std::thread::sleep(std::time::Duration::from_secs(1)); } }
■メモ
WSL上のUbuntu で最低限確認できたら、MacBook上でビルド環境を構築したい。MacのOSの仕組みがよくわかっておらず、オリジナルの環境を汚したくないのでDockerでコンテナ化したい。
■追記
MacのDocker上にUbuntuを入れてRust開発環境を構築した。さすがにCPUの性能差によるものか、バイナリまではサクサクと動いた。が、VMはUSBがパススルーされていないらしく、Docker環境からはファームを評価ボードに書き込めないようであった。Flash書き込みまでコマンド一発で実行できないため、これはなかり面倒だ。しょうがないので、コンテナではなく、Macの素の環境に入れるしかないか。。
■参考記事
WSLにUSBデバイスをマウントさせる方法
https://zenn.dev/nozo/scraps/5ad75a77d88470
WSL2環境からUSBシリアルデバイスを使う - Qiita
GitHub - esp-rs/esp-rust-board: Open Hardware with ESP32-C3 compatible with Feather specification designed in KiCad
*1:Tutorialを読み直すと、「5GはNGで、2.4Gに接続しろ」とあった