SSブログ
English Version

Z80GALの構想(その7)hexローダーでのCP/M-80ブート [Z80]

 前々回の記事でタイマ割込みによるシリアル通信を実装し、前回の記事でSDカードのアクセスに必要なSPIインターフェースを実装したので今回はいよいよCP/M-80の移植です。

 いままで検討してきたZ80GAL基板は想定通り、Z80:Z84C0020PEG(40PIN)、RAM:UM61512-15(32PIN)、EEPROM:W24C512-45Z(28PIN)、GAL:GAL22V10D(24PIN)、クロック&タイマ:PIC12F683(8PIN)の5チップ構成で仕上がりそうです。

 CP/M-80の起動画面が下図です。
 hexローダーでCP/M本体とBIOSをロード後、BIOSの先頭(boot)を実行することでCP/Mが起動しています。(^^)/

Z80GALでのCP/M-80起動画面


 久々にHI-TECH Cでコンパイルした際の画面です。「-v」オプションで詳細表示指定しています。

HI-TECH Cでのコンパイル


 しかし、今回のCP/Mの移植はいつもより、少し手間取りました・・ ^^;
 他の人の参考になるかもしれないので発生した主要な問題を二つ書いておきます。

  1. M80/L80で作成したCOMファイルの問題
     アセンブラ/リンカはMACRO-80(M80/L80)を使っていて、DOS窓でCPMエミュレータで動かしています。生成したcomファイルは開始アドレスを指定してhexファイルに変換後、モニタでZ80GAL内のメモリにダウンロードしています。
     開始アドレスを指定できるHEXファイル変換ツールが見当たらなかったので簡易的なツールを自作しました(「Z80GALの構想(その4)簡易モニタの製作」の記事の末尾に追記して公開しました)

     今回は割込み処理、SPIインターフェース及びSDカード初期化等もあるので64KBのCP/MではBIOS領域が足りず、CP/Mを62KBサイズにしているのでBIOSは0F200Hから始まります。
     COMファイルを生成するために先頭で「ORG 0100H」で宣言後、.phaseステートメントを使って実アドレスを指定しているのですが、.dephaseして、再度.phaseした際に生成されるcomファイルが16バイト欠落する問題が発生しました。

     アドレス再指定部分のソースは下記のとおりです。

      0020               RBUFSZ	EQU	32
      FFE0               RBUFMSK	EQU	NOT (RBUFSZ - 1)
    
      F6C0               RBufAd	EQU	($ + RBUFSZ -1) AND RBUFMSK
                         	.DEPHASE
                         	.PHASE	RBuFAd
    
      F6C0               RBuf:	DS	RBUFSZ
    
                         ;	;Drive	 A    B    C    D  ..     K L
      F6E0               drvtbl: dtbl	<dpha,dphb,dphc,dphd,dphe,,,,,,,>
      F6E0  F74B   +     	 dw	dpha
      F6E2  F75B   +     	 dw	dphb
     

     下図が生成されたcomファイルをバイナリエディタで確認した結果です。
     comファイル内コードの開始アドレスは0F200Hなので「drvtbl」が04E0H(=0F6E0H-0F200H)に配置されるはずなのに下図のように04D0Hに配置されてしまっています。orz

    04C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    04D0 4B F7 5B F7 6B F7 7B F7 8B F7 00 00 00 00 00 00
    04E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
     

     この問題は下記のようにして回避できました(その他の変更箇所もあるので上記のものとアドレスは異なっています)。

      0020               RBUFSZ	EQU	32
      FFE0               RBUFMSK	EQU	NOT (RBUFSZ - 1)
    
      F6E0               RBufAd	EQU	($ + RBUFSZ - 1) AND RBUFMSK
                         ;	.DEPHASE
                         ;	.PHASE	RBuFAd
    
      F6D2               DS	RBufAd - $
    
      F6E0               RBuf:	DS	RBUFSZ
     

     今回のディバッグスタイルはブレークなどは使わず、机上ディバッグがメインなのでこの手の問題が発生すると手こずります^^;


  2. CP/M-80の割込み用スタックの制限
     Z80GAL用のBIOSを書き上げてCP/Mを起動するとdirコマンド終了後にwboot内のシステムを読込み処理が走った後ディレクトリセクタの読込みが走る(固まる場合もある)現象が発生しました。
     他の動作は問題無いように見え、"dir"だけがおかしな状態です。BIOSのソースをいくら確認してもおかしな箇所は見当たらないので、コンソール入出力を初期に作った割込みを使わないものに変えてみたところ"dir"が正常に動作しました。

     割込み処理によるスタックの問題と思いdirコマンド実施時に実行されるであろうBIOS内の「READ」や「CONOUT」等の処理を確認し、「READ」処理内のPUSH BC,DE,HLを削除しても状況は変わりませんでした(CONOUTではPUSHは1つだけ)
     タイマ割込み処理ではPUSHは2個(AFとHL)だけでしたが少し遅くなりますがHLをメモリ変数に退避したところ、問題が解消しました。

     CCP内でのdirコマンド処理からのBIOSコール時ではなく、dirコマンド処理内自体でスタックが溢れていたようです。

     ネット情報をざっと調べましたが、CP/M-80実装時における割込み処理のスタック数についての情報は見当たりませんでした(どこかにあるのかも)。
     割込み処理内では"PUSH AF"以外はレジスタをメモリ上の変数に保存するか、スタックを切りなおしてPUSH/POPした方がいいようです

    ★追記 2020/11/15 {
     "dir *.z"等のようにどのファイルにもヒットしないワイルドカードでのdirコマンドで固まる現象が発生しました。
     割込み処理内で引き継いだスタックへの"PUSH"を無くし、スタックを切り直してから"PUSH"することで問題が解消しました。

     上の記載では割込み処理内で1段だけはスタックを使用しても問題ないようなことを書きましたが割込み処理内ではスタックを切りなおしてPUSH/POPした方がいいようです("CALL"でスタックを使用する場合も同様)
    }

     因みにCCPがコマンド内容を処理する際のスタック領域は下記のように8段しか確保されていないようです。

     E386 CD66E0    GETBACK CALL  RESETDR ;reset previous drive.
     E389 CD5EDE    GETBACK1:CALL CONVFST ;convert first name in (FCB).
     E38C 3ACEE3            LDA   FCB+1   ;if this was just a drive change request,
     E38F D620              SUI   ' '     ;make sure it was valid.
     E391 21F0E3            LXI   H,CHGDRV
     E394 B6                ORA   M
     E395 C209DE            JNZ   SYNERR
     E398 C382DF            JMP   CMMND1  ;ok, return to command level.
                    ;
                    ;   ccp stack area.
                    ;
     E39B 0000000000        DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
     E3AB =         CCPSTACK:EQU  $       ;end of ccp stack area.
     



 以上が、Z80GALへCP/M-80を移植した際に発生した問題の簡単なメモになります。
 今回のソフトによるSPIインターフェスでのSDカードのアクセスはできるだけ高速化したつもりですが、Pic24CPMと比較して体感上はSDアクセスが倍以上遅く感じます(^Cでのシステム+ディレクトリ読込みで2秒程度時間が掛かる)。

 Pic24CPMでは例えばSDリード時はPICでアクセスしたデータをZ80に引き渡し、更にDMA領域に転送していたので(Z80GALでは直にDMA領域への読込み)もう少し速くなると期待していたのですが・・

 CP/Mのメモリサイズも62KBになったのでBlocking/Deblocking処理を追加してSDアクセスを高速化したいと思います。

 因みにタイマ割込み処理は34.7us間隔で割込み処理時間は約7us程度(シリアル通信状態にも依存)なので

   20MHz x (35 - 7) / 35) = 16MHz

のクロック相当の処理速度です。Pic24CPMのクロックが丁度16MHzなのでASCIIART.BASを並べて実行してみたところ、見た目上はまったく同じ速度でした。



[TOP] [ 前へ ] 連載記事 [ 次へ ]
nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー