標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第238回]

●あれ?ブートプログラムが違ってる?

前回([第237回])、ブートプログラムのアドレスを変更しましたよ。というお話をいたしました。
毎度のことなのですけれど、一晩寝て朝になってからあらためて読みなおすと、おかしなことに気がついてしまうのですねぇ。
ほんとに困ったものです。

前回は、アドレス変更前のブートプログラムのリスト(メモリアドレス0000が開始アドレスになっています)と、開始アドレスを1000に変更したリストを両方お見せしています。
で。
開始アドレス(ORGの部分)と受信したデータ(プログラム)を格納するアドレスをプログラムで指定している、最初のLXI Hの部分をちょいちょいと直しました。
と書いたのですけれど、両方のリストを見比べてみましたら、
あれま、プログラムサイズが違ってるじゃないの?これって、どういうこと?

もとのプログラムのエンドアドレスは、001Bです。
それに対して変更後のプログラムのエンドアドレスは1021になっています。
開始アドレスを1000にしただけですから、エンドアドレスは101Bのはず。

よくよく見てみると、もとのリストは、作成日付が、09/03/10と09/03/11になっています。
ところが、変更後のリストを見ると、09/03/11がありません…。
どうやら、ソースを間違えてしまいました、ようです。
まっ。よくある話です…。

などと済ませられればよいのですけれど、こういうミスを納品でやってしまうと、大変です。
もう、すみません、すみません、すみまっせんっ。
って平謝りでプログラムの差し替えをすることになります。
もう、二度と過ちは繰り返しませんので、平にご容赦を…。
などと、不祥事の記者会見の定型文みたいなメールを送らなくてはいけません。

こういうことのないように、古いファイルは全部削除してしまうか、つねに上書き更新にすればよいのですけれど、そうすると、変更したらかえって異常な動作になってしまったので、もとに戻ってやり直したい、とか、気がついたら、最終ファイルまで削除してしまっていた、などという、それこそ取り返しのつかないことになったりする危険があります(事実、そういう悲しい体験もしっかりしてしまっています、です)。

ま。あれです。
えっ、と。プログラムを修正したり変更したりするときは、こういうみっともないことをしないように、お互い気をつけましょーね、というサンプルです。

過去にさかのぼって調べてみましたら、どうやら[第180回]でお見せしたプログラムをもとに変更作業をしてしまったようです。
この最初のブートプログラムは、その次の[第181回]の終りのところで、「最後のLOOP2は冗長なので、そこのところは削除しました」と書いています。

うーん。みごとに、ぜーんぶ、きれいさっぱりと、忘れてしまいますですねー。まあ、ほんとに、我ながらあきれてしまいます。

えー。
ことのついでに、なぜ冗長なのかを説明しておきましょう(そうでもしないと、きまりが悪くて、引っ込みがつきません)。

●説明のために、もう一度ブートプログラムのリストです



PICがUSB−RS232C変換回路を経て受信したデータをPIC内部で8ビット1バイトのデータにして、それをCPUにパラレルで渡します。そのデータ伝送は複数の制御線を使ってハンドシェイクで行われます。
ハンドシェイクというのは、送信側と受信側が互いに相手の動作を確認しながらデータの受け渡しをする方法で、手間がかかりますがデータを落としてしまう心配がありません。
これに対して、タレ流し式といっている方法は、受信側の状態を確認することなく、送信側が適当な遅延を入れて一方的に送ってしまう方法です。受信側が十分速くないと、データを落としてしまいます。

PICからのデータは8ビットパラレルで送られます。
CPU側はそのデータをI/Oアドレス94から読み込みます。
PICはデータをセットしたことをCPUに知らせるために、I/Oアドレス98のbit0のラインをLにします。
CPUはアドレス98のbit0を見ていて、それがL(=0)になったら、これからデータの読み込み処理をしますよ、ということをPICに伝えるために、アドレス98のbit0をL(=0)にしてから、アドレス94からデータを読み込み、HLレジスタで示すメモリアドレスに書き込みます。
ここまでが、1007〜1014までの部分です。
ここにはPICの側の動作は出てきませんが、PICはアドレス98のbit0出力を監視していて、それがLになったら、データセット信号(アドレス98のbit0入力)をHに戻します。

なお、同じ98のbit0を入力と出力の両方で使っていますが、「つくるCPU」のI/O回路は、互いに独立している入力と出力回路に、同じアドレス98を割り当てていますから、I/Oの外側は全く別の配線になっていて、それぞれPICの別の端子に接続されています。

そして最後に、1バイトのデータのメモリ書き込み作業が完了したことをPICに知らせるために、アドレス98のbit0出力をH(=1)にします。
PICは、そのCPUからの信号を見ていて、アドレス98のbit0出力がHになったのを確認したら、次のシリアルデータ受信〜CPUへのパラレル出力動作に入ります。
[注記]ここのところの説明に不正確なところがありました。次回([第239回])で訂正していますので、そちらもお読みください。

CPUは、LOOP2のところで、PICからのデータセット信号、アドレス98のbit0入力がHになるのを待ってから、次のデータ読み込みのためにLOOPに戻ります。
このようにしないと、前のデータセット信号のままなのに次のデータセット信号だと間違えて2度読みをしてしまう可能性があるからです(ここのところがウソです)。

完全なハンドシェイクです。冗長なところはないように思えます。
が、よーく、文章を読んでみると、あれえ、なんだかおかしくね?というところに気がつきます(ませんか?)。
タイミングチャートで説明しましょう。

上側の図が、LOOP2の部分の根拠になったタイミングチャートです。
でも、実はそうではなくて、PICからの出力、98(in)bit0は、下側の図のタイミングで変化するのです(そうそう、読みなおしてみましたら、[第181回]の説明で、ちゃんと「下側の図」をお見せしていました)。

PICは98(in)bit0をLにしたあと、98(out)bit0を監視していて、それがLになったらすぐに自分の出力、98(in)bit0もHにしてしまいます。PICのクロックは4MHzとわりとゆっくりしたクロックにしてありますが、それでもこの応答は速く行われ、5μs程度でHになります。
CPUの側は、IN 94、MOV M,A、INX H、MVI A,FF、OUT 98、と、これだけの命令を実行してから98(in)bit0を見に行くのですから、そのときには、もうPICからの出力は確実にHになってしまっています。
ですから、ここのLOOP2の部分は冗長なのです。

いや、実は、冗長どころか、PICの側の次のデータの出力処理がもしすばやく行われたならば、かえってハングアップの危険さえ出てきます。
今回のプログラムは幸いRS232Cの受信データがもとになっていますから、PICからのデータ出力も、RS232Cの受信に同期して行われます。
もともとシリアル受信はCPUのデータ処理速度に比べるときわめて低速ですから、今回の場合には、冗長ではあっても、特にハングアップの危険があるわけではありません。
でも、まあ、ムダなものをそのままにしておく必要はありませんから、ここはもう一度削除することにいたします。
2009.6.2upload

前へ
次へ
ホームページトップへ戻る