メモ:2023年4月時点で rp-hal と rtic を使おうとして遭遇した問題

前回、大変そう、みたいなことを書いたけど、実際大変だったので遭遇した問題をメモっておく。 たぶん1年後くらいに見るとだいたい解決されてそうな気はする。

rtic v2

これは前回書いたけど、rticはいまv2の開発中らしい。 開発中なのでv1を使っておくのが安全そうだけど、すでにexamplesはv2に書き直されてしまっているので、v1の情報に行き着きづらい。

changelog を見ると、RP2040の割り込み処理関連のfixが入っていて、詳細まで追ってないけど、このへん見るとv2まで待った方が無難なのかも感ある。

あと、関連する変更としては、cortex-m crateはoptionalになって、RP2040 には rp2040_pac が使われるようになっている。

ただし、v2がいつリリースされるのかはわからない。というのも、stable入りしていないtype_alias_impl_trait(TAIT)という機能を使っていて、 今のところnightlyでしかビルドできないからだ。このfeatureはけっこう範囲が広い話になってそうで、すぐstable入りするのかはわからない。

いちおう1月時点のType teamのアナウンスでは、ロードマップの半年後のマイルストーンとして

Both TAITs and RPITITs/AFITs should be stabilized or on the path to stabilization.

というのが上がっていて、うまくいけば今年中くらい?には stable 入りするのかもしれない。

probe-run v0.3.8

probe-run のバージョンを上げると、

Error: unable to determine reset handler

というエラーが出るようになった。以下のissueらしい。

解決策としては、とりあえず以下のいずれかを実行すればよく、これもまあ時間が解決してくれる。

# 古いバージョンをインストール
cargo install probe-run --version=0.3.6

# まだマージされてない修正バージョンをインストール
cargo install probe-run --git https://github.com/knurling-rs/probe-run.git --rev 884e799dd7fb0cf6d64619a23a3807ca2ccb47e9

critical-section v1

panic-halt crate(rp-halのテンプレがこっちを使っている)の代わりにpanic-probe crateを使おうとすると、以下のようなエラーになる。

error: linking with `flip-link` failed: exit code: 1
  |
  = note: "flip-link" "-flavor" "gnu" ...
  = note: rust-lld: warning: section type mismatch for .uninit.rtic0
          >>> C:\path\to\target\thumbv6m-none-eabi\release\deps\rp2040_project_template-9eb4fbc6648ae2bb.rp2040_project_template.67f1a80dc3e1e3e2-cgu.0.rcgu.o:(.uninit.rtic0): SHT_PROGBITS
          >>> output section .uninit: SHT_NOBITS

          rust-lld: warning: section type mismatch for .uninit.rtic1
          >>> C:\path\to\target\thumbv6m-none-eabi\release\deps\rp2040_project_template-9eb4fbc6648ae2bb.rp2040_project_template.67f1a80dc3e1e3e2-cgu.0.rcgu.o:(.uninit.rtic1): SHT_PROGBITS
          >>> output section .uninit: SHT_NOBITS

          rust-lld: warning: section type mismatch for .got
          >>> <internal>:(.got): SHT_PROGBITS
          >>> output section .got: SHT_NOBITS

          rust-lld: warning: section type mismatch for .got.plt
          >>> <internal>:(.got.plt): SHT_PROGBITS
          >>> output section .got: SHT_NOBITS

          rust-lld: warning: section type mismatch for .got
          >>> <internal>:(.got): SHT_PROGBITS
          >>> output section .got: SHT_NOBITS

          rust-lld: error: undefined symbol: _defmt_write
          >>> referenced by mod.rs:85 (src\export\mod.rs:85)
          >>>               C:\path\to\target\thumbv6m-none-eabi\release\deps\rp2040_project_template-9eb4fbc6648ae2bb.rp2040_project_template.67f1a80dc3e1e3e2-cgu.0.rcgu.o:(_$LT$$RF$mut$u20$W$u20$as$u20$core..fmt..Write$GT$::write_str::h92a8258e37737754)
          >>> referenced by mod.rs:85 (src\export\mod.rs:85)
          >>>               C:\path\to\target\thumbv6m-none-eabi\release\deps\rp2040_project_template-9eb4fbc6648ae2bb.rp2040_project_template.67f1a80dc3e1e3e2-cgu.0.rcgu.o:(_$LT$$RF$mut$u20$W$u20$as$u20$core..fmt..Write$GT$::write_char::h45710a9cd90d4bd7)
          >>> referenced by mod.rs:85 (src\export\mod.rs:85)
          >>>               C:\path\to\target\thumbv6m-none-eabi\release\deps\rp2040_project_template-9eb4fbc6648ae2bb.rp2040_project_template.67f1a80dc3e1e3e2-cgu.0.rcgu.o:(defmt::export::header::hff04f82cdd450f5a)
          >>> referenced 2 more times

          rust-lld: error: undefined symbol: _defmt_acquire
          >>> referenced by mod.rs:55 (C:\path\to\.cargo\registry\src\index.crates.io-6f17d22bba15001f\defmt-0.3.4\src\export\mod.rs:55)
          >>>               C:\path\to\target\thumbv6m-none-eabi\release\deps\rp2040_project_template-9eb4fbc6648ae2bb.rp2040_project_template.67f1a80dc3e1e3e2-cgu.0.rcgu.o:(rust_begin_unwind)

          rust-lld: error: undefined symbol: _defmt_release
          >>> referenced by mod.rs:71 (C:\path\to\.cargo\registry\src\index.crates.io-6f17d22bba15001f\defmt-0.3.4\src\export\mod.rs:71)
          >>>               C:\path\to\target\thumbv6m-none-eabi\release\deps\rp2040_project_template-9eb4fbc6648ae2bb.rp2040_project_template.67f1a80dc3e1e3e2-cgu.0.rcgu.o:(rust_begin_unwind)

          flip-link: the native linker failed to link the program normally; please check your project configuration and linker scripts


