haphysics blog - 幸福の物理ブログ

みんなに物理と工作と幸福をお届けするのだァ~!

Rustに入門するためにSTM32でLチカしてみた

近年、C++の後継となる言語としてRustと呼ばれるプログラム言語が注目されている。 研究やアルバイトではC++を書いているので、今までRustを使う機会は全くなかった。 だけど、食わず嫌いはいけないなと思い、趣味でRustを書くための動機を考えてみた。

そして、組み込み開発をRustでやるのが良さそうという結論に至った。 実は、STM32をHALライブラリ無しで動かそうと、ARMアセンブリを読んだり、C++のTMPでLチカしてみたりと、裏でいろいろやっていたのだ。 どうせなら、この取り組みで使っているC++をRustに置き換えれば、Rustへの理解につながるのではないか?というワケ。

そこで、Rustを使った組み込み開発の先行研究をサーベイしてみた。 すると、いくつかの記事を見つけることができた。

中でも、あるレジスタへの操作はその時点で適切か?をコンパイル時に検証する、ある種の有限状態マシンがこんなに簡潔に書けることを知って一目惚れしてしまった。 私の知ってる限りでは、C++で有限状態マシンを書くときには、全ての状態遷移をテーブル状に保持する型を用意する必要があり、ここまで簡潔に書くことができない。

また、japaric氏という方が、Rustを使った組み込み開発の先駆者であるということも知った。 Rustで組み込み開発をするときは、この方の情報に注目するのが良さそうだ。

Rustで組み込み開発をする十分な動機や近年の動向を知ることができたので、STM32の開発テンプレートを参考に、STM32F4DISCOVERYでLチカしてみた。

インストール

私の使用しているOSはLinuxディストリビューションはArch Linuxである。 したがって、他の環境でLチカするためには、適宜読み替えが必要になる。 下記文献を参照されたい。

Introduction - The Embedded Rust Book

Rust

まずはRustをインストールする。 公式サイトによれば、rustupというツールチェーンマネージャをインストールすれば良い。

$ yay -S rustup

この時点で

$ rustc -V

$ cargo -V

をすると

error: no default toolchain configured

というエラーメッセージが出力された。 原因は、文字通りデフォルトのツールチェーンが設定されていないからだ。 そこで、rustupで安定版のツールチェーンを設定する。

$ rustup default stable

最新版のツールチェーンのダウンロードが始まり、しばらくすると適切な設定がされる。

$ rustc -V
rustc 1.43.0 (4fb7144ed 2020-04-20)
$ cargo -V
cargo 1.43.0 (3532cf738 2020-03-17)

Cortex-Mターゲット向けツールチェーン

Cortex-Mターゲット向けのツールチェーンをインストールする。

今回使うSTM32F4DISCOVERYは、FPU付きCortex-M4 (Cortex-M4F) を搭載したマイコンを使っている。

STM32F407VGT6 microcontroller featuring 32-bit ARM®Cortex®-M4 with FPU core URL: https://www.st.com/en/evaluation-tools/stm32f4discovery.html

したがって、Cortex-M4Fターゲット向けのツールチェーンをインストールすれば良い。

$ rustup target add thumbv7em-none-eabihf

cargo-binutils

"The Embedded Rust Book"によると、cargo-binutils というものをインストールする必要がある。

これは一体何なのか?なぜこれが必要なのか?未だに分かってないです…。

$ cargo install cargo-binutils
$ rustup component add llvm-tools-preview

GNUデバッガー

ARM EABIターゲット向けのGNUデバッガーをインストールする。

$ yay -S arm-none-eabi-gdb

OpenOCD

デバッグやFlashROMへの書き込みのために使用する、OpenOCDをインストールする。

$ yay -S openocd

STM32F4DISCOVERYをOpenOCDに対して、ルート権限なしで使うためには、udevルールを設定する必要がある。 下記リンク先を参照されたい。

  1. https://rust-embedded.github.io/book/intro/install/linux.html#udev-rules
  2. https://wiki.archlinux.org/index.php/Udev#About_udev_rules

設定の際には、ベンダーIDとデバイスIDが必要である。 これらは、STM32F4DISCOVERYをPCに接続した状態で lsusb コマンドを使えば、知ることができる。 例えば、

$ lsusb
(...中略...)
Bus 001 Device 002: ID 0483:3748 STMicroelectronics ST-LINK/V2

であれば、ベンダーIDは0483、デバイスIDは3748である。

コード

Lチカするプログラムは、GitHubに公開した通りである。

プログラムは、このリポジトリを参考にした。

このプログラムは、以下の4つのクレートを利用している。

使い方

  1. STM32F4DISCOVERYをPCにつなげる。
  2. ターミナルでOpenOCDを起動する。
  3. 別のターミナルで、 cargo run を実行する。

これにより、openocd.gdbに書かれたコマンドが実行される。 つまり、マイコンにLチカプログラムが書き込まれ、デバッガが起動する。

OpenOCD + GDB in VSCode
OpenOCDとGDBVSCode上で立ち上げたときのスクショ

もし、STM32F4DISCOVERYのリセットボタン(黒いタクトスイッチ)を押したならば、4つのLEDが全て約1秒周期で点滅する。

次回は…

これで、「RustでLチカする」という目標は達成できた。 しかし、なぜLチカするのか?は明らかになっていない。 したがって、現在、ライブラリを読んで動作原理の理解に努めている。 同時に、Rustの機能や文法なども学んでいる。

次回はこの「なぜLチカするのか?」への問いに答えたい。