Rust Peripheral開発環境
前に戻る
用語解説(Terminology)
- BSP : Board Support Packages
- PAC : Peripheral Access Crates
- HAL : Hardware Abstruct Layer
Peripheral アクセス方法の整理
- 全体イメージ
- BSP, PAC, HAL の関係性
- use 宣言の際、bsp::hal::pac の順にシンボルが繋がっている
- HAL を具体的なチップの仕様に落としたのが、PAC
- HAL の上に、ボードの仕様をかぶせたのが、BSP
- そもそも HAL はハードの違いを吸収するためのものなので、ハードへのアクセスは PAC のシンボルを直接使うのではなく、できるだけ HAL の提供するAPIを使わなければならない
- Cargo.toml には、BSP を書けば良い。(rp-pico)
- BSP が rp2040-hal(PAC) を包含する。
- 実際には、BSP(rp-pico)自体には、全ピンの定義しか入っておらず、別途 PAC を付属している。
- raspi pico 向け crate のRustドキュメント
- Crateの包含関係の考え方
具体的な実装の問題点
- 現状の問題意識
- main()関数内で宣言されたペリフェラルの変数を、main()関数以外に持ち運ぶことができない。
- 引数に入れると、copy Traitがないのなんのと言われる
- 現状の対応
- ペリフェラルを変数に出来る型で、グローバル変数化する。
- グローバル変数は “static mut 大文字” と宣言
- 型は rust-analyzer などで調べる
- グローバル変数は、型の宣言を Option でくるみ、初期値を None にする。
- 初期化処理の中で、init関数などを呼んで、この変数を初期化する。
- unsafe などを頻繁に書かなくて済むように、このペリフェラルをアクセスする関数を別途作成しておく。
- 関数内は unsafe 内に if let Some(x) = &mut ペリフェラル名 {} と書き、xでアクセス
- 上記の関数を任意の箇所からコールして使う
ペリフェラル内のGenerics
pub struct I2C<I2C, Pins, Mode = Controller> {
i2c: I2C,
pins: Pins,
mode: PhantomData<Mode>,
}
- 上記の定義では、最初のI2Cが型であり、<>内にあるI2Cは、Genericsとして示す文字列
- 型指定にあるGenerics
- 例えば: static mut USB_DEVICE: Option<UsbDevice<hal::usb::UsbBus» = None;
- Option は None があるから
- UsbDevice<hal::usb::UsbBus> は ??
- インスタンス生成なので、UsbDevice の型宣言の中にある型引数に、UsbBus が入れられたと考えられる
- “A<B>” : AはGenericsを伴う型であり、中に特定の型Bを入れないと成り立たない。
- BにさらにGenericsがあった場合、上記と同じ考えを繰り返す
- 型定義でGenericsを使う場合、Trait で指示するが、Genericsで実インスタンスを作るときは、型名を指定しなければならない