PC-6001: December 2008アーカイブ

Z80からのI/O信号に対し、どのくらいでAVRによる割り込み反応が得られるのかを調査してみました。 回路は前回作ったものを使います。

PC-6001側からI/O命令を発行し、AVRの外部割込み入力をトリガにして反応を調べます。 まずは、主な信号線の様子。

20081214-INT0.PNG

ここで、INT0が活性化されている時間(A-B)は、630ns。

実行されているプログラムは以下のような感じです。

.org	1
	rjmp	INT_IN
INT_IN:
	sbic	PIND, 2	; 割り込み終了だったらInputへ
	rjmp	Input
	; omit...
Input:
	out	DDRC, r18
	out	PORTC, r19
	sbi	PORTB, 4
	reti

INT0は両トリガでの割り込みにしているのですが、 AVRの割り込みルーチンが反応するときには、INT0はHレベルになっているのか、常にInputルーチンへ飛びます。

上図にあるLEDという信号線は実際にはAVRのポートB4で、これがLからHになる(sbi PORTB, 4)まで2,040nsかかっています。 8MHzだと約16クロック分です。

割り込みへの反応速度を見るために、プログラムを少し変えてみました。

.org	1
	rjmp	INT_IN
INT_IN:
	sbi	PORTB, 4
	; omit...

割り込みがアクティブになってから、rjmpおよびsbiのみの実行です。 タイミングは以下のようになっています。

20081214-INT1.PNG

これで、LED(PORTB4)の変化までの反応時間は1,200nsでした。8MHzで9.6クロック分。 rjmpとsbiの実行時間4クロックを差し引くと、割り込みの反応に700ns(5.6クロック)ほどかかることになります。

ちなみに、割り込みをダウンエッジのみにして追試してみましたが、反応時間は1,160nsで、それほど大きな差はありませんでした。

これを、最初の図と照らし合わせると、INT0の活性化時間が700nsに満たないため、割り込みルーチン開始時にはどう足掻いてもI/Oには間に合わない、ということになります。

やはりどうしてもZ80とAVRの間にはラッチが必要ということになりますね。


レトロパソコンのインテリジェントな周辺機器を作るのに 大きな間違いに気づいてショックな今日この頃。 デコーダ・バッファは8255が入手困難な現在、手持ちのCPLD(Xilinx XC9536XL)があるのでそれでやってみようと思うのですが、困ったことにライタがありません。

ライタを作ろうにも、そのための部品が手持ちでは苦しいところです。 またしても鶏卵問題に陥りそうなのですが、悩んでいても埒が明かないので、とりあえずやれることからやってみることに。


まずは、テスト用に以前の回路を手直しして、以下のような簡単な回路を作ってみました。

20081213-Test.PNG

入出力に対応させてありますが、とりあえずそれは気にしないでin命令に応じてLEDを点滅させてみることにしました。

AVRのプログラムは以下のとおり。

.include	"m8def.inc"
.org	0
	rjmp	RESET
INTERRUPT:
	sbic	PORTB, 4	; 前回は点灯ならスキップ
	rjmp	LEDON
	sbi	PORTB, 4	; LEDを消灯
	reti
LEDON:
	cbi	PORTB, 4	; LEDを点灯
	reti
RESET:
	ldi	r24, low(RAMEND)
	out	SPL, r24
	ldi	r24, high(RAMEND)
	out	SPH, r24
	ldi	r24, 0x10
	out	DDRB, r24
	cbi	PORTB, 4	; 初期状態は点灯
	ldi	r24, 0x02
	out	MCUCR, r24	; 割り込みモード(INT0ダウンエッジ)
	ldi	r24, 0x40
	out	GICR, r24	; INT0割り込みイネーブル
	sei	      		; 割り込み許可
LOOP:
	rjmp	LOOP

LOOPでの無限ループ中に、割り込みがかかるとINTERRUPTルーチンが走ります(INT0のベクタアドレスに直接書いています)。 割り込み条件はINT0のダウンエッジです。

INT0は回路にあるように、IORQ | RD | A7 | A6なので、これらがすべて0のとき、すなわちBASICなどで

a=inp(0)
  

を実行すると点滅します。

ところが、不思議なことに放っておいても(BASICのテキストモードで何もしなくても)不規則に点滅します。

割り込みの条件から考えると、0x00~0x3fのI/Oリード要求により点滅するはずなのですが...。 何かおかしいんでしょうかねぇ。

以前設計した回路には、重大な盲点がありました。 2点あります。

  1. 割り込み要求線に^RD/^WRを入れておかないと、おかしなタイミングで割り込み要求がかかる
  2. Z80からのI/O要求に対する応答が間に合わない

割り込み要求線

以前の設計では、割り込み要求は次のようにしていました。

20081213-AVR1.png

IORQの確定とRD/WRの確定には時間差があるようで、どうもIORQの確定のほうが早いようです。 そのため、割り込み要求後にRD/WR線を調べないと本当にI/Oアクセスがかかっているのか分からないです。

そのため、INT線に入れる要求はRDまたはWRとORを取っておく必要があります。

20081213-AVR2.png

なお、デコードに常にA7を入れているのは、PC-6001の場合、I/Oポート0x80~はシステムによって予約されているためです。


I/O要求のタイミング

以前設計していたときは、Z80(約4MHz)のin/out命令のスピードが最低でも13クロックかかるため、8MHzのAVRなら26命令分の余裕があると思っていました。

ところが、これが大間違いだったのです。 I/Oの実際の信号が出るのは、命令読み込みではなく命令実行のタイミングのため、IORQが確定するのはかなり遅くなります。

もっとも高速なIN A, (n)やOUT (n), Aで考えても、M1ステートで命令を読み込み、M2ステートでI/Oアドレスを読み込むので、実際のI/O処理が行われるのはM3ステートのみです。

データシートを元に考えると、おおよそ以下の図のようになります。

IN A, (n)のM3ステート時の動作

20081213-Z80_RD.png

OUT (n), AのM3ステート時の動作

20081213-Z80_WR.png

すると、I/Oリクエストによる割り込みからデータ入出力まではZ80クロック基準で2.5クロック分くらいしか余裕がないのです。

これに対処するには、8MHzのAVRの割り込み処理ではとても追いつきません。 専用のデコーダと入出力用のデータバッファが必要になります。

ていうか、一般的にはこれは常識っぽいですよね。 8255がある理由がそうですから。 なんと間抜けなことをしたことか...。