Watchdogタイマ(WDT)は、マイコン(MCU)が停止または暴走していないかを見張るタイマーであり、Watchdogの意味通り「番犬」としての役割を果たす。
この記事では、Raspberry Pi Picoボードに内蔵されたWatchdogタイマをRust言語で動かしながら解説し、Watchdogの動作や活用方法、さらにRaspberry Pi Pico内の時間計測におけるWatchdogタイマの役割について具体的に理解することを目指す。
Watchdogタイマ
Watchdogタイマの基本動作
RustによるRaspberry Pi Picoの開発環境では、rp2040_hal
クレートにWatchdogタイマが実装されている。
後述する方法でWatchdogタイマを取得し、以下のコードを書くことで、WatchdogタイマによるMCUの監視をはじめることができる。
// Activate Watchdog with time limit of 1.05 seconds
watchdog.start(1_050.millis());
ここでは制限時間を1,050ミリ秒(=1.05秒)に指定して監視を開始した。
これは、次のような契約を意味する。
タイムアウトモード
1.05秒に1回はご飯をあげるよ。
よろしくね。
僕が寝落ちしない限りは大丈夫。
制限時間内にご飯をあげたとき
監視がはじまると、Watchdogタイマは制限時間のカウントダウンをはじめる。
この間にfeed
メソッドを呼ぶことで、Watchdogへの「餌付け」を行うことができる。
watchdog.feed();
watchdog.feed()
今後ともご贔屓に。
これにより、Watchdogタイマのカウントダウンが再び最初から実行される。
制限時間を超過したとき
...
ご主人が寝てる!リセットしてやる!
制限時間内にfeed
メソッドが呼ばれなかった場合、WatchdogはMCUをリセット(再起動)し、プログラムを最初から実行する。
つまり、一定時間MCUからの信号がないことで、MCUの停止を検知している。
このようなWatchdogの機能をタイムアウトモードという。
ウインドウモード
Raspberry Pi PicoのWatchdogタイマには実装されていないが、以下のように、より高度な監視を行う機能も存在する。
0.05~1.05秒に1回ご飯をあげるよ。
よろしくね。
…
ゴハンデスヨ!
ありがとう?
ゴハンデスヨ!
ご主人が暴走してる!リセットしなきゃ!
こちらでは、異常に短い間隔で信号が与えられたときにMCUが暴走したと判断する機能が追加されている。
このような機能をウインドウモードという。
Watchdogタイマの利用方法
Watchdogタイマの取得
rp2040_hal
クレートを用いて、Watchdogタイマは以下のコードで取得できる。
let mut pac = pac::Peripherals::take().unwrap();
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
Watchdogタイマによる時間計測の開始
Watchdogタイマによる監視を行う前に、Watchdogタイマが正確な時間を刻めるように設定し、時間の計測を開始する必要がある。
enable_tick_generation
メソッドを呼ぶことで、Watchdogがtick
の生成を開始する(時計の針を動かしはじめる)。
// Start Watchdog tick generation at 120 MHz
watchdog.enable_tick_generation((XTAL_FREQ_HZ / 1_000_000) as u8);
メソッドの引数にはWatchdogが参照するクロック(外部クリスタル)の周波数clk_ref
をMHz単位で表したものを与える。
Raspberry Pi Picoでは、clk_ref
が
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
に設定されているため、引数の値は12MHzとなる。
enable_tick_generation
メソッドを呼ぶのではなく、Clock
を取得(初期化)することによってもWatchdogによる時間計測を開始できる。
let clocks = hal::clocks::init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
なぜならば、Clock
を初期化する際に用いたinit_clocks_and_plls
関数の内部で、enable_tick_generation
メソッドが実行されているためである。
WatchdogとTimerの関係
Raspberry Pi PicoのTimer
は、Watchdogにおけるtick生成を参照して時間の計測を行っている。
そのためWatchdogタイマを使用しない場合であっても、Timer
を使用する際にはenable_tick_generation
メソッドかinit_clocks_and_plls
関数でWatchdogタイマにおける時間計測を開始しておく必要がある。
サンプルコード
このコードでは、Watchdogタイマによるリセットを利用して、Raspberry Pi Picoの内部LEDの点滅タイミングを変えている。
- 2秒間LEDを点灯
- 1HzでLEDを点滅(Watchdogタイマは正常に「餌付け」される)
- 5HzでLEDを点滅(Watchdogタイマへの「餌付け」を行わない)
- 1.05秒後にWatchdogタイマがリセット信号を発し、プログラムを最初から実行する(1.に戻る)
Comments