SSブログ
English Version

レトロマイコンZ80ボードの構想(その10)CP/M80 BIOS検討2 [Z80]

 ebayで注文していたブレッドボード用接続ケーブルが届いたので実験を再開しました。
 届いたケーブルはメッチャ安いのですが、ブレッドボードに差し込むピンにボンドが付いた状態だったので接触不良を防ぐために1本ずつピンセットで挟んでボンドを取り除きながらの接続作業でした^^;;
 自分で接続ケーブルを作るよりは全然楽なのですがさすがに安いだけあって品質が・・・

 最初にやりたかった実験は NMI や RESET 以外で HALT 状態を抜ける実験です。

 HALT状態では内部でNOPを実行しているということがマニュアルに書いてあったので、アドレスはインクリメントせずにHALTをNOPに置き換えてフェッチを繰り返しているものと想像していました。
 であればバスをPIC制御にし、HALTコードをNOPに変更後、バスを開放すれば、Z80は何事もなかったようにHALT状態を抜けるのではないかと考えたわけです。

 実験のソースとロジアナ波形は以下のとおりです。
 Z80の動作としては0000hのアドレスのHALTコード(76H)でHALT状態になった後は0001h番地のNOPコード(00h)をフェッチしています。

 従ってNOP書換えによるHALT脱出はできないという結論になりました。^^;

 ロジアナ波形でresetがhighになった後RD/がlowの部分で命令コードをフェッチしています。
 RD/の最初のlowでは(AD1,AD0)=(0,0)でアドレス0000hのコード(76h)をフェッチしています。(なので(D1,D0)=(1,0))
 その後HALT状態(HALT/がlowに遷移)し、(ad1,ad0)=(0,1)なので0001hのメモリのコード(00h:NOP)をフェッチする動作が繰り返されます。

 マーカーはRD/がアクティブになってからメモリからデータが出てくるまでの時間を示していて62.5nsでした。(この時ロジアナのサンプリング周波数は32MHzなので解像度は30ns程度です)
 使用しているメモリはHM628128D(DIPタイプ、128KBytes)でアクセスタイムは70nsなのでアクセスタイムにはあまり余裕はありませんが問題なく動作しているようです。
 Z80はPIC側から供給している16MHzで動作しています。(Z80は20MHz対応のチップを使用)

 NOP書換えではHALTから抜けれないことが判ったのでBIOSではNMIかRESETを使用することになりそうですが、PIC側で使用するI/O数を節約するために RESET方式にしようかと考えています(NMI方式にした場合でもRESETはPICから制御したいからねぇ)

 また、BUSREQ/はマシンサイクルの最後でチェックされ(Z80のマニュアルより:BUSREQ is always recognized at the end of the current machine cycle.)NMIよりも優先されるのでBUSACK/のチェックは省略可能と考えています。(SDカードの装着信号?を入力しておかないと起動後に抜き差しできなくなるのでI/O節約検討中なのですw)

HALT実験ソース(picle言語)
1:# HALT test by skyriver 2018/02/27 2: 3:use LibCpm; 4: 5:proc main() { 6: init(); 7: initPmp(); 8: 9: PmpOn(); 10: 11: PmpSetAdr( 0 ); 12: MemWr( $76 ); # HALT 13: MemWr( $00 ); # NOP 14: 15: PmpOff(); 16: 17: LATC[0] = $0008; # reset on 18: BusRelease(); 19: LATC[0] = $0009; # reset off 20:}


HALTコード実行時のZ80の挙動



 お遊びでZ80の全メモリをNOP(00h)に書き換えるプログラムを動かしてみました。
 このコードなら今でもそらで機械語を言えます ^^

 ロジアナ波形を見ると左側1/3くらいからデータバスがlowに貼り付き、WR/はhighに貼り付きます。
 Z80は全メモリNOPコードの中、アドレス(PC)を進めるのみの動作になります。
 昔のマイコンはメモリ空間上にVRAMがあったのでVRAM上での命令実行時に画面にノイズが載ってZ80の走行状態を目視できたんだよねぇw

全メモリクリアソース(picle言語)
:l 1:# all memory clear with Z80 by skyriver 2018/02/28 2: 3:use LibCpm; 4: 5:proc main() { 6: init(); 7: initPmp(); 8: 9: PmpOn(); 10: PmpSetAdr( 0 ); 11: MemWr( $21 ); # LD HL,0001h 12: MemWr( $01 ); 13: MemWr( $00 ); 14: MemWr( $36 ); # LD (HL),0e9h 15: MemWr( $e9 ); 16: MemWr( $2b ); # DEC HL 17: MemWr( $f9 ); # LD SP,HL 18: MemWr( $36 ); # LD (HL),0e5h 19: MemWr( $e5 ); 20: MemWr( $e9 ); # JP (HL) 21: 22: PmpOff(); 23: LATC[0] = $0008; # reset on 24: BusRelease(); 25: LATC[0] = $0009; # reset off 26: Timer_ = 50; 27: while ( Timer_ ); 28: dump( 0 ); 29:} :run 0000 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0020 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0030 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 :

★2018/02/28 変更 メモリクリア部を1byte短縮w


全メモリクリアで永遠にNOPを実行し続ける


[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(4) 
共通テーマ:趣味・カルチャー