ウォッチドッグは優れていますが、プログラムやシステムが簡単に適合しない場合は、面倒です。(一般的に)次のようなコードがある場合に最適に機能します。
Watchdog_init();
hardware_init();
subsystem1_init();
subsystem2_init();
subsystem3_init();
...
subsystemN_init();
forever {
Watchdog_tickle();
subsystem1_work();
subsystem2_work();
subsystem3_work();
...
subsystemN_work();
}
非常に多くの場合、これが機能するようにプログラムを設計できます。一般に、それは非常に簡単です (ただし、完全ではありません)。
しかし、あなたのような場合、これはうまくいきません。ウォッチドッグが愛撫されるかどうかを制御するために満たす必要があるさまざまな条件を持つフレームワークを設計および作成する (またはおそらくライブラリを使用する) 必要があります。ただし、これは非常に難しい場合があります。このコードの複雑さ自体がエラーを引き起こす可能性があります。ウォッチドッグ フレームワークを除いて完璧なアプリケーションを作成しても、プロジェクトが何度もリセットされる可能性があります。または、すべてのコードが正しくなく、ウォッチドッグを継続的にかわいがり、リセットされない可能性があります。
より複雑な状況を処理するために上記のコードを変更する 1 つの良い方法は、subsystemX_work 関数を状態に合わせて変更することです。これは、関数内の静的変数を使用するか、関数ではなく関数ポインターを使用して行うことができ、実行される実際の関数を変更して、そのサブシステムの現在の状態を反映させることができます。各サブシステムはステート マシンになります。
意図的な長い待機を回避するもう 1 つの方法は、実行時間の長い関数を短い部分に分割することです。それよりも:
slow_device_init();
Watchdog_tickle();
あなたがすることができます:
slow_device_init_begin();
Watchdog_tickle();
slow_device_init_finish();
Watchdog_tickle();
そして、これを拡張して、次のようにしてウォッチドッグ タイマーを延長します。
slow_device_init_begin();
for ( i = SLOW_DEV_TRIES; i ; i--) {
Watchdog_tickle();
if (slow_device_init_done()) {
break;
}
}
Watchdog_tickle();
それでも、ますます複雑になる可能性があります。多くの場合、満たされる条件をチェックし、これらの条件に基づいてウォッチドッグをかわいがるかどうかをチェックするウォッチドッグ デリゲートを作成する必要があります。これは非常に複雑になり始めます。サブシステムの正常性をテストするために呼び出すメソッド/関数を持つサブシステムごとにオブジェクトを作成することで実装できます。ヘルス メソッドは非常に複雑になる可能性があり、そのサブシステムの状態が変化すると変更されることもありますが、コードが正しいことをできるだけ簡単に検証できるように、また、サブシステムが機能するためには、健康の測定方法を変更する必要があります。
一部のコードが定期的に実行されることを確認できる場合は、サブシステムのローカル ウォッチドッグとして機能する各サブシステムの整数を使用できます。一部のコード (タイマー割り込みハンドラー内にある可能性がありますが、必ずしもそうとは限りません) は、各サブシステムの変数をデクリメントしてテストします。いずれかのサブシステムで 0 に達した場合、ウォッチドッグはティックリングされません。
Watchdog_periodic() {
for_each subsustem in subsystem_list { // not C, but you get the idea
if ( 0 > --(subsystem->count_down) ) {
// Do something that causes a reset. This could be returning and not petting
// the hardware watchdog, doing a while(1);, or something else
}
}
Watchdog_tickle();
}
次に、各サブシステムは、その count_down を正の値に設定することにより、さまざまな時間、独自の count_down をくすぐることができます。
また、実際のリセットを行うためにハードウェア ウォッチドッグを使用している場合でも、これは実際には単なるソフトウェア ウォッチドッグであることに注意してください。
また、ウォッチドッグ フレームワークが複雑になるほど、そのフレームワークでエラーが発生する可能性が高くなり、他のコードでエラーが発生して不適切に動作する可能性が高くなることにも注意してください。たとえば、次のようなポインター エラーです。
int x;
fscanf(input, "%i", x); // Passed uninitialized x rather than address of x
一部のサブシステムの count_down 値が設定される可能性があり、その結果、ウォッチドッグが必要なときに噛むことができなくなる可能性があります。