stm32-rsのクレートを用いてSTM32系マイコンボードのお手軽Rustプログラミング
Rustが組込み開発で注目されていて、すでによくできたドキュメント類が用意されています。
また、ペリフェラルドライバのクレートがいくつか用意されています。
STM32系であれば、stm32-rsコミュニティが管理するクレートを用いれば、USARTやLEDなどのモジュールをお手軽に利用できます。
今回は自分の手元にあるNUCLEO-F429ZI用にstm32f4xx-hal
クレートでシリアル通信を例に解説します。
実際にシリアル通信のループバックを組んだレポジトリを以下に用意しました。
garasubo/stm32f4xx-hal
依存するクレート
このレポジトリで使用されているクレートから説明していきます。レポジトリ内のCargo.toml
を参照してください。
-
panic-halt
:no_std
のプログラミングではパニックした際の関数をこちらから与える必要があります。panic-halt
は無限ループで止まるパニック関数を提供します -
cortex-m-rt
:Cortex-Mマイコン向けにno_std
のプログラミングのためのマクロなどを提供してブートストラップを助けてくれます。例外ハンドラの登録もできますが、今回は利用していません -
embedded-hal
:Rust Embeddedグループにより組込みでよく使うペリフェラル向けのトレートが定義されています。これに沿ってペリフェラルドライバを組めば他の場所での再利用が見込めます -
stm32f4xx-hal
:stm32f4xx向けのペリフェラルドライバの実装が提供されています。features
によってボードを切り替えることができます。rt
はcortex-m-rt
との連携のため必要です。ベースはsvd2rust
で作られたコードになっています。
コードの解説
src/main.rs
について解説します。1、2行目はベアメタルプログラミングではお馴染みの標準ライブラリを使わないための宣言とmain関数が存在しないことを宣言するためのものです。
extern crate panic_halt
によってパニック関数を取り込んでいます。
cortex_m_rt::entry
属性を付与されたmain
関数はクレート側でbssセクションの初期化等の最低限のブートストラップ処理をした後実行されることになります。
Periphrals::take()
でシングルトン化されたペリフェラルインターフェースが手に入れられます。今回は他で使う箇所がないのでunwrap
しても大丈夫です。
今回シリアル通信に使うのはUSBケーブルから利用できるUSART3で、PD8をTX、PD9をRX用のピンとして利用します。
into_alternate_af7
とすることで、そのピンに対してalternateモードを有効化させることができます。af7
がUSART用のモードです。
この辺の機能はstm32f4xx_hal::gpio::GpioExt
によりsvd2rustで定義された型を拡張させて使っています。
更に、この結果には型がついていて、これにより間違った設定のピンをシリアル通信に使おうとすることを型レベルで強制することができています。
config
変数はシリアル通信の通信速度などの設定です。デフォルトのボーレートだといつも自分がシリアル通信用に使うminicomの設定と合わなかったので、ボーレートのみ上書きしています。
クロックの設定はデフォルトのものを使っています。
これらをSerail::usart3
に渡します。第2引数のpins
はTX用のピンとRX用のピンが渡されることが期待されます。
しかし、渡されるピンには型がついていて、使えるピンにのみこの関数は定義されているので、間違ったピンを渡してもコンパイルエラーで落ちることでしょう。
最後のループはシリアルから1バイトだけ文字を読み込みそれをそのまま返すだけの無限ループになっています。
そのほか
memory.x
はcortex-m-rt
のために必要です。フラッシュのメモリ領域とRAM領域のアドレスを教えてあげないとちゃんとリンクできないということです。
また、.cargo/config
でリンカースクリプトを指定して、デフォルトのターゲットも変更しておくと便利でしょう。link.x
はcortex-m-rt
から提供されます。
まとめ
今まで自分のブログでは他のクレートをあまり使わない形での組込みプログラミングを紹介していましたが、今回はがっつりとクレートをつかうものを紹介しました。
今回はzenn.devというサービスのテストを兼ねて簡単めな記事を書いてみました。
Discussion