⑥割り込み処理
このコード部分の話
#[hal::pac::interrupt]
fn IO_IRQ_BANK0() {
static mut LED_AND_BUTTON: Option<LedAndButton> = None;
if LED_AND_BUTTON.is_none() {
critical_section::with(|cs| {
*LED_AND_BUTTON = GLOBAL_PINS.borrow(cs).take();
});
}
if let Some(gpios) = LED_AND_BUTTON {
let (green_led, red_led, orange_led, button, timer) = gpios;
if button.interrupt_status(hal::gpio::Interrupt::EdgeLow) {
info!("Button pressed");
red_led.set_low().unwrap();
info!("green");
green_led.set_high().unwrap();
timer.delay_ms(2000);
green_led.set_low().unwrap();
info!("orange");
for _ in 1..4 {
orange_led.set_high().unwrap();
timer.delay_ms(500);
orange_led.set_low().unwrap();
timer.delay_ms(500);
}
orange_led.set_low().unwrap();
info!("red");
red_led.set_high().unwrap();
button.clear_interrupt(hal::gpio::Interrupt::EdgeLow);
}
}
}
hal::pac::interrupt
関数を割り込みの関数として表すマクロです。
次のIO_IRQ_BANK0
を割り込みの関数として扱うことを意味しています。
IO_IRQ_BANK0
IO割り込みとして予約されている関数です。
割り込み登録をしたIO_IRQ_BANK0
に紐づく関数です。このように割り込みの関数は、割り込みによって関数名が決められています。
割り込み関数内での借用
static mut LED_AND_BUTTON: Option<LedAndButton> = None;
LED_AND_BUTTON
がstatic
な変数として用意されます。
static
は、プログラムの最初に初期化されてからプログラムが終了するまで残り続ける変数を意味しています。
そしてIO_IRQ_BANK0
の中で宣言されるということは、この関数が呼び出され終了した後もLED_AND_BUTTON
は残り続け、再びIO_IRQ_BANK0
が呼び出されると残り続けているLED_AND_BUTTON
がそのまま再利用されます。
if LED_AND_BUTTON.is_none() {
critical_section::with(|cs| {
*LED_AND_BUTTON = GLOBAL_PINS.borrow(cs).take();
});
}
IO_IRQ_BANK0
内で宣言したLED_AND_BUTTON
がNone
だった時に、Critical Sectionを借用し、GLOBAL_PINS
をLED_AND_BUTTON
に入れる処理です。
LED_AND_BUTTON
の前に*
がついていますが、これはC言語のポインターに近い概念です。
LED_AND_BUTTON
は、static mut
になっていますがRustが自動的に&mut
と解釈するため、これをmut
として扱う(&
を外す)ために*
が必要になります。
割り込みされたか確認
if button.interrupt_status(hal::gpio::Interrupt::EdgeLow) {...}
IO_IRQ_BANK0
は、GPIOの割り込みがあったと時に動作し、それがどのGPIOのPinであったか認識することはできません。
このif
文は、button
のPinでEdgeLow
の割り込みがあったか確認をしています。
もし割り込みがあった場合は、{...}
の処理を実行します。
割り込み情報のクリア
button.clear_interrupt(hal::gpio::Interrupt::EdgeLow);
clear_interrupt
でbutton
のPinに割り込みがあった情報をクリアします。
今回は、割り込みを検出するPinが1つしなかったため、必要性を感じないですが、複数の割り込みを検知するPinがあった場合、このclear_interrupt
をしないとすべてのGPIO割り込みでbutton
のPinの処理が実行されてしまいます。
そのため、このclear_interrupt
の処理は必須になります。