【17】リセットの使い方
今回は「リセットの使い方」というタイトルをつけましたが、リセットというものを暴走や緊急時の再起動のきっかけにするだけでしたら、 "使う" という言葉は適切ではないように感じます。
PICのようにひとつの独立した部品として扱われるコンピュータシステムが、予期しない動きに陥ったときに元に戻すためにリセットというものがある、と前回説明させていただきました。どの教科書にもだいたい同じようなことがかかれてます。ところがリセットが掛かって再起動が始まったときどうするか、というところまでは解説したモノがあまりないような気がします。
今回はかなり私的な使い方を書かせていただきました。たしかに昔のゲーム機ではこのような使い方をしていましたが、動作を完全に保障するものではありませんので、そんな方法もあるのか、という参考程度にしていただければと思っています。
前回も書きましたが、大まかなリセットの種類を以下にあげます。
① 電源が入ったとき(パワーオン)リセット
② 電源が切れたとき(ブラウンアウト)リセット
③ マニュアルリセット。手動で MCLR端子を L にしてから H にする。
④ 異常時に(ウォッチドッグタイムアウト)リセット
上記のリセットを起動というカタチから見ますと以下のようになります。
■ 電源が入った最初のリセット・・・①(初期起動)
■ 動作中に起きたリセット・・・③④(再起動)
■ 瞬断・・・②(瞬間停止)
電源が入ったときのリセットは再起動ではなく、初期起動ということになりますので、まず入出力ポートの初期化、使用するタイマーやレジスタの初期化、RAMの初期化、割り込みの設定 ……、などを通っていちばん最初の状態、例えば操作する人の作業待ちなどになります。
動作中に起きたりセットも初期起動と同じ動きをさせても、すべてが初めに戻りますので問題は有りません。しかしもう少し賢いシステムにしたい場合、せめて前回どこの処理をしているときにリセットが掛かって再起動したのか判断できれば、中断していた処理へ戻すことができると思いませんか。
そのために、PICにはリセットを判別するフラグが準備されています。
特殊機能レジスタと呼ばれるたくさんの一時記憶用のエリアがあり、その中のSTATUS(ステータス)レジスタのTO(タイムアウト)ビットと、PCON(パワーコントロール)レジスタの中のBOR(ブラウンアウトリセットステータス)ビット、POR(パワーオンリセットステータス)ビットと呼ばれるフラグがセット、クリアされます。
どのリセットが掛かってもプログラムは0番地へ飛び、ポートはすべてアナログ入力ポートにセットされます。もたもたしていると危険な状況になるかも知れませんので、まずは早急にI/Oポートの初期化を行います。それから先ほどの、どのリセットで再起動が掛かったかを判断することになります。
ちなみにもたもたすると危険な状況というのは、たとえば自動販売機でおつりを排出中にリセットが掛かったときのように、高速に動いている何かを制御しているときは、とりあえずその状況を安全な方向に導いてから、ということです。
次に、動作中に起きたリセットの場合、本当に完全な初期化を通さなくてもいいかという問題です。完全な初期化を通せば安全に起動します。そのかわりリセットが掛かる前まで行っていた処理は中断してしまうことになります。先ほどの自動販売機を例にとると、おつりの排出が途中で止まったり、おつりは出たが商品が出ないという状態になり、これは少しまずいですね。
▽ メモリ破壊 △
安全かそうでないかは、メモリ破壊をチェックします。
この場合の「破壊」とは壊れて使えなくなるの「破壊」ではありません。メモリの内容が意図する数値ではない値に置き換わっていることを指します。これはどういうことかいうと、電源が切れると当然記憶は消えますのでメモリ破壊が起きます。それ以外にも暴走状態でCPU自身が自分のメモリを無茶苦茶に上書きしてメモリ破壊を起こすこともあります。
どのようにしてメモリ破壊かそうでないかを判断するのかというと、ユーザーメモリの適当なアドレスに連続して何かのメッセージを書き込んでおきます。例えばシステムのタイトルでもいいですし自分の名前でもいいです。それをアスキーコードに直して数値化してメモリに書き込んでおいて、リセットが掛かかるとリセット判別処理でその部分を調べて、正しいメッセージが書き込まれていたらメモリ破壊が起きていないと判断する方法です。
そしてもうひとつ、何の処理を行っている最中なのかプロセス別にコード化して、ユーザーメモリにそのコードを記憶させます。さらにそのメモリのコピーを別の離れたアドレスにも何個か作ります。
これもメッセージのときと同じように、リセット判別処理でプロセスコードを書き込んだユーザーメモリーの値がすべてのコピーとで同じかを調べて、正しければ処理を分岐させます。同じでなければメモリ破壊と判断して、完全な初期化を通してから再起動するか、「係員をお呼びください」のメッセージを出して停止するなどの処置をすることになります。
ただし単純にマスターと同じコードをコピーへ書き込むだけではまずい場合があります。暴走で同じ数値を上書きする場合や、電源ONで偶然同じ数値になることもありますので、単純な数値ではなく、アスキーコードに変換したものをコピーするとか、マスターのプロセスコードを書き込んだメモリを2倍したものをコピーに書き込み、比較するときは逆に1/2にしてもとの数値へ戻してから比較するとかの工夫が必要です。
またPICの場合はRAMエリアがバンク切り替え方式ですので、同じアドレス、たとえば0x028番地を指定する場合、バンクの切り換で、0x0A8、0x128、0x1A8の4箇所が選択される可能性があります。メモリ破壊が進むときはこのようなバンクを飛んだ同じアドレスのメモリが破壊される可能性も有りますので、コピー先を同じアドレスの別バンクに設置するというのもひとつの手です。
何重ものメモリー破壊検知を行っていますが、絶対に安全とはいい切れません。
しかしPIC内臓のリセット判別フラグとメモリ破壊検知を併せたリセット処理をうまく使うと、割り込み機能のない古いPICや、小規模PICでもMCLR端子を利用して割り込みのような使い方ができます。
MCLR端子をLにしてHに戻すとパワーオンリセットが発生します。このままフラグだけでリセットの判断をしますと、当然ですが電源が入ったと判断されて完全なメモリの初期化を選んでしまいますが、メモリ破壊検知で破壊無しと判断できれば、パワーオンリセットを利用して別の処理へ分岐させてから元の処理に戻る、という割り込みのような使い方ができるようになります。
_______________________________________________________
2011.08.28
Copyright(C) 2004. D-Space Keyoss. All rights reserved