[概要]
78K0/Kx2には従来のウォッチドッグ・タイマを機能強化したものが搭載されています。強化された機能のうちで以下の機能は全く新規のもので、これらはウォッチドッグ・タイマとして特に設定を行わないでも動作します。
- 命令をフェッチできないアドレスからフェッチした場合にリセット発生
- データをアクセスできないアドレスをアクセスした場合にリセット発生
これ以外に
- 特定の期間以外でウォッチドッグ・タイマをクリアしようとするとリセット発生
(ウィンドウ機能)
などの特徴があります。
ウォッチドッグ・タイマの基本的な内容については、「
ウォッチドッグ・タイマの基本」を参照してください。
[使い方の基本]
プログラムが正しく動作しているかを確実に把握することは困難なことです。ウォッチドッグ・タイマを使う場合にも、
"
どうなっていれば正しく動作しているか"を最初に定義することが必須です。
このためには、まずプログラムが正常な動作をしているときにはどのような処理フローで動作しているかを把握する必要があります。いろんな場合分けが存在するような場合には大変かもしれませんが、これがきちんと把握できないと仕様の追加が必要になったときや評価項目設定等が大変になります。通常、プログラムを開発する場合には、ここまでは問題なくできるはずです。逆に、この段階で引っかかってしまうようだと、プログラムの開発方法に問題が考えられ、プログラムが完成した(と思った)としても、ディバグ段階でトラブルが多発する可能性が大いに考えられます。
次に、正常な動作時の処理時間やタイミングの見積もりを行います。特に、非同期に発生する割り込み処理がある場合には全体の処理時間が変動しますので注意が必要です。その比率が大きい場合には、ウォッチドッグ・タイマのウィンドウ機能は使えないと考えた方がいいでしょう。
[処理時間解析]
以下に処理時間解析の例を示します。
処理内容のリスト
| 処理番号 | 処理内容 | 処理時間 |
| 1 | 初期化処理 | 100μs |
| 2 | メイン共通処理 | 1ms/100μs |
| 3 | メイン処理1 | 20ms |
| 4 | メイン処理2 | 30ms |
| 5 | 共通のサブルーチン | 100μs |
| 6 | メイン処理1のサブルーチン | 200μs |
| 7 | メイン処理2のサブルーチン | 300μs |
| 8 | シリアル受信割り込み | 10μs |
| 9 | シリアル送信完了割り込み | 5μs |
| 10 | タイマ割り込み(1ms周期) | 50μs |
| 11 | A/D完了割り込み | 5μs |
初期化が完了したら、メイン共通処理を行い、そこでタイマを起動し、その割り込みを許可しておきます。また、シリアル通信の割り込みを許可しておきます。
メイン共通処理はその後の処理要求を待つ部分です。通常はタイマ割り込みにより起動されて、タイマ割り込み処理後、メイン処理1の処理要求確認、メイン処理2の起動タイミング確認を行い、何も処理要求がなければ100μsの処理後はHALTモードに入って次のタイマ割り込み待ちになるものとします。処理要求はシリアル通信により送られてくるものとし、シリアル受信割り込みでは送られてきたデータをリングバッファに保存するだけとします。シリアル通信は最短では520μs間隔(19.2kbps相当)で受信割り込みが発生することがあり、メイン共通処理ではHALTモード中にこの割り込みでHALTが解除された場合には再度HALTに入るものとします。タイマ割り込みでの起動により処理要求が認識され、その解析を行い1msの処理を行いメイン処理1またはメイン処理2に分岐します。処理要求の解析ではサブルーチンを2回コールするものとします。
メイン処理1では必要な処理を行い、その結果のステータス10バイト分をシリアル通信によって送信するものとします。メイン処理1ではサブルーチンを10回コールし、シリアル送信は割り込みを使用することで、メイン処理1と並行して実行できるものとします。
メイン処理2は一定の周期で起動され、8チャネルのアナログ信号を読み込んで、A/D変換とを処理するためにサブルーチンを8回コールします。サブルーチンではA/Dの割り込み処理時間を含めて300μsの処理時間がかかるものとします。また、このサブルーチン以外ではA/Dコンバータは動作しないものとします。
このような場合に、動作としては大きく3つに分けられます。これらは排他的に動作するものとします。
(1)処理要求待ち
メイン共通処理での処理要求待ちで、1msのタイマ割り込みで起動されます。タイマ割り込み処理を含めて150μsの期間処理を行い、残りの期間はHALTモードで停止します。
処理要求があった場合には、タイマ割り込みで起動されたメイン共通処理では1ms及びサブルーチンでの処理(100μsが2回)及び次のタイマ割り込み処理の50μsが必要になります。これはタイマ割り込みの頭からみると、1.3msとなります。シリアル受信割り込みはこの間に0回〜最大では3回入る可能性がありますので、これを含めると最大では1.33msかかることになります。シリアルの処理時間比率は小さいので、それを無視した場合の処理要求確認から実際の処理がスタートするまでのタイムテーブルは以下のようになります。
(2)メイン処理1の実行
メイン処理1ではその処理時間20msにサブルーチンの処理時間(200μsが10回)とシリアル送信完了割り込み処理(5μsが10回)で合計22.05msの処理時間となります。この間にタイマ割り込みは22回発生しますので、その処理時間である1.1ms処理が長くなります。この1.1msの間にもさらにもう1回のタイマ割り込みが発生しますから合計では23.2msかかることになります。処理要求確認のタイマ割り込みからは24.5msで完了することになります。もし、この期間にもシリアル受信割り込みが発生していたとすると、最大で47回のシリアル受信割り込みが発生することになり、その処理時間は0.47msで、それでも次のタイマ割り込みまでには完了できることになります。
(3)メイン処理2の実行
メイン処理2ではその処理時間30msにサブルーチンの処理時間(300μsが8回)で32.4msの処理時間となります。この間にタイマ割り込みが32回発生しますが、それにより実行時間が1.6ms長くなるので、さらに2回のタイマ割り込みが発生し、全体では34.1msで処理が完了となります。これは、処理要求確認のタイマ割り込みからは35.4msで完了することになります。もし、この期間にもシリアル受信割り込みが発生していたとすると、最大で69回のシリアル受信割り込みが発生することになり、その処理時間は0.69msとなります。0.6ms以上シリアル受信処理でかかると、次のタイマ割り込みも発生するので、最悪では36.14msとなります。
以上をまとめると、3つの場合について以下の実行時間となります。
(1)処理要求待ちは1msごとに150〜160μs
(2)メイン処理1の実行は24.5〜24.97ms
(3)メイン処理2の実行は35.4〜36.14ms
ここまででは、各処理における実行時間の見積もりです。以上では個々の処理部の処理時間が与えられているものとして、計算しましたが、実際に命令の実行時間から処理時間を求めるのは困難です。そのため、デバッグを進める中で、イン・サーキット・エミュレータの時間計測機能を用いて処理時間を求めることになります。この場合に注意する必要があるのは、「測定できるのはある特定のパターンで動作している状態での処理時間」ということです。それが、どのような動作であり、同期/非同期で発生してくる割り込みがどのように影響しているかを確認しておく必要もあります。その上で、必要と思われる変動要素を加味した処理時間を求めてください。
これは、ウォッチドッグ・タイマの検討に必要な情報の一部ですが、どちらかと言うと処理性能の評価です。場合によっては、システムの要求仕様として、メイン処理1は20〜30msで完了し、メイン処理2は25〜50msで処理完了するといった条件が最初に与えられる場合もあります。しかしながら、このときの値は殆どの場合でかなりの幅をもちますし、場合によっては最大値しか示されない場合もあり、ウォッチドッグ・タイマの検討ではあまり使えない可能性があります。
また、ウォッチドッグ・タイマの動作の基準クロックにはばらつきが存在します。そのばらつき以上の精度で処理時間を求めても、通常はあまり意味はありません。せいぜい10%程度の精度で求めれば十分です(この例のように比較的単純な場合はいいのですが、複雑な処理では厳密に求めるのは大変です)。処理時間の精度が要求されるのはウォッチドッグ・タイマのウィンドウ機能を用いるときです。もっとも厳しい条件の場合には、約8%しかクリアできる期間がありませんので、4%以下の誤差で処理時間を求める必要があります。
[動作パターンと検出条件]
実際の検討を進めるには、メイン処理1,2に対する要求がどのような頻度やタイミングで発生するかを明確にする必要があります。その上で、どのような条件で検出を行うかを決めます。
例えば、以下のような要求条件で検討してみます。
(例1)
- 100msに1回メイン処理2が起動される。
- 1時間に1回メイン処理1が200msごとに20回要求される。
(メイン処理1実行はメイン処理2より優先)
この場合にはどのような状態であれば正常と考えるかを規定する必要があります。ここでは以下の3種類の基準で考えます。
(1)メイン処理2やメイン処理1を実行すれば正常と判断
(2)メイン処理2やメイン処理1を定められた時間以内で実行すれば正常と判断
(3)メイン処理2やメイン処理1を定められた時間範囲で実行すれば正常と判断
(1)の場合にはメイン処理2やメイン処理1だけでウォッチドッグ・タイマをクリアすればいいことになります。処理のループとしては最低が100msですから、ウォッチドッグ・タイマのオーバフローまでの時間をこれ以上に設定して、メイン処理1とメイン処理2でウォッチドッグ・タイマをクリアすればよいことになります。78K0/Kx2ではこの条件を満たすオーバフロー時間は2
15/fRL(最短で124.12ms)、2
16/fRL(最短で248.24ms)、2
17/fRL(最短で489.48ms)となります。さらに、(2)の条件を加味すると、2
15/fRL(最短で124.12ms)を選択することになります。これを選択した場合、メイン処理1とメイン処理2が競合して、メイン処理2の実行が遅らされた場合には、メイン処理2だけでクリアしていると、ここの間隔はメイン処理1の分だけ伸びてしまい、124.5ms以上になり、オーバフローが発生するので、メイン処理1でのクリアも必要になることがわかります。
次に、(3)の例として、ウォッチドッグ・タイマのウィンドウ機能を使う場合について考えてみます。メイン処理1及びメイン処理2の最後でクリアするものとした場合の最短のクリアタイミングは下図の例1のようになります。ウォッチドッグ・タイマのクロックが遅いほうにずれた場合、オーバフロー時間は151.7msとなり、最もウィンドウを開いた場合でもオーバフロー時間の25%の期間(約38ms)はウィンドウが閉じています。下図の例1では最短では34.5ms間隔となるので、このままではウィンドウが閉じているときにクリアをかけることになります。そこで、メイン処理1でのクリアタイミングを処理の頭に変更すると、最短の間隔でも59msとなるので、クリアタイミングはすべてウィンドウが開いている期間におさまります。
(例2)
上記の例1ではメイン処理1が200msごとに起動することにしてありましたが、これを100msごとに変更した場合にはどうなるでしょうか。今度はメイン処理2でのクリアからメイン処理1でのクリアまでの時間が厳しくなり、下の例3のように約38.9msとなります。
この場合には最悪でもウィンドウに納まるので、このままのタイミングでもいいのですが、マージンを大きくしたい場合にはメイン処理1の頭から10ms程度のタイミングでクリアしてください。このように、ウィンドウ機能を用いる場合には条件のちょっとした変更により影響を受けるので、注意が必要です。
ここで重要な点は
- オーバフロー時間を計算する場合には、カウントクロックの最大周波数で計算する。
- ウィンドウ期間を見積もるときにはカウントクロックの最小周波数を使う。
です。ウォッチドッグ・タイマのカウントクロックは規格上-10%〜+10%の範囲でばらつきます。検討を簡単にするためにカウントクロックとして最大周波数だけを用いて見積もる場合には、ウィンドウが閉じている期間は1.22倍して見積もる必要があります。つまり、
- 25%閉じる(75%開く)設定では約30%閉じていて、残り70%開いている
- 50%閉じる設定では約61%閉じていて、残り39%開いている
- 75%閉じる設定では約92%閉じていて、残り8%開いている
が確実にウィンドウが開いている期間となります。その上で、処理時間も最悪の組み合わせで考えてください。
[高度な検出条件設定]
(例3)
これまでは単純にウォッチドッグ・タイマをクリアするタイミングだけで検討してきました。上記の例では、メイン処理1が全く実行されなくてもウォッチドッグ・タイマでは検出できません(1時間に数回しか実行されない処理のことを考慮してウォッチドッグ・タイマ処理を設計するかどうか自体が問題ですが)。そこで、プログラムの処理の状況に応じたフラグを準備しておき、そのフラグを利用してメイン処理1の実行を監視することにします。具体的にはまずは次のフラグを準備します。
メイン処理1間隔フラグはメイン処理1を実行してからの時間を100ms単位でカウントします。メイン処理1はこのカウンタをクリアし、メイン処理2でカウント処理を行います。メイン処理2ではこのカウンタをチェックして1時間分のカウント以上であればウォッチドッグ・タイマをクリアしないようにします(実際には、1時間/100ms=36000カウントからメイン処理1の実行回数×繰り返しの間隔を引いた値となります。上記の例1のように200msごとでは20×2、例2のように100msごとでは20を36000から引きます)。これにより、1時間以上メイン処理1が実行されなかったことを検出できます。(タイミング例は示しませんが、上記のタイミング例2やタイミング例3と同じです。)
また、メイン処理1は処理の最後で必ずウォッチドッグ・タイマをクリアするようにし、メイン処理2ではこのフラグが0のときもウォッチドッグ・タイマをクリアしないようにしておくことが考えられます。この場合のクリアのタイミング例を下図に示します。このときのクリアの最大間隔は111.64ms、最小間隔は88.36msとなり、オーバフロー時間を2
15/fRL(最短で124.12ms)と設定した場合にはウィンドウの開いている期間を50%(この場合に確実にウィンドウが開いているのは約80ms以降となります)に狭めても問題がなくなります。
(ただし、メイン処理1の直後にメイン処理2を実行したかの確認は行えません。)
さらに、ウォッチドッグ・タイマのクリアを処理の頭で行うようにすれば、処理時間のばらつきの影響はさらに小さくできるので、ウィンドウの開いている期間を25%にすることも可能です(この場合も、メイン処理1の直後にメイン処理2を実行したかの確認は行えません)。どちらのチェックを優先するかにより処理方法を決めてください。
ただし、これだけでは、1時間にメイン処理1を20回実行したかを確認するには不十分です。
そこで、メイン処理1実行フラグを追加することを考えます。
メイン処理1はこのフラグをカウントアップします。メイン処理2ではメイン処理1間隔フラグの値をカウントアップして2または3(メイン処理1の間隔による)になったときにこのフラグを確認して、0または20(メイン処理1の連続した実行回数)以外の場合にはウォッチドッグ・タイマをクリアしないようにします。これでメイン処理1の実行回数も確認することはできます。
このように、ウォッチドッグ・タイマをクリアする際の条件を追加することで、より細かなチェックを行うことができるようにはなります。しかし、あまり複雑にすると本来実行すべき処理の制限が厳しくなる、処理が複雑になることで間違いが入り込む等、別のところで問題が発生する可能性があります。
(2005/11)