プログラムの大枠

プログラムの大枠は、次の通りです。

graph TD
    A[main] --> C[mainの何もしない無限ループ]
    C -->|"GPIO割り込み(Button割り込み)"| B[IO_IRQ_BANK0]
    B -->|IO_IRQ_BANK0の処理完了| C

main関数は、Pinの設定、割り込み設定を行い最後に何もしない無限ループで終わります。 Button割り込みがなければ、常に何もしない無限ループで待機し続けます。

Button割り込みがあった時に、IO_IRQ_BANK0関数が実行され、LEDが点灯し処理終了後にmain関数の何もしない無限ループに戻ります。

つまり割り込みがない限りは、何もしないプログラムになります。 また前章のボタンの入力をmain関数で検知する処理と比較して、GPIO割り込みというハードウェアとして備わっている機能に任せることができため、高速化つ確実にButtonを検知できます。

関数間でやり取りするためのグローバル変数の必要性

本章の処理では、main関数とIO_IRQ_BANK0関数の2つの関数がそれぞれ独立して実行されます。

Rustでは、main関数から別の関数を実行する場合は所有権を渡してPinの参照変更をし、LEDを光らせます。 今回の場合は、IO_IRQ_BANK0関数をmain関数が呼び出すのではなく、GPIO割り込み(Button割り込み)が呼び出し実行します。 そのため、main関数から所有権をIO_IRQ_BANK0に所有権を貸すことができません。 そこで次のようなグローバルな変数を宣言して、関数間の所有権と変数の参照変更をできるようにしています。

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