結局 Rust の embedded-hal v1.0.0 ってどうなってるの?

この記事は、モダン言語によるベアメタル組込み開発 Advent Calendar 2022の12日目として書きました。

qiita.com

モダン言語によるベアメタル組込み開発、と言われても私のような人間は、何の言語ネタで書くか困ってしまいますね。 困った時の神だより。 神と言えば、Rust というのが、人類の共通認識になって久しく思われるため、Rust について書くことにしました。

あらまし

github.com

embedded-hal について言うことは全て「基礎から学ぶ組込みRust」で書いたので、何も書きません! 二度と同じような内容は書かない、という強い気持ちのもと書ききったので誰も文句ないね? embedded-hal を知らない人は本を買ってね。 本にはめちゃくちゃ丁寧に書いたから!

そんな embedded-hal ですが、基礎から学ぶ組込みRust執筆前から、v1.0.0 のリリースについての issue が作られています。

github.com

本を書き始めた当初は、本を出すのは embedded-hal v1.0.0 が出るのを待ちたい、とか言ってましたね。 待たなくてよかったね?

そんな長らく時間のかかっている embedded-hal v1.0.0 のリリースですが、一体全体どうなっているのでしょう? わたし、気になります! ということで軽く現状を調べてみました。

本当に軽く調べただけなので間違ってる部分もあるかもしれません。 ほんまかぁ?と思ったら自分でも確かめて見てください。

継続的に v1.0.0 alpha リリースがなされている

ちょいちょい v1.0.0-alpha.x がリリースされています。 現在の最新は alpha.9 です。 リポジトリのトップにも注意書きがなされていますが、alpha リリースごとに非互換の修正が入っています。

単純な一ユーザーとして考えると、毎バージョン、変更に対応しようとするとコストが高そうです。 また、世の中の embedded-hal のトレイトを使って実装されているドライバーは、stable version の 0.2.x で止まっているものもあれば、最新の alpha リリースを追いかけているものもあります。 そのような状況なので、やりたいアプリケーションを書こうとしたときに、両方の embedded-hal が必要になったりして、中々にカオスな状況です

そんな状況なので、なんと、v0.2.x 系と v1.0.0-alpha 系との互換性維持のための crate が生まれちゃっていたりします。うーん!

github.com

async / await どうすんねん問題

Rust と embedded-hal をある程度触ったことあると共通の疑問に辿りつきます。 それが「async どうすんねん問題」です。

元々、embedded-hal の API はすべて nb という non-blocking APIResult を返す設計になっていました。 そして、nb のドキュメントにさも async / await と関係ありそうなことが書いてありました。

Furthermore those APIs are not tied to a particular asynchronous model and can be adapted to work with the futures model or with the async / await model.

docs.rs

結論から言うと、nb と Rust の言語機能としての async / await は何も関係がありません。 nb が提供できるのは、WouldBlock のエラーを返す API をポーリングして non-blocking な処理がかける、というだけなのです。

ということで、ワーキンググループの中で、v1.0.0 を出す前に async ちゃんと考えないといけないよね、という話になったようです。 これはめちゃくちゃ良い議論 & 判断な印象を受けました。

We had a brief chat about 1.0 in the meeting today and two interesting points were raised:

  • Should we remove the nb traits entirely for 1.0? It's not clear that they're especially useful or widely used, many users report confusion with them, and ultimately the async traits should fully replace nb. > Plus, we could always add them back, but we can't ever delete them later if they're included in 1.0.
  • Could we keep embedded-hal-async a separate crate forever, with embedded-hal just containing the common types/errors and the blocking traits? It would mean we could remove the ::blocking sub-modules which simplifies the crate, but we couldn't easily merge async traits back in the future.

Both worth resolving before we release 1.0.

あるべき方向に向かっている気がする

さて、エンターテイメントでもあるので、若干おもしろおかしく書いている部分はありますが、私個人の意見としてはあるべき方向に向かっている、という印象で、多少時間がかかってでも v1.0.0 の完成度を上げるのは今後の組込み Rust の普及に、非常に重要なことだと感じています。

例えば、async 系は、embedded-hal の一部として出すことを想定して、今は試行錯誤のフェーズとして独立した crate で開発されています。 でもちゃんと async が embedded-hal の一部として存在するようにする、というのはめちゃくちゃ価値があることだと思います。

github.com

その他、以前の embedded-hal では SPI や I2C など、マスターが複数のデバイスと通信できるペリフェラルをうまく表現できていない問題がありました。 今はこれを Bus として切り出して embedded-hal に加えていこうとする動きが見て取れます。 これも非常に良い話ですね。

github.com

まとめ

非互換修正が入りまくる中で開発するのはユーザーとしてしんどい部分もありますが、気長にあるべき姿の embedded-hal v1.0.0 のリリースを待ちたいと思います。 なんと言っても書籍を執筆していないので焦る必要がありませんしね!

来年も組込み Rust を頑張っていこうと思います。 良いお年を。