SSブログ
English Version

レトロマイコンZ80ボードの構想(その13)CP/M80 boot成功 [Z80]

 前回の記事でRESETでのHALT抜け方式でBIOS内コンソール関連の機能確認が出来たのでREAD/WRITEを追加しBIOSを仕上げました。

 また、「レトロマイコンZ80ボードの構想(その9)CP/M80 BIOS」の記事の最後の方でbootはPIC内のフラッシュメモリから展開するようなことを書きましたが、PIC側のI/O不足対策により、PIC側からアクセスできる外部メモリの範囲は 0x0000 - 0x07ff, 0xf800 - 0xffff になったのでPIC内フラッシュからの展開はやめて先頭セクタにIPLを入れたCP/M本来の形式にしました。

 IPLはこんな感じです。

PicCPM用のIPL(Z80アセンブラ)
; CP/M IPL for PicCPM(PIC24FJ64GA004) ; Ver 0.01 2018/03/14 by skyriver 0040 MaxSec EQU 64 ;sectors pre track 0037 SysSec EQU 55 ;number of system sectors 0040 MSIZE EQU 64 B000 BIAS EQU (MSIZE-20) * 1024 E400 CCP EQU 3400H+BIAS ;base of cpm ccp FA00 BIOS EQU CCP+1600H ;base of bios 000D CR EQU 13 000A LF EQU 10 FF70 PICWRK EQU 0FF70H ; PIC service work area FF80 PICDMA EQU 0FF80h ; DMA for PIC 0080 SECSIZE EQU 128 ; sector size 0000 FC_SYSTEM EQU 0 ; EXIT CP/M 0001 FC_CONST EQU 1 ; CONST 0002 FC_CONIN EQU 2 ; CONIN 0003 FC_CONOUT EQU 3 ; CONOUT 0004 FC_READ EQU 4 ; READ SD Card 0005 FC_WRITE EQU 5 ; WRITE SD Card 0006 FC_PIC EQU 6 ; RETURN TO PIC ; ++++ work area for PIC Interface FF70 FuncNo EQU PICWRK ; ds 1 : function No FF71 RetVal EQU PICWRK + 1 ; ds 1 : return value FF72 CoData EQU PICWRK + 2 ; ds 1 : conout data FF73 SelDk EQU PICWRK + 3 ; ds 1 FF74 Track EQU PICWRK + 4 ; ds 2 FF76 DmaAdr EQU PICWRK + 6 ; ds 2 FF78 Sector EQU PICWRK + 8 ; ds 1 0000' ASEG .Z80 ORG 0100H ; IPL for the CP/M with a PIC. 0100 31 0080 LD SP,0080H 0103 3E E9 LD A,0E9H ; JP (HP) ope-code 0105 32 0000 LD (0000H),A 0108 21 015E LD HL,IplMsg 010B CD 014A CALL PrnMsg 010E 3E 04 LD A,FC_READ 0110 32 FF70 LD (FuncNo),A 0113 AF XOR A 0114 32 FF73 LD (SelDk),A 0117 5F LD E,A ; DE : track No 0118 57 LD D,A 0119 21 E400 LD HL,CCP 011C 01 3701 LD BC,SysSec*256 + 1;B:sector counter, C:sector No 011F ED 53 FF74 LoopTr: LD (Track),DE 0123 79 Loop: LD A,C 0124 32 FF78 LD (Sector),A 0127 C5 PUSH BC 0128 D5 PUSH DE 0129 E5 PUSH HL 012A 21 012E LD HL,NextHalt 012D 76 HALT 012E NextHalt: 012E E1 POP HL 012F 11 FF80 LD DE,PICDMA 0132 EB EX DE,HL 0133 01 0080 LD BC,SECSIZE 0136 ED B0 LDIR 0138 EB EX DE,HL 0139 D1 POP DE 013A C1 POP BC 013B 05 DEC B 013C CA FA00 JP Z,BIOS 013F 0C INC C 0140 79 LD A,C 0141 FE 40 CP MaxSec 0143 38 DE JR C,Loop 0145 0E 00 LD C,0 0147 13 INC DE 0148 18 D5 JR LoopTr 014A PrnMsg: 014A 3E 03 LD A,FC_CONOUT 014C 32 FF70 LD (FuncNo),A 014F PrnM00: 014F 7E LD A,(HL); 0150 23 INC HL 0151 B7 OR A 0152 C8 RET Z 0153 32 FF72 LD (CoData),A 0156 EB EX DE,HL 0157 21 015B LD HL,PrnM10 015A 76 HALT 015B EB PrnM10: EX DE,HL 015C 18 F1 JR PrnM00 015E IplMsg: 015E 0D 0A DB CR,LF 0160 6C 6F 61 64 DB 'loading...' 0164 69 6E 67 2E 0168 2E 2E 016A 00 DB 0 END
★2018/03/15 追記 iplの版数が古かったので差し換えました^^;


 前回の記事のBIOS試験の延長でIPLを読込み起動してみたところ、多少のゴニョゴニョした作業はあったものの CP/M の初起動に成功しました。(^^)/

 picle言語で色々確認後、最終的にはC言語に置き換えようかと思っていましたが、picle言語だけでCP/M起動までできてしまいました。^^

 初起動の様子が下の表示です。IPL試験用のpicleのリスト表示後、runコマンドで実行しています。IPLのロード状態確認のためにメモリダンプ表示後、Z80にリセットをかけてIPLを実行させています。
 ディバッグ用の表示のコメントアウトがあったり、少し生々しい状態で今後整理が必要ですがCP/M 初ブート記念として貼っておきます。

