標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第466回]
●NMI(その2)
Z80のNMI(Non Maskable Interrupt)については[第437回]で説明をいたしました。
説明をすることはしたのですけれど、引用したZilog社のZ80CPU User Manualの説明文がなんともいいかげんな説明文で、肝心のところがいまひとつはっきりしませんでした。
ということで、[第437回]はあいまいな説明のままで終わってしまいました。
その時点では、その次の回に引き続きNMIについて、もう少しはっきりした説明を書くつもりでおりました。
ところがZ80版TK80ボードの試作基板が出来てきてしまったものですから、そのままその説明に入ってしまって、NMIの続きなどもうどこかに行ってしまいました。
そういうことだったのですけれど、まあしかし、INTと違って普通の用途ではNMIなどを使うことは余り無いとも思われますし、事実私自身も何かにNMIを利用したという記憶はありません。
もともとNMIなどというものは8080にはありませんでしたし、当然のことながらTK80のモニタプログラムには関係がありません。
NMIのエントリアドレスといいますか、スタートアドレスは0066番地に固定されていますから、Z80を使ってTK80互換ボードを作ることを考えると、そのアドレスはTK80モニタプログラムが書かれているアドレスですから、もしもNMIの機能を利用しようとすれば、TK80モニタプログラムの、その部分を書き換えなくてはなりません。
それまでしてNMIを使う必要は無いと思いますから、そうするといまさらNMIなど持ち出さなくてもよいではないか、ということになるかもしれません。
しかし、Z80版TK80ボードの試作基板の説明に移ってしまったものですから、完全に宙に浮いてしまったのですけれど、実は、次の回あたりで説明をするつもりで、NMIについてロジアナを使って動作を確認した資料なども準備していたのです。
せっかくそこまでしても、またいつものことで、そのままにしておいたらどうせすっかり忘れてしまいます。
ですので、これもこの機会にここでまとめておきたいと思います。
[第437回]のUser ManualのNMIの説明でははっきりしないところがありますけれど、NMIも普通のINTも、割込みの動作そのものは基本的には同じです。
割込み信号は、実行中の命令の最後のクロックのときにCPUに認識され、Z80CPU User Manualの説明によると、その次にデータバスに読み込まれた命令は無視されて、そのときのPC(プログラムカウンタ)の値が外部スタックに保存されたあと、0066番地の命令が実行される、ということのようです。
●NMIテストプログラム
そのあたりの動作を、[第374回]でご紹介しましたカメレオンUSB+ロジアナで観測して確認してみることにしました。
割込みプログラムの開始アドレスは0066番地ですから、プログラムはROMに書くしか仕方がありません。
今回はTK80モニタプログラムは無視です。
ROMの先頭アドレス0000番地から簡単なテストプログラムを書きました。
2010/2/20 9:40 NMITEST.TXT END=006C ;;; Z80 NMI TEST 10.2.20 ; ORG $0000 0000 3100E0 LXI SP,$E000 0003 3E90 MVI A,90;82C55 A=IN,B,C=OUT 0005 D383 OUT 83 0007 3EFF MVI A,FF 0009 D382 OUT 82 000B DB80 LOOP1:IN 80 000D FEFF CPI FF 000F CA0B00 JZ LOOP1 0012 3E00 LOOP2:MVI A,00 0014 D382 OUT 82 0016 3EFF MVI A,FF 0018 D382 OUT 82 001A C31200 JMP LOOP2 ; ORG $0066 0066 D381 OUT 81 0068 3EFF MVI A,FF 006A D382 OUT 82 006C C9 RET ;END LOOP1 =000B LOOP2 =0012
むむむ。
NMIはZ80の機能ですから、Z80ニーモニックで書くところなのですが、どういうわけか、8080ニーモニックで書いてしまいました。
プログラムだけを見ても、これのどこが割込みのテストプログラムじゃ、という感じになりますが、もちろんシカケがあります。
LOOP2のところで82C55のCポート(I/Oアドレス82)に00とFFを交互に出力しています。
実は、そのCポートのビット0(PC0)の出力をZ80のNMI入力に接続してあるのです。
ですから0014番地のOUT命令が実行された直後にNMI割込みが発生するはずです。
それをロジアナで観測しよう、ということなのです。
なお、その上のLOOP1は、リセットまたはPOWER ONによっていきなりLOOP2にエントリさせると、起動時の不安定な状態のときにCPUから出力される信号によってロジアナのトリガが働いてしまうのを防止するためのものです。
82C55のAポート(I/Oアドレス80)のビットのどれかをGNDに落とすことで、LOOP2のプログラムが実行され、そこではじめてNMI割込みが発生する、という仕掛けです。
●ロジアナでの観測結果
ロジアナで観測した結果です。
今回のテストプログラムは短いプログラムで実行範囲が限られていますから、アドレスバスの上位8ビット(A8〜A15)はロジアナには入力しませんでした。
PROBE07のラインにデータバス(D0〜D7)の値を書き加えてあります。
またPROBE12のラインにアドレスバスの下位8ビット(A0〜A7)の値を書き加えてあります。
PROBE08がNMI入力です。
24μsのところでD3 82(OUT 82)が実行されて、アドレスバスが82、データバスが00になっています。
WR信号(このときは実はIOWR)の立ち上がりで82C55のCポートから00が出力され、その結果NMIがLになっています。
NMI入力はその次の3E FF(MVI A,FF)の実行の終わりに受付けられます。
データバスには、その次の命令コードのD3がメモリから読み出されていますが、その命令コードは無視されて、その次のタイミングで、このときのアドレス、つまりPC(プログラムカウンタ)の値(0018)が、スタックに退避されています。
そのあとアドレスバスが66になっていて、ここで0066番地の割込みプログラムが実行されたことがわかります。
割込みプログラムはアドレス006CのC9(RET)で処理を終わり、もとのプログラムに戻ります。
スタックに保存されていたアドレス0018がPC(プログラムカウンタ)に戻され、そしてあらためて、さきほど無視された、0018のD3 82(OUT 82)が実行されています。
2010.3.31upload
前へ
次へ
ホームページトップへ戻る