warning: `rp2040-project-template` (bin "rp2040-project-template") generated 1 warning
error: could not compile `rp2040-project-template` (bin "rp2040-project-template") due to previous error; 1 warning emitted

これはどういう問題かというと、以下に詳しい説明がある。

defmtは、組み込み(などのリソースが限られた環境)用のロギングのフレームワークで、defmt-rttはそれをRTT越しにやりとりする仕組みらしい。 probe-runを使ってデバッグ用のログが見れるのもこの仕組みのおかげのはず。

そのdefmt-rttが依存しているcritical-section crate(組み込み環境で排他処理を行うやつらしい)は、ビルドに当たって適切なfeatureを明示的に選択する必要があり、しなければエラーになる。 こういう状況になったのは、以前の critical-section のデフォルトの実装はシングルコアを想定していて、それがマルチコア環境では想定外の事故を引き起こすから、という感じらしい。

誤って使われることを防ぐために過去のバージョンをすべて crates.io から yank していて、わりと深刻な問題っぽい。

で、「適切なfeatureを明示的に選択」とはどういうことかというと、HALがそういうfeatureを提供してるはずなのでそれ使ってね、とのことだった。 たとえばシングルコアの場合はこう、とドキュメントに書かれていて、これをコピペすれば動きそうな気がするけど、一瞬立ち止まって「RP2040はマルチコアだ!」という事実を思い出す。 なのでこれは違う。

[dependencies]
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]}

(https://docs.rs/critical-section/1.1.1/critical_section/#usage-in-no-std-binaries)

ではどうなってるかというと、ここはrp-pico crateが適切に設定してくれているはず。なので、なぜエラーになるのかは謎のまま...

defmt wire version 4

cargo embedを実行すると以下のようなエラーになる。

       Error defmt wire format version mismatch: firmware is using 4, `probe-run` supports 3
             suggestion: `cargo install` a different version of `probe-run` that supports defmt 4

これはいったい...?、と思ってdefmtのChangelogを見ると、4月頭にリリースされたバージョンでdefmtのプロトコルのバージョンが上がったらしい。

probe-runと書かれているので何度もcargo install probe-runしてたけど、改善せず、やるのはcargo install cargo-embedであることに気付いた。

cortex-m v0.8

cortex-m crateは、crates.io上にあるのはv0.7.7なのに、レポジトリを見るとv0.7.4のコードしかなくて、なぜ?と思ってたけど、 masterじゃなくてv0.7.xというブランチで開発が進んでいるらしい。

1年半前くらいからv0.8の計画があるというissueを見つけた。 まだ全然リリースされてないのはどういうこと?、と思ったら、どうやらembedded-hal v1.0リリース待ちらしい。

embedded-hal v1

embedded-hal v1については、詳しく書かれている方がいたのでこれを参照。

ちなみに、rp-halはv0.2もv1.0も両方平行してサポートする方針でいってるらしい。大変そう...

感想

これだけ書いといてあれだけど、デバッグを諦めれば(つまりプログラムをRaspberry Pi Picoに送り込むだけでよければ)、ふつうに動くのでそんなに困ってるわけではない。 ただ、深追いしようと思うと、いろいろ調べないと行けなくてめちゃんこ疲れた。

組み込みRustは、自分のような初心者が気軽に触れるようになるまでにはあと2年くらいはかかりそう。 という予測が外れであってほしい...