Rust on ESP32ではesp-halとesp-idfのどちらを使うべきなのか
この記事はZennにも投稿していますESP32で使えるRust向けのHALは現在2種類開発されています。
1つ目はesp-idf-svc/halです。こちらはEspressifによるESP-IDFというフレームワークをRustでも使えるようにしたものです。 2つ目はesp-halです。これはベアメタルなRust向けのライブラリで、こちらの方が開発が活発です。というかesp-idf-svc/halの方はほとんど開発が止まっており、公式にはこちらを使うことが推奨されています。
#std vs no_std
esp-idf-svcの一番大きな特徴として、Rustのstdが使えることが挙げられます。通常組み込みRustではOSの機能に依存するstd標準ライブラリは使えず、coreと呼ばれるライブラリを使います。しかしながらesp-idf-svcでは、IDFの機能を用いて標準ライブラリを実装しています。そのため、タスクを並行実行したいならstd::thread::spawnを呼び出すだけでできてしまいます。
その他にもWiFiやBLEもIDFの機能を使って比較的容易に実装することが可能です。
一方、esp-halはcoreのみが使えるno_std環境で使用することが想定されています。では並行タスクなどはどうするのか、RTOSは使うのかという話になりますが、Rustではembassyというフレームワークを使うのが一般的です。これはRustの言語機能である非同期機能を使ってタスクを実行します。Embassyについて詳しくはこの記事などを参考にしてください。慨して非常に書きやすく良いフレームワークです。
#どちらを使うべきなのか
では、どちらを使うべきなのかという話になりますが、「基本的には」esp-halを使うべきだと思います。esp-idf-svc/halはstdが使えるので一見初心者向けのような気もしますが、以下のような標準的なRust環境から外れたハマりポイントがあり、逆に苦労する可能性もあります。
- svc/halでサポートされている機能ならば良いが、結局のところFFIなので時にはesp-idf-sysを使ってunsafeなコードを書く必要がある
- トラブル時にIDFの方を疑う必要がある
- IDFの設定フレームワークがCargoとうまく連携しないことがある
- それによってコンパイルが通らないとかLSPが動かないなどの事象が発生する
- また、コンパイル速度も遅い
- esp-halよりもasyncサポートが弱い
- 基本的にesp-halはembassyを念頭に置いて開発されているため、asyncサポートが充実
- 一方、esp-idf-halでは例えばSPIは非同期ドライバが実装されているがI2Cにはされていない
- 結局MCU上なのだから変にstdによる抽象化が入っていると逆に何が起こっているか分かりづらい
一方、現状では「esp-halではできないこと」が存在しているのも事実であり、このような場合にはIDF系を使ったほうが良いです。
- esp-halで実装されていないドライバを使いたい場合
- 例えば執筆時点だとSDIOドライバがない(ただし開発中のようではある)
- 消費電力を最大限まで抑えたい場合
- ESP-IDFでは、esp-halには(まだ)実装されていない自動ライトスリープや動的周波数調整などの高度な電力管理機能が実装されている
- 特に無線を用いる場合には差が顕著に出る
- Rustエコシステムが発達していない機能を使いたい場合
- 例えば、SDカードを使いたい場合には、Rustでもembedded-fatfsなどの実装があるにはあるが、esp-idf-sysで提供されている
std::fsから使える仮想ファイルシステムのほうがパフォーマンスは良いし、安定性も高い
- 例えば、SDカードを使いたい場合には、Rustでもembedded-fatfsなどの実装があるにはあるが、esp-idf-sysで提供されている
- ESP Component Registryを使いたい場合
- esp-idf-svcにはESP Component Registryを使うための機能があり、自動でライブラリを取得してバインディングの生成まで行ってくれる
全体的に、何かあった時のワークアラウンドが少なくとも存在するという点ではIDFのほうが良いと言えます。例えばesp-halで使うembassyもstd featureを有効にすればIDFで使えますし、asyncサポートが弱い問題も、スレッドで何とかすることは一応可能です。
このようにまだ機能面ではIDF系が勝っているのは事実ですが、esp-halはEspressif公式が関与するようになったこともあってか最近急速に開発が進んでいます。例えば無線系だとBLEはtrouble、WiFiはembassy-netなどのRust製スタックを使うことができます。なので将来的にはこれらのesp-halでできないことも解消されるのではないかと期待しています。