mbedでウォッチドッグタイマを使う

mbedでいろいろな機能を実装していたらメモリリークが起きているのか不定期に動作が停止するようになってしまいました。そこでウォッチドッグタイマを使って自動でリセットをかけるようにしてみました。

ウォッチドッグタイマはCookbookのWatchDog Timerにサンプルがあります。
http://mbed.org/cookbook/WatchDog-Timer

また、フォーラムの方でもいくつかサンプルコードを見ることができました。
http://mbed.org/forum/mbed/topic/508/


フォーラムのSimon Ford氏(NXPの中の人?)のコードがさっぱりしていて見やすかったのでこれでテストしてみました。

#include "mbed.h"

Serial pc(USBTX, USBRX);

class Watchdog {        // Watchdogクラス
public:
    void kick(float s) {
        LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
        uint32_t clk = SystemCoreClock / 16;    // WD has a fixed /4 prescaler, PCLK default is /4 
        LPC_WDT->WDTC = s * (float)clk;         
        LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset        
        kick();
    }
    
    void kick() {
        LPC_WDT->WDFEED = 0xAA;
        LPC_WDT->WDFEED = 0x55;
    }
};

Watchdog w;

int main() {
    printf("Hello World!\n");
    w.kick(2.5);    // ウォッチドッグタイマを2.5秒にセット

    int hang = 0;
    while(1) {
        printf("loop...\n");
        wait(0.1);
        
        if(hang == 10) {        // ループ10回目で強制的に無限ループに入れる
            while(1);
        }

        w.kick();
        hang++;
    }
}

Watchdogクラスのkick(float s)メソッドでウォッチドッグタイマの秒数をセットし、kick(void)メソッドでタイマをクリア。

このコードを実行してみると、

Hello World!
loop...
loop...
loop...
loop...
loop...
loop...
loop...
loop...
loop...
loop...
loop...
(数秒の間)
Hello World!
loop...
loop...
loop...
loop...

という実行結果が得られ、無限ループに陥った後に自動でリセットをかけてまたmain()の最初から動作していることが分かります。

このウォッチドッグタイマを自分のメモリリークによる動作停止が疑われるソースに導入してみたところ、ちゃんと動作停止後にリセットがかかりました。


メモリリークの解決はできていませんが、とりあえずウォッチドッグタイマでの自動的な復帰ができるようになりました。