①LED、Buttonの型、グローバル変数宣言

このコード部分の話

type GreenLedPin =
    hal::gpio::Pin<hal::gpio::bank0::Gpio22, hal::gpio::FunctionSioOutput, hal::gpio::PullDown>;
type RedLedPin =
    hal::gpio::Pin<hal::gpio::bank0::Gpio20, hal::gpio::FunctionSioOutput, hal::gpio::PullDown>;
type OrangeLedPin =
    hal::gpio::Pin<hal::gpio::bank0::Gpio21, hal::gpio::FunctionSioOutput, hal::gpio::PullDown>;
type ButtonPin =
    hal::gpio::Pin<hal::gpio::bank0::Gpio23, hal::gpio::FunctionSioInput, hal::gpio::PullUp>;
type DelayTimer = hal::Timer;
type LedAndButton = (GreenLedPin, RedLedPin, OrangeLedPin, ButtonPin, DelayTimer);
static GLOBAL_PINS: critical_section::Mutex<core::cell::RefCell<Option<LedAndButton>>> =
    critical_section::Mutex::new(core::cell::RefCell::new(None));

グローバルな変数

static GLOBAL_PINS: critical_section::Mutex<core::cell::RefCell<Option<LedAndButton>>> =
    critical_section::Mutex::new(core::cell::RefCell::new(None));

GLOBAL_PINSは、関数間でPin情報の変数を参照変更するためのグローバルな変数です。

関数を超えて変数の所有権、参照、変更のやり取りをするために、staticcritical_sectionMutexRefCellを利用します。

critical_sectionとは

critical_sectionは、並行処理で必要とされるグローバルな変数を制御するのに役立つ組み込み用のクレートです。 MutexRefCellは、stdが提供していますが、std_no環境である組み込みでは利用することができません。

そこでcritical_sectionが代わりにMutexRefCellを提供してくれています。

ジェネリック<T>

hal::gpio::Pin<><>は、ジェネリックと言われるもので、構造体の中で異なる複数の型の値を保持できる定義です。

struct Container<T>{
    value: T
}

Tが任意の型になります。

hal::gpio::Pin<hal::gpio::bank0::Gpio22, hal::gpio::FunctionSioOutput, hal::gpio::PullDown>は、hal::gpio::Pin<>というPinの型で、hal::gpio::bank0::Gpio22hal::gpio::FunctionSioOutputhal::gpio::PullDownの3つを指定しており、GPIO22、SioOutput、PullDownのPin設定であることを意味しています。

type

type GreenLedPin = hal::gpio::Pin<...>;

これはhal::gpio::Pin<...>GreenLedPinという名前に省略するよという意味です。 このtypeを定義することで、グローバル変数の記述が読みやすくなります。

static

staticは、静的変数を定義するために使われます。静的変数はプログラムの全体で一度だけ初期化され、プログラムの終了まで存在します。

Rustでは、static変数自体は変更不可能(イミュータブル)ですが、内部のデータが変更可能(ミュータブル)にすることが可能です。 GLOBAL_PINSは、critical_section::Mutexcore::cell::RefCellを使って内部のデータを安全に変更できるようにしています。

critical_section::Mutex

Mutexは、変更可能(ミュータブル)な変数として扱うためのものです。 そして、複数の関数から安全にアクセスできるようにするためのロック機構が備わっており、同時に複数の関数がデータにアクセスすることを防ぎます。

core::cell::RefCell

RefCellは、実行時に変更可能(ミュータブル)な借用をチェックするためもので、同じスコープ内での複数の変更可能(ミュータブル)な参照を可能にします。

Option

変数でNoneを扱うためのものです。 次のようにi32Optionでラップすることで、Noneを入れることができます。

let val: Opiton<i32> = None

Noneとは

Noneとは、「値が存在しない」ことを示す値です。