Embassyは、Rust用の組み込みプログラミングフレームワークです。
具体的にはAsyncでのタスク管理とHALが組み合わさったような感じです。HALはstm32のものが用意されています。STMの公式の開発環境とHALはあまり評判がよくない(し、個人的に使いにくい)ので、せっかくならばメモリ安全性のあるRustのフレームワークを使いたいと思います。
今回はWindowsのWSL上で環境を構築することにしました。Getting Startedのページを参考に進めていきます。下にコマンドが書いてありますが、バージョン違いでエラーとなったりするので実際は公式のドキュメントを見ながら行ってください。書き込みデバイスはST-Link(クローン)、ターゲットデバイスはSTM32F103C8T6を想定しています。
環境構築
rustupとprobe-rsが必要なようです。rustupはコマンド一つでインストールできます。インストール後はウィンドウを開き直します。
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
probe-rsは少し設定が必要です。一般権限でも使えるようにするためにudevのルールを作成し、WSLのUSBフォワードを設定します。
$ curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh
$ wget https://probe.rs/files/69-probe-rs.rules
$ sudo mv 69-probe-rs.rules /etc/udev/rules.d
$ sudo udevadm control --reload
$ sudo udevadm trigger
probe-rsのインストールは完了しましたが、この状態でlsusbを実行しても何も表示されず、WSL側にUSBが認識されていないと思います。USBデバイスを接続するの記事の通り、usbipdをインストールする必要があります。
Windows側にusbipdをインストールして、WSLウィンドウを開いてから、PowerShellを管理者権限で起動させusbipd listを実行して”STM32 STLink”という名前のBUSIDをコピーします。PowerShell上でusbipd bind --busid [BUSID]とusbipd attach --wsl --busid [BUSID]を実行し、USBのバインドとアタッチを行います。この状態でWSL側でlsusbを実行すると、デバイスが表示されるはずです。
この作業を行うとUSBはWindows側からは認識されなくなります。WIndows側に戻すにはPowerShellでusbipd detach --busid [BUSID]を実行します。attachとdetachを行う際は管理者権限はいりません。
probe-rs listをWSL側で実行してprobe-rsが書き込みデバイスを認識しているか確認します。以下のように表示されれば認識しています。
The following debug probes were found:
[0]: STLink V2 -- 0483:3748:40 (ST-LINK)
Embassyのサンプルを動かす
以下のコマンドを実行してEmbassyをダウンロードし、サンプルのLチカをビルドします。LEDのピンはBlue Pill等でよくあるPC13に設定されています。ほかのボードではPB12など他のピンの場合もあるので、その場合はsrc/bin/blinky.rsのピン指定を変更します。初回ビルドは関係パッケージをダウンロードしてくるので時間がかかります。
$ git clone https://github.com/embassy-rs/embassy.git
$ cd embassy/examples/stm32f1
$ cargo build --bin blinky --release
書き込み前に、EmbassyのサンプルではBOOT0を手動でHighにしないとSWDでの書き込みができなくなるのでスイッチにアクセス可能か調べてから行ってください。また、クロックやピンの設定等もデフォルトのものになるので周辺機器はつながないでください。
ビルドが成功したら、BOOT0がHighの状態でボードの電源を入れ、BOOT0をLowにしてからST-Linkにつなぎ、以下のコマンドでボードに書き込みます。
$ cargo run --bin blinky --release
書き込みが成功してプログラムが実行できた場合、以下のようにログが出力されます。
0.000000 [TRACE] rcc: enabled 0x7:28 (embassy_stm32 src/rcc/mod.rs:299)
0.000000 [TRACE] rcc: enabled 0x5:4 (embassy_stm32 src/rcc/mod.rs:299)
0.000000 [TRACE] rcc: enabled 0x6:0 (embassy_stm32 src/rcc/mod.rs:299)
0.000000 [TRACE] BDCR ok: 00008200 (embassy_stm32 src/rcc/bd.rs:307)
0.000000 [DEBUG] rcc: Clocks { hclk1: MaybeHertz(8000000), pclk1: MaybeHertz(8000000), pclk1_tim: MaybeHertz(8000000), pclk2: MaybeHertz(8000000), pclk2_tim: MaybeHertz(8000000), rtc: MaybeHertz(40000), sys: MaybeHertz(8000000), usb: MaybeHertz(0) } (embassy_stm32 src/rcc/mod.rs:81)
0.000000 [TRACE] rcc: enabled 0x7:2 (embassy_stm32 src/rcc/mod.rs:299)
0.000030 [INFO ] Hello World! (blinky src/bin/blinky.rs:13)
0.000183 [INFO ] high (blinky src/bin/blinky.rs:18)
0.300415 [INFO ] low (blinky src/bin/blinky.rs:22)
0.600677 [INFO ] high (blinky src/bin/blinky.rs:18)
0.900939 [INFO ] low (blinky src/bin/blinky.rs:22)
VSCode
VSCodeでは、embassyディレクトリを開くことでVSCode用の設定が読み込まれます。ディレクトリを開くとrust-analyzerとBetter TOMLがおすすめされるのでインストールします。またprobe-rsの拡張機能もインストールします。
.vscode/settings.jsonを開き、ターゲットのアーキテクチャとプラットフォームの部分のコメントを外します。今回の場合は以下の2行のコメントを外します。
...
"rust-analyzer.cargo.target": "thumbv7em-none-eabi",
...
"examples/stm32f1/Cargo.toml",
...
rust-analyzer.cargo.featuresの部分を今回使う機能に合わせます。STM32F103C8のフィーチャーフラグ・モジュールはembassy_stm32に説明があります。
"stm32f103c8",
"time-driver-any",
"defmt",
"unstable-pac",
"exti",
"rt",
書き込みにはソースコード(blinky.rsなど)を開いて、#[embassy_executor::main]の下にRunというボタンが表示されるのでこれをクリックするとビルドと書き込みが行えます。
embassyの外でプロジェクトを開く際は、!#[no_std] Can’t find crate for ‘test’ エラーが表示されたときの対処法を元に、以下をプロジェクトルートの.vscode/settings.jsonに追加します。
{
"rust.target": "thumbv7m-none-eabi",
"rust.all_targets": false,
"rust-analyzer.cargo.target": "thumbv7m-none-eabi",
"rust-analyzer.checkOnSave": false
}
余談
気になるのはバイナリサイズですが、今回の単純なLチカで書き込みサイズは15KBでした。
フォーラム等を見ているとCよりはバイナリサイズが大きくなる傾向があるようです。それでもCubeIDEより全然マシです。