WatchDogTimerを実現するには

最終更新日:2022/5/11

※[2022/05/11]WDTでうまく対応出来ないケースに出くわしました。

早々に検討しなければいけない事があります。WatchDogTimerの実現方法です。

https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__watchdog.html に SDKドキュメントとして情報掲載されています。
これによると 『RP2040にはHWウォッチドッグタイマーが組み込まれています。』とありますのでどの開発環境でも実現出来るのかと思います。

時間はプログラム内容によりますが、Loop()の先頭でresetして、そのループ実行が設定時間内に実行されていればTimerReset、間に合わなければrestartになるようにすれば良いのかと考えます。
アールFフィルハワー氏版のドキュメントにはWDTの記述は無かったと思います。暫し調査します。

ArduinoのスケッチにCやインラインアセンブラのコードを含めても許されます。Arduinoのコーディングルールでは避けるべきなのでしょう。Wrapしたライブラリを作って使う方がいいのかもしれません。でも、直接使う事で明確に扱う事も出来るともいえそうです。


PiPicoの資料にはhardware_watchdog機能として以下のAPIが紹介されています。

void 	watchdog_reboot (uint32_t pc, uint32_t sp, uint32_t delay_ms)

ウォッチドッグタイムアウト時に実行するアクションを定義します。

pc ゼロの場合、標準のブートが実行されます。
ゼロ以外の場合、これはリセット時にジャンプするプログラムカウンターです。
sp pcがゼロ以外の場合、これは使用されるスタックポインタになります。
delay_ms 初期負荷値。最大値0x7fffff、約8.3秒。

void 	watchdog_start_tick (uint cycles)

ウォッチドッグティックを開始します。

cycles
これは、XOSC入力に適用されたときに1MHzクロックを生成する分周器である必要があります。したがって、XOSCが12MHzの場合、これは12である必要があります。

void 	watchdog_update (void)

watchdog_enableで設定された時間でウォッチドッグカウンターをリロードします。

void 	watchdog_enable (uint32_t delay_ms, bool pause_on_debug)

ウォッチドッグを有効にします。

delay_ms watchdog_updateが呼び出されずにウォッチドッグが再起動するまでのミリ秒数。最大0x7fffff、これは約8.3秒です
pause_on_debug デバッガーがコードをステップ実行しているときにウォッチドッグを一時停止する必要がある場合

bool 	watchdog_caused_reboot (void)

watchdog_enableは最後の再起動を引き起こしましたか?

true ウォッチドッグタイマーまたはウォッチドッグフォースが最後の再起動を引き起こした場合
false 最後の電源投入時のリセット以降にウォッチドッグの再起動がなかった場合。パワーオンリセットは、通常、電源の入れ直しまたは実行ピン(リセットボタン)の切り替えによって発生します。

bool 	watchdog_enable_caused_reboot (void)

watchdog_enableは最後の再起動を引き起こしましたか?

true ウォッチドッグタイマーまたはウォッチドッグ強制が発生した場合、watchdog_enableが呼び出された後に最後の再起動とウォッチドッグの再起動が発生しました
false 最後の電源投入時のリセット以降にウォッチドッグの再起動がなかった場合、またはwatchdog_enableが呼び出された後のウォッチドッグのタイムアウトが原因でウォッチドッグの再起動が発生しなかった場合。パワーオンリセットは、通常、電源の入れ直しまたは実行ピン(リセットボタン)の切り替えによって発生します。

uint32_t 	watchdog_get_count (void)

ウォッチドッグがチップをリブートするまでのマイクロ秒数を返します。

uint32_t
ウォッチドッグがチップをリブートするまでのマイクロ秒数。


テストコードの説明です。
テストコードはWDT=7秒に設定し、Loop()内でdelay()で待機時間を設定実行します。7秒待機までは普通に実行されますが、8秒待機の実行途中でWDTのTimeUpが働きReBootが掛かります。PiPicoの場合はビープ音が鳴るようです。
※ReBoot後にシリアルモニタのリンクが切れてしまうのでシリアルモニタでのデバッグは困難です。そのためLED等での点灯で確認出来る術を用意する必要があります。