IPL試験・・CP/Mが起動した(picle言語)
:l 1:# CP/M boot test for PIC24FJ64GA004 with picle 2:# Ver 0.02 by skyriver 2018/03/14 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var ProgStart,ProgWrk,_WrkVal,_PicDma; 8: 9:proc initSd() { 10: var dmy,ans,i; 11: 12: ProgStart = $0100; # Prog start addr 13: ProgWrk = $ff70; # Prog work addr 14: _PicDma = $ff80; 15: _WrkVal = Alloc( 5 ); 16: 17: SetCsOff(); 18: for ( i=0; i<10; i=i+1 ) { 19: SpiSnd( $ff ); 20: } 21: TmWait( ByteTimer * 2 ); 22: SetCsOn(); 23: SpiSnd( $40 ); # CMD0 24: SpiSnd( 0 ); 25: SpiSnd( 0 ); 26: SpiSnd( 0 ); 27: SpiSnd( 0 ); 28: SpiSnd( $95 ); 29: 30: ans = SpiRcvAns(); 31: SetCsOff(); 32: 33: if ( ans <> 1 ) { 34: PrnVal( "Cmd0Res:", ans ); 35: } else { 36: SetCsOn(); 37: SpiSnd( $ff ); # __ improve error 38: SpiSnd( $48 ); # CMD8 39: SpiSnd( 0 ); 40: SpiSnd( 0 ); 41: SpiSnd( 1 ); 42: SpiSnd( $aa ); 43: SpiSnd( $87 ); 44: ans = SpiRcvAns(); 45: SpiRcvN( 4 ); # 16M:00 00 01 aa 46: SetCsOff(); 47: if ( ans <> 1 ) { 48: PrnVal( "CMD8 err:", ans ); 49: } else { 50: if ( (_SpiBuf[2] <> $01) | (_SpiBuf[3] <> $aa ) ) { 51: PrnStr_("SDC not v2" ); 52: } else { 53: SdhcFlg = 1; 54: do { 55: SetCsOn(); 56: SpiSnd( $77 ); # CMD55 57: SpiSnd( 0 ); 58: SpiSnd( 0 ); 59: SpiSnd( 0 ); 60: SpiSnd( 0 ); 61: SpiSnd( $65 ); 62: ans = SpiRcvAns(); 63: if ( ans = 1 ) { 64: SpiSnd( $69 ); # ACMD41 65: SpiSnd( $40 ); 66: SpiSnd( $ff ); 67: SpiSnd( $80 ); 68: SpiSnd( $00 ); 69: SpiSnd( $17 ); 70: ans = SpiRcvAns(); 71: } 72: SetCsOff(); 73: } while ( ans <> 0 ); 74: SetCsOn(); 75: SpiSnd( $7a ); # CMD58 76: SpiSnd( 0 ); 77: SpiSnd( 0 ); 78: SpiSnd( 0 ); 79: SpiSnd( 0 ); 80: SpiSnd( $fd ); 81: ans = SpiRcvAns(); 82: SpiRcvN( 4 ); # 16MB:c0 ff 80 00 83: SetCsOff(); 84: SPISTAT[0] = $0000; 85:# SPISTAT[1] = $7e; # SPI1CON1 prescale1:1,prescale1:1 = 1:1 4M NG 86:# SPISTAT[1] = $7a; # SPI1CON1 prescale2:1,prescale4:1 = 8:1 2M NG 87: SPISTAT[1] = $7d; # SPI1CON1 prescale1:1,prescale16:1 = 16:1 1M OK 88: SPISTAT[0] = $8000; 89: if ( ans <> 0 ) { 90: PrnVal( "CMD58 err:", ans ); 91: } 92: } 93: } 94: } 95: SetCsOff(); 96:} 97: 98: 99:proc PicSrv() { 100: var i,fno,rval; 101: 102: while (1) { 103: while ( LATB[-1] & 8 ) {} # wait halt 104: PmpOn(); 105: PmpSetAdr( ProgWrk ); 106: fno = MemRd(); # dummy 107: for ( i=0; i<9; i=i+1 ) { 108: _WrkVal[i] = MemRd(); 109: } 110: fno = _WrkVal[0]; # function No 111: if ( fno = 1 ) { # CONST 112: if ( InpChk_() ) { 113: rval = $ff; 114: } else { 115: rval = 0; 116: } 117: } 118: else if ( fno = 2 ) { # CONIN 119: if ( InpChk_() ) { 120: rval = InpChar_(); 121: if ( rval = $1b ) { # if ESC then end 122: exit(); 123: } 124: } else { 125:# PrnChar_('x'); # __ for debug 126: rval = InpChar_(); 127: } 128: } 129: else if ( fno = 3 ) { # CONOUT 130: PrnChar_( _WrkVal[2] ); 131: rval = 0; 132: } 133: else if ( fno = 4 ) { # READ 134: var track; 135: track = _WrkVal + 4; 136: rval = BlkRead( track[0]*64 + _WrkVal[8] ); 137:#PrnVal( "\nTk:",track[0]); 138:#PrnVal( " Sec:", _WrkVal[8] ); 139: if ( rval = 0 ) { 140: PmpSetAdr( _PicDma ); 141: for ( i = 0; i < 128; i=i+1 ) { 142: MemWr( _SpiBuf[ i ] ); 143: } 144:#dump(_PicDma); 145:#if ( _WrkVal[8] = $37 ) { 146:# dump( $fa00 ); 147:#} 148: } 149: } 150: else if ( fno = 5 ) { # WRITE 151: var track; 152: track = _WrkVal + 4; 153: PmpSetAdr( _PicDma ); 154: i = MemRd(); # dummy 155: for ( i = 0; i < 128; i=i+1 ) { 156: _SpiBuf[ i ] = MemRd(); 157: } 158: rval = BlkWrite( track[0]*64 + _WrkVal[8] ); 159: } else { 160: PrnStr_( "\nFunc err" ); 161: } 162: PmpSetAdr( ProgWrk + 1 ); 163: MemWr( rval ); 164: 165: PmpOff(); 166: LATC[0] = $0000; # reset on 167: BusRelease(); 168: LATC[0] = $0001; # reset off 169: } 170:} 171: 172: 173:proc main() { 174: var i; 175: init(); 176: initPmp(); 177: initSpi(); 178: initSd(); 179: 180: if ( BlkRead( 0 ) <> 0) { 181: PrnStr_( "NG" ); 182: SetCsOff(); 183: } else { 184: SetCsOff(); 185: PmpOn(); 186: 187: PmpSetAdr( 0 ); 188: MemWr( $c3 ); 189: MemWr( ProgStart ); 190: MemWr( ProgStart / 256 ); 191: 192: PmpSetAdr( ProgStart ); 193: for ( i = 0; i< 128; i=i+1 ) { 194: MemWr( _SpiBuf[ i ] ); 195: } 196: dump( 0 ); 197: dump( ProgStart ); 198: LATC[0] = $0000; # reset on 199: BusRelease(); 200: LATC[0] = $0001; # reset off 201: PicSrv(); 202: } 203:} :run 0000 : C3 00 01 00 02 C3 06 EC 68 00 68 00 68 00 68 00 0010 : 68 00 68 00 68 00 68 00 68 00 68 00 68 00 68 00 0020 : 68 00 68 00 68 00 68 00 68 00 68 00 68 00 2D 00 0030 : 68 00 2D 00 68 00 86 00 C3 86 D8 00 86 00 2D 00 0040 : 68 00 43 00 43 00 43 00 43 00 43 00 43 00 43 00 0050 : 43 00 43 00 43 00 43 00 43 00 43 00 00 53 54 41 0060 : 54 20 20 20 20 43 4F 4D D1 22 04 0C 00 20 20 20 0070 : 20 20 20 20 20 20 20 20 00 00 00 00 00 00 E6 FA 0100 : 31 80 00 3E E9 32 00 00 21 5E 01 CD 4A 01 3E 04 0110 : 32 70 FF AF 32 73 FF 5F 57 21 00 E4 01 01 37 ED 0120 : 53 74 FF 79 32 78 FF C5 D5 E5 21 2E 01 76 E1 11 0130 : 80 FF EB 01 80 00 ED B0 EB D1 C1 05 CA 00 FA 0C 0140 : 79 FE 40 38 DE 0E 00 13 18 D5 3E 03 32 70 FF 7E 0150 : 23 B7 C8 32 72 FF EB 21 5B 01 76 EB 18 F1 0D 0A 0160 : 6C 6F 61 64 69 6E 67 2E 2E 2E 00 E5 E5 E5 E5 E5 0170 : E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 loading... 64k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>dir A: ASM COM : BIOS ASM : CPM SYS : DDT COM A: DEBLOCK ASM : DISKDEF LIB : DSKMAINT COM : BCLOAD A: DUMP ASM : DUMP COM : ED COM : LOAD COM A: PIP COM : READ ME : STAT COM : SUBMIT COM A: XSUB COM a>ddt DDT VERS 2.2 -d 0100 01 BC 0F C3 3D 01 43 4F 50 59 52 49 47 48 54 20 ....=.COPYRIGHT 0110 28 43 29 20 31 39 38 30 2C 20 44 49 47 49 54 41 (C) 1980, DIGITA 0120 4C 20 52 45 53 45 41 52 43 48 20 20 20 20 20 20 L RESEARCH 0130 44 44 54 20 56 45 52 53 20 32 2E 32 24 31 00 02 DDT VERS 2.2$1.. 0140 C5 C5 11 30 01 0E 09 CD 05 00 C1 21 07 00 7E 3D ...0.......!..~= 0150 90 57 1E 00 D5 21 00 02 78 B1 CA 65 01 0B 7E 12 .W...!..x..e..~. 0160 13 23 C3 58 01 D1 C1 E5 62 78 B1 CA 87 01 0B 7B .#.X....bx.....{ 0170 E6 07 C2 7A 01 E3 7E 23 E3 6F 7D 17 6F D2 83 01 ...z..~#.o}.o... 0180 1A 84 12 13 C3 69 01 D1 2E 00 E9 0E 10 CD 05 00 .....i.......... 0190 32 5F 1E C9 21 66 1E 70 2B 71 2A 65 1E EB 0E 11 2_..!f.p+q*e.... 01A0 CD 05 00 32 5F 1E C9 11 00 00 0E 12 CD 05 00 32 ...2_..........2 01B0 5F 1E C9 21 68 1E 70 2B 71 2A 67 1E EB 0E 13 CD _..!h.p+q*g..... -^C a>


 ついでにブレッドボードの写真も貼っておきます(写真で見るとメッチャ汚い・・冷静に見たら肉眼で見ても汚いw)。
 使用しているICは Z84C0020PEC(Z80 20MHz:40-Pin DIP)、HM628128ALP-7(128Kbytes SRAM:32-Pin DIP)、PIC24FJ64GA004(44-Pin TQFP) の3個でTTL等は使っていません。右下の緑の基板はSDカードホルダ基板です。
 SDカードはSDHCタイプの16GBのものを使っています。

PicCPM実験用Z80ブレッドボード



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