/*
 * 2022年4月5日 T.Wanibe
 * Arduino-Pico環境でWDT(WatchDogTimer)の動作確認を行う
 * 残念ながらArduino-PicoドキュメントにWDTの記述はないが、
 * PiPicoSDKにWDTの記述はある。直接Call出来ると思うのでまずは確認
 * シリアルモニタ出力では再起動後の接続に問題が出るので
 * 最大2093056バイトのフラッシュメモリのうち、スケッチが59320バイト(2%)を使っています。
 * 最大262144バイトのRAMのうち、グローバル変数が11160バイト(4%)を使っていて、ローカル変数で250984バイト使うことができます。
 */
extern "C" {
#include <hardware/watchdog.h>
};
int             count           =       0;
uint32_t        delay_ms        =       7000;                   //8秒 最大8.3秒
bool            pause_on_debug  =       false;                  //デバッガーがコードをステップ実行しているときにウォッチドッグを一時停止する必要があるか?
int             led_state       =       HIGH;                   // high / low state of led
//----------------
void setup(){
        Serial.begin(115200);
        //while(!Serial);                                       //デバッグ用
        pinMode(LED_BUILTIN, OUTPUT);                           // Led as output on pin 14
        //watchdog_enable(delay_ms,pause_on_debug);
        watchdog_reboot(0,0,delay_ms);
}
//----------------
void loop(){
        if (watchdog_caused_reboot()){
                //Serial.printf(F("Rebooted by Watchdog!\n"));  //F()マクロがなぜかコンパイルが通らない
                Serial.printf("Rebooted by Watchdog!\n");
                digitalWrite(LED_BUILTIN, led_state);
                led_state = !led_state;
        }else{
                //Serial.printf(F("Clean boot\n"));
                Serial.printf("Clean boot\n");
        }
        watchdog_update();
        int waitTime    = count * 1000;
        //Serial.print(F("待ち時間[Sec]="));Serial.println(count);
        Serial.print("待ち時間[Sec]=");Serial.println(count);
        delay(waitTime);
        count++;
}


WDTでうまく実現出来ない現象を確認しました。対策を検討中です。

現状WDTではLoop()の先頭で一定時間内に帰還出来ればUpdateを掛けて対処しています。これはこれでうまくゆくはずでしたが、PiPicoにNICを接続してWebServerを構築していたところ、WDTにより再起動になる事は無いのにブラウザからアクセスに対するタイムアウトが発生してしまいます。マイコン再起動後は問題無いのですが一日も経たずにブラウザでのアクセスに反応がなくなってしまいます。
原因が判れば対策も出来ます。が、デバッグが困難です。とりあえずLoop()の動作についてはBuiltInLEDの点滅で判断し、Timer割込は時刻表示の更新で判断出来るよう、プログラムを弄りました。この状態で動作していたところ、ブラウザからのアクセスが出来なくなった時点でLEDの状態を確認したのですがBuiltInLEDは特に変わりなく点滅しており、時刻表示も正しい時刻を刻んでいます。

コマンドラインからpingを確認したら、応答がありません。W5500はping応答が無い場合はアプリケーション層での対処は要検討です。定期的にセルフセンド/ループバック127.0.0.1を実行してRequest timed outになったらNICをRESETするかマイコンをrebootするのが良いのかと考えました。
この仕様をプログラムに組み込むのですが、それなりに事前検討が必要です。検討を続けます。
この件、NTPサーバについての検討 に引き継ぎます。


戯言(nonsense)に戻る


問い合わせ頁の表示


免責事項

本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。

本ソフトウエアの著作権はToolsBoxに帰属します。
本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。

商標・登録商標

Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
I2Cは、NXP Semiconductors社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。