So-net無料ブログ作成
English Version

レトロマイコン86ボードの構想(その6)メモリチェックプログラムの製作 [8086]

 前回の記事で書いたようにヘキサファイルをV20のメモリ内にダウンロードできるようになったのでプログラムを作って遊んでいます。
 アセンブラはCP/M-86のASM86を使い、アセンブラから出力されるヘキサファイルをhexファイルローダーでV20内のメモリにダウンロードして動かしています。

 環境としてはMS-DOS Player上でCP/M-86エミュレータ(cpm86.exe)を動かし、ASM86.CMDを起動しています。

 しかし、プログラムを作成して動かしてみると、不安定であり、ブレッドボード上の配線のチェックを行ったところ、接続線が1本断線していましたorz
 今回は2度目の配線なのでテスタで線材の導通を確認しながら配線したのですが、最後の方で一部チェックせずに配線した部分で問題が発生していました(手抜きは駄目ですね・・)^^;

 状況は改善したものの例えばダミーのPUSH/POPを追加しただけで動作が変わることがあったり等、微妙に不安定な要素があったので手抜きせずにメモリチェックプログラムを作成して確認してみました。

 理想を言えばメモリ上に変数を置かずにレジスタだけで動作する(CALLも使用しない)方がいいのですが、そこまで不安定ではないのでメモリ上の変数やCALLは許容することにして、アドレスバスやデータバスのエラーはきちんと検出したいので
  • チェック書込みとチェック方法
     チェック対象メモリ全体にチェックデータを書込んだ後に書き込んだデータが読込めるか確認する。

  • 書き込みデータ
     簡易的な乱数(合同法)を使って生成し、書込み開始時に乱数のseedを保存し、チェック開始時に乱数seedを復元する。
    通常の合同法ではrand(n+1) = A x rand(n) + B(A,Bは素数が望ましい、Bは無い場合もある)ですが、LSBが固定されないように「A x rand(n)」の結果の特定ビットが1の場合、Bを加算するようにしました。

  • 長期安定確認
     上記の書込みとチェックを繰り返し動かし(乱数のseedは継続利用)、チェック開始時に何回目のチェックかを2バイトヘキサ表示する

ようにしました。

 プログラム自体は0010:0000からに置き、0030:0000~7FFE:0000をチェック対象にしています(メモリ最後の部分はPICとのI/F用とリセット時のジャンプ命令で使用するのでチェック対象外)。

 結果として、最初は結構すぐにエラーが発生する(例えばチェック1回目で「err 17E0:0000」が発生)状況でしたが、回路の抵抗値の調整等を行い少し安定になりました。
 最終的には、安定化電源で供給していた電圧がブレッドボード上では0.2V程度低かったので、5.0Vにしたところ数十回の連続チェックも通るようになりました^^


メモリチェックプログラム(アセンブラ)
CP/M ASM86 1.1 SOURCE: MEMCHK.A86 Check Memory title 'Check Memory' ;++++++++++++++++++++++++++++++++++++ ; Check Memory for Pic24V20 ; Ver 0.01 2019/08/19 skyriver ;++++++++++++++++++++++++++++++++++++ FFFF true EQU -1 0000 false EQU not true 000D CR EQU 13 000A LF EQU 10 0010 PrgSeg EQU 0010H 0030 StartSeg EQU 0030H 7FFE EndSeg EQU 7FFEH B46D SEED EQU 46189 1D05 MULVAL EQU 7429 81EF ADDVAL EQU 33263 0400 CHKBIT EQU 0400H ; memory assign ; ffde0 ffde:0000 SD buf 512bytes ; fffe0 ffde:0200 work area 16 bytes ; ffff0 ffff:0000 reset jump ; FFDE PWrkSeg EQU 0FFDEH 0200 SdBufSz EQU 512 0000 SdBuf EQU 0 ; SD buffer offset ; function No. 0000 FC_EXIT 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_PUNCH EQU 6 ; PUNCH 0007 FC_READER EQU 7 ; READER 0200 PicWrk EQU SdBuf + SdBufSz ; Pic I/F work area 0200 FuncNo EQU PicWrk ; RB 1 ; function No 0201 CoData EQU FuncNo + 1 ; RB 1 ; conout data 0202 SdSec EQU CoData + 1 ; RB 4 ; SD block No. 0206 RetVal EQU SdSec + 4 ; RB 2 ; return value 0208 PreSd EQU RetVal + 2 ; RB 4 ; previos SD block No. 020C ChgFlg EQU PreSd + 4 ; RB 1 ; buffer change flag for Blocking/Deblocking 020D BlkCnt EQU ChgFlg + 1 ; RB 1 ; Block first write counter ; *** offset from PicWrk *** 0000 oFuncNo EQU FuncNo - PicWrk 0001 oCoData EQU CoData - PicWrk 0002 oSdSec EQU SdSec - PicWrk 0006 oRetVal EQU RetVal - PicWrk 0008 oPreSd EQU PreSd - PicWrk 000C oChgFlg EQU ChgFlg - PicWrk 000D oBlkCnt EQU BlkCnt - PicWrk 0010 CSEG PrgSeg ORG 0 0000 8CC8 START: MOV AX,CS 0002 8ED0 MOV SS,AX 0004 BC5C01 MOV SP,StackBase 0007 B8DEFF MOV AX,PWrkSeg 000A 8EC0 MOV ES,AX 000C BE0002 MOV SI,PicWrk 000F 2EC7062E0100 MOV CS:ChkCnt,0 00 0016 BA0080 MOV DX,8000H 0019 2EC70630016D MOV CS:RndVal,SEED B4 0020 BB1001 MOV BX,offset StMsg 0023 E85400 007A CALL PutStr 0026 B05B MA010: MOV AL,'[' 0028 E82200 004D CALL PutChar 002B 2EA12E01 MOV AX,CS:ChkCnt 002F 40 INC AX 0030 2EA32E01 MOV CS:ChkCnt,AX 0034 E82000 0057 CALL PutHexW 0037 B05D MOV AL,']' 0039 E81100 004D CALL PutChar 003C E86500 00A4 CALL Write 003F E88600 00C8 CALL Check 0042 E9E1FF 0026 JMP MA010 ; exit 0045 26C60400 Exit: MOV ES:BYTE PTR oFuncNo[SI],FC_EXIT 0049 EE OUT DX,AL 004A E9FDFF 004A JMP $ ; PutChar ; AL <- data PutChar: 004D 26C60403 MOV ES:BYTE PTR oFuncNo[SI],FC_CONOUT 0051 26884401 MOV ES:BYTE PTR oCoData[SI],AL 0055 EE OUT DX,AL 0056 C3 Return: RET ; put hex(Word) ; AX <- data PutHexW: 0057 86C4 XCHG AL,AH 0059 E80200 005E CALL PutHex 005C 86C4 XCHG AL,AH ; go through PutHex ; Put Hex(Byte) ; AL <- data 005E 8AD0 PutHex: MOV DL,AL 0060 D0E8 SHR AL,1 0062 D0E8 SHR AL,1 0064 D0E8 SHR AL,1 0066 D0E8 SHR AL,1 0068 E80200 006D CALL PutNbl 006B 8AC2 MOV AL,DL ; go through PutNbl ; put nible ; AL -< data 006D 240F PutNbl: AND AL,0FH 006F 0430 ADD AL,'0' 0071 3C3A CMP AL,'9'+1 0073 7202 0077 JC PutN10 0075 0407 ADD AL,'A' - '0' - 10 0077 E9D3FF 004D PutN10: JMP PutChar ; put string ; BX <- string(segment:CS) 007A 2E8A870000 PutStr: MOV AL,CS:[BX] 007F 84C0 TEST AL,AL 0081 74D3 0056 JZ Return 0083 E8C7FF 004D CALL PutChar 0086 43 INC BX 0087 E9F0FF 007A JMP PutStr ; rand ; AX <- rand 008A 53 Rand: PUSH BX 008B 52 PUSH DX ; destroyed by mul 008C 2EA13001 MOV AX,CS:RndVal 0090 BB051D MOV BX,MULVAL 0093 F7E3 MUL BX 0095 A90004 TEST AX,CHKBIT 0098 7403 009D JZ Rand10 009A 05EF81 ADD AX,ADDVAL 009D 2EA33001 Rand10: MOV CS:RndVal,AX 00A1 5A POP DX 00A2 5B POP BX 00A3 C3 RET ; write memoy 00A4 2EA13001 Write: MOV AX,CS:RndVal 00A8 2EA33201 MOV CS:SeedVal,AX 00AC BB3000 MOV BX,StartSeg 00AF 8EDB Wri10: MOV DS,BX 00B1 BF0000 MOV DI,0 00B4 B90800 MOV CX,8 00B7 E8D0FF 008A Wri20: CALL Rand 00BA 8905 MOV WORD PTR [DI],AX 00BC 47 INC DI 00BD 47 INC DI 00BE E2F7 00B7 LOOP Wri20 00C0 43 INC BX 00C1 81FBFE7F CMP BX,EndSeg 00C5 75E8 00AF JNZ Wri10 00C7 C3 RET ; check memory 00C8 2EA13201 Check: MOV AX,CS:SeedVal 00CC 2EA33001 MOV CS:RndVal,AX 00D0 BB3000 MOV BX,StartSeg 00D3 B80100 MOV AX,1 00D6 F8 CLC 00D7 8EDB Chk10: MOV DS,BX 00D9 BF0000 MOV DI,0 00DC B90800 MOV CX,8 00DF E8A8FF 008A Chk20: CALL Rand 00E2 3B05 CMP AX,WORD PTR [DI] 00E4 750C 00F2 JNZ ChkErr 00E6 47 INC DI 00E7 47 INC DI 00E8 E2F5 00DF LOOP Chk20 00EA 43 INC BX 00EB 81FBFE7F CMP BX,EndSeg 00EF 75E6 00D7 JNZ Chk10 00F1 C3 RET 00F2 BB2701 ChkErr: MOV BX,offset ErrMsg 00F5 E882FF 007A CALL PutStr 00F8 8CD8 MOV AX,DS 00FA E85AFF 0057 CALL PutHexW 00FD B03A MOV AL,':' 00FF E84BFF 004D CALL PutChar 0102 8BC7 MOV AX,DI 0104 E850FF 0057 CALL PutHexW 0107 BB2401 MOV BX,offset CrLfMsg 010A E86DFF 007A CALL PutStr 010D E935FF 0045 JMP Exit 0110 0D0A53746172 StMsg DB CR,LF,'Start Memory Check' 74204D656D6F 727920436865 636B 0124 0D0A00 CrLfMsg DB CR,LF,0 0127 0D0A65727220 ErrMsg DB CR,LF,'err ',0 00 ;EnMsg DB CR,LF,'complete',0 012E ChkCnt RW 1 0130 RndVal RW 1 0132 SeedVal RW 1 0134 RW 20 015C StackBase EQU ( offset $ + 1 ) AND 0FFFEH END END OF ASSEMBLY. NUMBER OF ERRORS: 0. USE FACTOR: 2%


 アセンブル時のコマンドはこんな感じです。

C:¥picle¥V20¥asm¥bios¥cmd>msdos cpm86 asm86 Memchk
CP/M-86 emulator for DOS vers 1.3 - 11/30/97
Copyright (c) 1985, 1997 Jim Lopushinsky

CP/M 8086 ASSEMBLER VER 1.1
END OF PASS 1
END OF PASS 2
END OF ASSEMBLY. NUMBER OF ERRORS: 0. USE FACTOR: 2%


C:¥picle¥V20¥asm¥bios¥cmd>


 アセンブルした結果、生成されたHexファイルをHexファイルローダーでダウンロードしている様子が下記です。
 Hexファイルの内容をTeraTermにコピペするとデータタイプを表示しながらV20のメモリにロードされます。

:¥¥

+E000-EDC7 # Memory chack executer 2019/08/19
+F000-FC43 # Pic24V20 HexLoader v0.02 2019/08/12

:¥<$F000
3139
:run
HexLoader Start
e3aaaaaaaaaaaa1
:


 安定化した後の確認結果も貼っておきます。
 尚、途中でリセットして中断していますが、リセットしなければ永遠とメモリチェックを繰り返します。

メモリチェック結果
:l 1:# Memory chack executer 2019/08/19 2:# ver 0.01 by skyriver 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var ProgWrk,_WrkVal,_PicDma,SdSec; 8:var EscFlg,EscY; 9: 10: 11:proc PicSrv() { 12: var i,fno,rval; 13: 14: while (1) { 15: while (LATA[-1]&1) {} # wait reset 16: while (LATC[-1]&$40) {} # wait ready off 17: CMCON[0] = CMCON[0]&$feff; # CMP1 off 18: PmpOn(); 19: PmpSetAdr(ProgWrk); 20: fno=MemRd(); # dummy 21: for (i=0;i<2;i=i+1) { 22: _WrkVal[i]=MemRd(); 23: } 24: fno=_WrkVal[0]; # function No 25: rval=0; 26: if (fno=3) { # CONOUT 27: PrnChar_( _WrkVal[1] ); 28: } 29: else if (fno=0) { 30: break; 31: } else { 32: PrnStr_("\nFunc err"); 33: PrnHexB_(fno); 34: } 35: PmpOff(); 36: BusRelease(); 37: CMCON[0] = CMCON[0]|$0100; # CMP1 on 38: } 39:} 40: 41: 42:proc main() { 43: init(); 44: initPmp(); 45: initSpi(); 46: initSd(); 47: 48: ProgWrk = $ffe0; # work addr(fffe0) 49: _PicDma = $fde0; 50: 51: _WrkVal = Alloc(5); 52: SdSec=_WrkVal+2; # long SdSectorNo 53: 54: LATA[0]=LATA[0]|1; # on reset:a0 55: BusReq(); 56: LATA[0]=LATA[0]&$fffe; # off reset:a0 57: 58: PmpOn(); 59: 60: PmpSetAdr($07f0); 61: MemWr($ea);MemWr($00);MemWr($00);MemWr($10);MemWr($00); 62: 63: PmpOff(); 64: LATA[0]=LATA[0]|1; # on reset:a0 65: BusRelease(); 66: 67: Timer_ = 1; 68: while ( Timer_ ); 69: LATA[0]=LATA[0]&$fffe; # off reset:a0 70: 71: while ((LATC[-1]&$40)=0); # wait ready on 72: 73: PicSrv(); 74: 75: BusReq(); 76: PrnStr_("** end **"); 77: 78: Rdump($0100); 79:} :run Start Memory Check [0001][0002][0003][0004][0005][0006][0007][0008][0009][000A][000B][000C][000D][000E][000F][0010][0011][0012][0013][0014][0015][0016][0017][0018][0019][001A][001B][001C][001D][001E][001F][0020][0021][0022][0023][0024][0025][0026][0027][0028][0029][002A][002B][002C][002D][002E][002F][0030][0031][0032][0033]



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

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

レトロマイコン86ボードの構想(その5)HEXファイルローダーの製作 [8086]

 前回の記事で書いたように8088互換のV20とPICとのインターフェース部の動作確認が出来たので、今回はインテルヘキサファイルのローダーの製作について書いてみます。

 インテルヘキサファイルのフォーマットに関してはネット上に色々あります(例えばIntel HEX)ので情報は豊富です。
 レコードタイプは
  • 00 : data record(CP/M-86独自の81H~84Hも含む)
  • 01 : end of file
  • 02 : segment(CP/M-86独自の85H~88Hも含む)
  • 03 : start address

に対応しました。メモリへのダウンロードが目的なのでタイプ3については空読みするようにしています。

★2019/08/12 追記
 CP/M-86のASM86独自のレコードタイプ(81H~88H)に下記のソースも含めて対応しました。

 HexLoader自体はアセンブリ言語で書き、nasmを使ってアセンブルしています。
 アセンブルは下のようなバッチファイルで行い、アセンブルで生成されたたbinファイルを自作のbin2state(バイナリからpicleのステートメントへ変換するツール)で変換し、picleのソースに埋め込んでいます。

nasm -l %1.lst -o %1.bin %1.asm
bin2state <%1.bin >%1.txt


 ソースは以下のとおりです。

HexLoaderのアセンブリソース
1 ;***************************** 2 ; Pic24V20 HexLoader 3 ; Ver0.02 supports ASM86 HexFile 4 ; 2019/08/12 by skyriver 5 ;***************************** 6 7 8 CPU 8086 9 10 SEC_SZ EQU 512 ; sector size 11 WRK_START EQU 01e0H ; work start adr 12 13 FC_EXIT EQU 0 ; EXIT CP/M 14 FC_CONST EQU 1 ; CONST 15 FC_CONIN EQU 2 ; CONIN 16 FC_CONOUT EQU 3 ; CONOUT 17 FC_READ EQU 4 ; READ SD Card 18 FC_WRITE EQU 5 ; WRITE SD Card 19 FC_PUNCH EQU 6 ; PUNCH 20 FC_READER EQU 7 ; READER 21 22 SdBuf EQU WRK_START 23 PicWrk EQU SdBuf + SEC_SZ 24 25 STRUC tPic ; Pic I/F work area 26 00000000 <res 00000001> .FuncNo RESB 1 ; function No 27 00000001 <res 00000001> .RetVal RESB 1 ; return value 28 00000002 <res 00000001> .CoData RESB 1 ; conout data 29 00000003 <res 00000001> .SelDk RESB 1 ; selected disk 30 00000004 <res 00000002> .Track RESB 2 ; track No 31 00000006 <res 00000002> .DmaAdr RESB 2 ; DMA adr 32 00000008 <res 00000001> .Sector RESB 1 ; sector No. 33 ENDSTRUC 34 35 ; *** memory assign *** 36 37 ; ffc00 ffc0:0000 code area 38 ; 39 ; ffde0 ffc0:01e0 SD buf 512byte 40 ; fffe0 ffc0:03e0 work 16byte 41 ; ffff0 ffff:0000 reset jmp 42 43 44 ; SEGMENT CODE ABSOLUTE=0xffc0 45 SEGMENT CODE 46 47 ORG 0 48 49 00000000 8CC8 START: MOV AX,CS 50 00000002 8ED8 MOV DS,AX 51 00000004 8ED0 MOV SS,AX 52 00000006 BCE001 MOV SP,WRK_START 53 00000009 31C0 XOR AX,AX 54 0000000B 8EC0 MOV ES,AX 55 56 0000000D BA0080 MOV DX,8000H 57 58 00000010 BB[2200] MOV BX,MESG 59 00000013 E84100 CALL PUTS 60 00000016 E87300 CALL LOAD 61 00000019 E82800 CALL CONIN ; read CR 62 0000001C E83300 CALL EXIT 63 0000001F E9FDFF JMP $ 64 65 66 00000022 4865784C6F61646572- MESG: DB 'HexLoader Start',13,10,0 67 0000002B 2053746172740D0A00 68 00000034 20657272210D0A00 ERRMSG: DB ' err!',13,10,0 69 70 ; go pic nterface 71 ; AL <- Function No 72 ; AL -> return value 73 0000003C A2E003 PICSRV: MOV [PicWrk + tPic.FuncNo],AL 74 0000003F EE OUT DX,AL 75 00000040 A0E103 MOV AL,[PicWrk + tPic.RetVal] 76 00000043 C3 RET 77 78 79 ; get console status 80 ; AL -> 0FFH:data exist, 00H:no data 81 ;CONST: MOV AL,FC_CONST 82 ; JMP PICSRV 83 84 ; input from console 85 ; AL -> data 86 87 00000044 B002 CONIN: MOV AL,FC_CONIN 88 00000046 E9F3FF JMP PICSRV 89 90 91 ; output to console 92 ; CL <- data 93 94 00000049 B003 CONOUT: MOV AL,FC_CONOUT 95 0000004B 880EE203 MOV BYTE [PicWrk + tPic.CoData],CL 96 0000004F E9EAFF JMP PICSRV 97 98 99 ; return to PIC world 100 101 00000052 B000 EXIT: MOV AL,FC_EXIT 102 00000054 E9E5FF JMP PICSRV 103 104 105 ; put string 106 ; BX <- string adr 107 108 00000057 8A0F PUTS: MOV CL,[BX] 109 00000059 43 INC BX 110 0000005A 08C9 OR CL,CL 111 0000005C 7406 JZ PUTSE 112 0000005E E8E8FF CALL CONOUT 113 00000061 E9F3FF JMP PUTS 114 00000064 C3 PUTSE: RET 115 116 117 ; read hex nible 118 ; AL -> data 119 00000065 E8DCFF RDNBL: CALL CONIN 120 00000068 2C30 SUB AL,'0' 121 0000006A 3C0A CMP AL,10 122 0000006C 7202 JC RDNBLE 123 0000006E 04F9 ADD AL,10 + '0' - 'A' 124 00000070 C3 RDNBLE: RET 125 126 127 ; read byte data 128 ; AL -> byte data 129 130 00000071 E8F1FF RDBYTE: CALL RDNBL 131 00000074 D0E0 SHL AL,1 132 00000076 D0E0 SHL AL,1 133 00000078 D0E0 SHL AL,1 134 0000007A D0E0 SHL AL,1 135 0000007C 88C7 MOV BH,AL 136 0000007E E8E4FF CALL RDNBL 137 00000081 08F8 OR AL,BH 138 00000083 C3 RET 139 140 141 ; read hex word 142 ; AX -> data 143 00000084 E8EAFF RDWORD: CALL RDBYTE 144 00000087 88C4 MOV AH,AL 145 00000089 E9E5FF JMP RDBYTE 146 147 148 ; load hex file 149 150 0000008C B500 LOAD: MOV CH,0 151 0000008E E8B3FF LOAD01: CALL CONIN 152 00000091 3C3A CMP AL,':' 153 00000093 75F9 JNZ LOAD01 154 155 00000095 E8D9FF CALL RDBYTE ; get byte count 156 00000098 88C3 MOV BL,AL 157 0000009A E8E7FF CALL RDWORD ; get address 158 0000009D 89C7 MOV DI,AX 159 0000009F E8CFFF CALL RDBYTE ; get record type 160 161 000000A2 88C4 MOV AH,AL 162 000000A4 88C1 MOV CL,AL 163 000000A6 2480 AND AL,080H 164 000000A8 B0E0 MOV AL,080H + 'a' - 1 165 000000AA 7502 JNZ LOAD03 166 167 000000AC B030 LOAD02: MOV AL,'0' 168 000000AE 00C1 LOAD03: ADD CL,AL 169 000000B0 E896FF CALL CONOUT 170 000000B3 88E0 MOV AL,AH 171 172 000000B5 3C02 CMP AL,02H ; segment data 173 000000B7 7508 JNZ NXCK1 174 175 000000B9 E8C8FF TYP02: CALL RDWORD ; ** segment 176 000000BC 8EC0 MOV ES,AX 177 000000BE E9CDFF JMP LOAD01 178 179 000000C1 3C85 NXCK1: CMP AL,085H 180 000000C3 73F4 JNC TYP02 181 182 000000C5 08C0 OR AL,AL ; data record 183 000000C7 750E JNZ NXCK2 184 185 000000C9 88D9 TYP00: MOV CL,BL 186 000000CB E8A3FF TYP00A: CALL RDBYTE ; ** DATA 187 000000CE 268805 MOV [ES:DI],AL 188 000000D1 47 INC DI 189 000000D2 E2F7 LOOP TYP00A 190 000000D4 E9B7FF JMP LOAD01 191 192 000000D7 3C81 NXCK2: CMP AL,081H 193 000000D9 73EE JNC TYP00 194 195 000000DB 3C01 CMP AL,01H ; end of data 196 000000DD 7504 JNZ NXCK3 197 198 000000DF E88FFF CALL RDBYTE ; ** EOD 199 000000E2 C3 RET 200 201 000000E3 3C03 NXCK3: CMP AL,03H ; start address 202 000000E5 74A7 JZ LOAD01 ; not implement 203 204 000000E7 BB[3400] MOV BX,ERRMSG 205 000000EA E86AFF CALL PUTS 206 000000ED C3 RET


 テスト用のヘキサファイルは手で作るよりは一般的なツールで作った方がいいのでLASMを使いました。LASMはソースが100行以下であれば無料で使えます。

テスト用データ作成のためのLASM用ソース
;++++++++++++++++++++++++++++++++ ; Test data for HexLoader ; for lasm assembler ; ; asm & link command ; lasm32 testdata.asm ; lil32 -hex -sdseg=0030 testdata.obj ; ; 2019/08/10 by skyriver ;++++++++++++++++++++++++++++++++ dseg segment byte data: db '0123456789ABCDEF' dseg ends end


 上のソース内にアセンブルとリンクの方法をコメントで書いていますが、dsegの値を0030Hにしてリンクして生成されたヘキサファイルの内容はこんな感じです。

:020000020030CC
:10000000303132333435363738394142434445464E
:00000001FF


 下記がHexLoaderのpicleのリスト表示後、実行し、上のヘキサファイルをTeraTermにコピペした際のログです。
 スタートメッセージを表示後、「201」と表示されていますが、これはV20側の処理で受信したヘキサファイルのレコードタイプを出力しているものです(81H~88Hは'a'~'h'で表示)。

HexLoader実行時のログサンプル
:l 1:# Pic24V20 HexLoader v0.02 2019/08/12 2:# by skyriver 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var ProgWrk,_WrkVal,_PicDma,WrkTrk; 8: 9: 10:proc m( data ) { 11: MemWr( data ); 12:} 13: 14: 15:proc PicSrv() { 16: var i,fno,rval; 17: 18: while (1) { 19: while (LATC[-1]&$40) {} # wait ready off 20: CMCON[0] = CMCON[0]&$feff; # CMP1 off 21: PmpOn(); 22: PmpSetAdr(ProgWrk); 23: fno = MemRd(); # dummy 24: for (i=0;i<3;i=i+1) { 25: _WrkVal[i] = MemRd(); 26: } 27: fno = _WrkVal[0]; # function No 28: 29: if (fno=1) { # CONST 30: if (InpChk_()) { 31: rval = $ff; 32: } else { 33: rval = 0; 34: } 35: } 36: else if (fno=2) { # CONIN 37: rval = InpChar_(); 38: } 39: else if (fno=3) { # CONOUT 40: PrnChar_( _WrkVal[2] ); 41: } 42: else if (fno=0) { 43: break; 44: } else { 45: PrnStr_("\nFunc err"); 46: } 47: PmpSetAdr(ProgWrk+1); 48: MemWr(rval); 49: 50: PmpOff(); 51: BusRelease(); 52: CMCON[0] = CMCON[0]|$0100; # CMP1 on 53: } 54:} 55: 56: 57:proc main() { 58: var adr; 59: init(); 60: initPmp(); 61:# initSpi(); 62:# initSd(); 63: 64: ProgWrk = $ffe0; # work addr(fffe0) 65: _PicDma = $fde0; 66: _WrkVal = Alloc( 5 ); 67: WrkTrk = Alloc( 2 ); 68: 69: LATA[0]=LATA[0]|1; # on reset:a0 70: BusReq(); 71: LATA[0]=LATA[0]&$fffe; # off reset:a0 72: 73: PmpOn(); 74: 75: PmpSetAdr($07f0); 76: m($ea);m($00);m($00);m($c0);m($ff); 77: 78: adr = $400; # adr:ffc00 79: PmpSetAdr(adr); 80: 81: m($8c);m($c8);m($8e);m($d8);m($8e);m($d0);m($bc);m($e0); 82: m($01);m($31);m($c0);m($8e);m($c0);m($ba);m($00);m($80); 83: m($bb);m($22);m($00);m($e8);m($41);m($00);m($e8);m($73); 84: m($00);m($e8);m($28);m($00);m($e8);m($33);m($00);m($e9); 85: m($fd);m($ff);m($48);m($65);m($78);m($4c);m($6f);m($61); 86: m($64);m($65);m($72);m($20);m($53);m($74);m($61);m($72); 87: m($74);m($0d);m($0a);m($00);m($20);m($65);m($72);m($72); 88: m($21);m($0d);m($0a);m($00);m($a2);m($e0);m($03);m($ee); 89: m($a0);m($e1);m($03);m($c3);m($b0);m($02);m($e9);m($f3); 90: m($ff);m($b0);m($03);m($88);m($0e);m($e2);m($03);m($e9); 91: m($ea);m($ff);m($b0);m($00);m($e9);m($e5);m($ff);m($8a); 92: m($0f);m($43);m($08);m($c9);m($74);m($06);m($e8);m($e8); 93: m($ff);m($e9);m($f3);m($ff);m($c3);m($e8);m($dc);m($ff); 94: m($2c);m($30);m($3c);m($0a);m($72);m($02);m($04);m($f9); 95: m($c3);m($e8);m($f1);m($ff);m($d0);m($e0);m($d0);m($e0); 96: m($d0);m($e0);m($d0);m($e0);m($88);m($c7);m($e8);m($e4); 97: m($ff);m($08);m($f8);m($c3);m($e8);m($ea);m($ff);m($88); 98: m($c4);m($e9);m($e5);m($ff);m($b5);m($00);m($e8);m($b3); 99: m($ff);m($3c);m($3a);m($75);m($f9);m($e8);m($d9);m($ff); 100: m($88);m($c3);m($e8);m($e7);m($ff);m($89);m($c7);m($e8); 101: m($cf);m($ff);m($88);m($c4);m($88);m($c1);m($24);m($80); 102: m($b0);m($e0);m($75);m($02);m($b0);m($30);m($00);m($c1); 103: m($e8);m($96);m($ff);m($88);m($e0);m($3c);m($02);m($75); 104: m($08);m($e8);m($c8);m($ff);m($8e);m($c0);m($e9);m($cd); 105: m($ff);m($3c);m($85);m($73);m($f4);m($08);m($c0);m($75); 106: m($0e);m($88);m($d9);m($e8);m($a3);m($ff);m($26);m($88); 107: m($05);m($47);m($e2);m($f7);m($e9);m($b7);m($ff);m($3c); 108: m($81);m($73);m($ee);m($3c);m($01);m($75);m($04);m($e8); 109: m($8f);m($ff);m($c3);m($3c);m($03);m($74);m($a7);m($bb); 110: m($34);m($00);m($e8);m($6a);m($ff);m($c3); 111: 112: PmpOff(); 113: 114: LATA[0]=LATA[0]|1; # on reset:a0 115: BusRelease(); 116: Timer_ = 1; 117: while ( Timer_ ); 118: LATA[0]=LATA[0]&$fffe; # off reset:a0 119: 120: while ((LATC[-1]&$40)=0); # wait ready on 121: 122: PicSrv(); 123: 124: BusReq(); 125:} :run HexLoader start 201 :


 ヘキサファイルをダウンロード後のメモリ内容を確認した結果を以下に貼っておきます。
 0x0300からのデータがヘキサファイル内容のように「0123・・・DEF」になっていることから正常にダウンロードできたものと判断できます。

ヘキサファイルロード結果の確認
:l 1:# Pic24V20 dump 2:# by skyriver 3: 4:use LibCpm; 5:use LibSpi; 6: 7: 8:proc main() { 9: var adr; 10: init(); 11: initPmp(); 12:# initSpi(); 13:# initSd(); 14: 15: LATA[0]=LATA[0]|1; # on reset:a0 16: BusReq(); 17: LATA[0]=LATA[0]&$fffe; # off reset:a0 18: 19: PmpOn(); 20: dump($300); 21:} :run 0300 : 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 0310 : 0E 8D DC 81 31 D7 85 3B DD 97 58 AD 02 F5 12 6E 0320 : 59 D3 97 8C 40 B4 20 B9 B1 FD A9 5C 00 59 40 66 0330 : A7 AD 93 DD A1 D7 46 FF 19 E8 23 F9 11 5D 04 FF 0340 : B8 8D 89 29 40 7F 00 6F 6C FC 08 7E C5 7A 11 F5 0350 : D4 97 06 F8 89 AF 2A C4 60 E5 B1 FB 00 75 08 76 0360 : 59 8F A8 1C 02 8B 02 3B 24 FA 60 AB 10 39 20 E6 0370 : 51 9C 06 F7 9B 2E 0A FB 69 DE A1 57 10 6E 02 EE :


★2019/08/12 追記
 CP/M-86のasm86が出力するhexファイルの中にタイプが81H等のインテルヘキサファイルフォーマットに反するレコードがありました。
 調べてみたところ、CP/M-86システムガイドの中にasm86だけが使う拡張タイプについて書いてありましたので貼っておきます。

asm86での拡張ヘキサファイルフォーマット



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

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

レトロマイコン86ボードの構想(その4)V20とPICのI/F確認 [8086]

 前回の記事でPICからメモリに書込んだプログラムがV20で実行できることを確認できたので今回はPICとV20のインタフェース部の動作について確認しました。

 前回書いたようにアセンブラはNASMを使っていますがマニュアルにはできるように書いてある

  SEGMENT DATA
  MOV AX,DATA

でのセグメント値の参照やセグメントの絶対アドレス指定の

  SEGMENT CODE ABSOLUTE=0xffc0

でエラーやワーニングが発生したり、ORGを2カ所に書くとエラーになったりで悩みましたが、8086のメモリモデルとしてコードセグメントとデータセグメントを同じ値にするtinyモデルにし、データは EQUステートメントでアドレス指定することでPICとV20のインタフェースを確認しました。

 PICとのインタフェースの仕掛けとして、回路は初回の記事を参照して頂くとして処理概要としては
  1. V20からの処理要求
    I/F用のワークエリアにパラメータを設定し、A15=1のアドレスにI/O命令を発行する。
  2. READY信号がinactiveに遷移
    PICのコンパレータの出力(オープンドレイン)を使ってハード的にREADY信号がinactiveとなりV20はwait状態になる。
  3. PIC側で処理
    PIC側ではREADY信号を監視していてREADY信号がinactiveになったらコンパレータ出力を無効にし(プルアップしているのでREADY信号はactiveになる)HLDRQをactiveにしてバスの使用権を獲得し、ワークエリアに設定された要求を処理後、結果をワークエリアに保存する。
  4. PIC側のバスの開放
    バスを開放し、コンパレータの出力を有効にする。

となります。

 V20側のアセンブルリストは下記のとおりです。処理内容としてはこの手の確認では定番の"Hello!"の表示です。

インタフェース試験でのV20側アセンブラソース
1 ;***************************** 2 ; Pic24V20 Pic interface test 3 ; 2019/07/28 by skyriver 4 ;***************************** 5 6 7 CPU 8086 8 9 SEC_SZ EQU 512 ; sector size 10 WRK_START EQU 01e0H ; work start adr 11 12 FC_EXIT equ 0 ; EXIT CP/M 13 FC_CONST equ 1 ; CONST 14 FC_CONIN equ 2 ; CONIN 15 FC_CONOUT equ 3 ; CONOUT 16 FC_READ equ 4 ; READ SD Card 17 FC_WRITE equ 5 ; WRITE SD Card 18 FC_PUNCH equ 6 ; PUNCH 19 FC_READER equ 7 ; READER 20 21 SdBuf EQU WRK_START 22 PicWrk EQU SdBuf + SEC_SZ 23 24 STRUC tPic ; Pic I/F work area 25 00000000 .FuncNo RESB 1 ; function No 26 00000001 .RetVal RESB 1 ; return value 27 00000002 .CoData RESB 1 ; conout data 28 00000003 .SelDk RESB 1 ; selected disk 29 00000004 .Track RESB 2 ; track No 30 00000006 .DmaAdr RESB 2 ; DMA adr 31 00000008 .Sector RESB 1 ; sector No. 32 ENDSTRUC 33 34 ; *** memory assign *** 35 36 ; ffc00 ffc0:0000 code area 37 ; 38 ; ffde0 ffc0:01e0 SD buf 512byte 39 ; fffe0 ffc0:03e0 work 16byte 40 ; ffff0 ffff:0000 reset jmp 41 42 43 ; SEGMENT CODE ABSOLUTE=0xffc0 44 SEGMENT CODE 45 46 ORG 0 47 48 00000000 8CC8 START: MOV AX,CS 49 00000002 8ED8 MOV DS,AX 50 00000004 8EC0 MOV ES,AX 51 00000006 8ED0 MOV SS,AX 52 00000008 BCE001 MOV SP,WRK_START 53 0000000B BB[3500] MOV BX,MESG 54 0000000E BA0080 MOV DX,8000H 55 00000011 E80D00 CALL PUTS 56 00000014 E80300 CALL EXIT 57 00000017 E9FDFF JMP $ 58 59 0000001A C606E00300 EXIT: MOV BYTE [PicWrk + tPic.FuncNo],FC_EXIT 60 0000001F EE OUT DX,AL 61 00000020 C3 RET 62 63 64 ; print string 65 ; BX <- message adr 66 ; DX <- I/O Adr ( > 0x7fff ) 67 ; 68 00000021 C606E00303 PUTS: MOV BYTE [PicWrk + tPic.FuncNo],FC_CONOUT 69 00000026 8A07 CONO_L: MOV AL,[BX] 70 00000028 43 INC BX 71 00000029 08C0 OR AL,AL 72 0000002B 7407 JZ CONO_E 73 0000002D A2E203 MOV [PicWrk + tPic.CoData],AL 74 00000030 EE OUT DX,AL 75 00000031 E9F2FF JMP CONO_L 76 00000034 C3 CONO_E: RET 77 78 79 00000035 48656C6C6F210D0A00 MESG: DB 'Hello!',13,10,0 80


 PIC側でのリスト表示後実行した際のログを以下に示します。ログの末尾にあるように想定通り"Hello!"が表示されました(^^)/

V20とPICのI/F確認時のpicleソース
:l 1:# Pic24V20 Pic interface test 2019/07/28 2:# by skyriver 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var ProgWrk,_WrkVal,_PicDma,WrkTrk; 8: 9:proc MemDsp( adr ) { 10: var i; 11: PmpSetAdr( adr ); 12: i = MemRd(); 13: PrnStr_("\n"); 14: PrnHex_(adr); 15: PrnStr_(" :"); 16: for ( i=0; i<8; i=i+1 ) { 17: PrnStr_(" "); 18: PrnHexB_(MemRd()); 19: } 20:} 21: 22: 23:proc m( data ) { 24: MemWr( data ); 25:} 26: 27: 28:proc PicSrv() { 29: var i,fno,rval; 30: 31: while (1) { 32: while (LATC[-1]&$40) {} # wait ready off 33: CMCON[0] = CMCON[0]&$feff; # CMP1 off 34: PmpOn(); 35: PmpSetAdr(ProgWrk); 36: fno = MemRd(); # dummy 37: for (i=0;i<3;i=i+1) { 38: _WrkVal[i] = MemRd(); 39: } 40: fno = _WrkVal[0]; # function No 41: 42: if (fno=1) { # CONST 43: if (InpChk_()) { 44: rval = $ff; 45: } else { 46: rval = 0; 47: } 48: } 49: else if (fno=2) { # CONIN 50: rval = InpChar_(); 51: } 52: else if (fno=3) { # CONOUT 53: PrnChar_( _WrkVal[2] ); 54: } 55: else if (fno=0) { 56: break; 57: } else { 58: PrnStr_("\nFunc err"); 59: } 60: PmpSetAdr(ProgWrk+1); 61: MemWr(rval); 62: 63: PmpOff(); 64: BusRelease(); 65: CMCON[0] = CMCON[0]|$0100; # CPM1 on 66: } 67:} 68: 69:proc main() { 70: var adr; 71: init(); 72: initPmp(); 73:# initSpi(); 74:# initSd(); 75: 76: ProgWrk = $ffe0; # work addr(fffe0) 77: _PicDma = $fde0; 78: _WrkVal = Alloc( 5 ); 79: WrkTrk = Alloc( 2 ); 80: 81: LATA[0]=LATA[0]|1; # on reset:a0 82: BusReq(); 83: LATA[0]=LATA[0]&$fffe; # off reset:a0 84: 85: PmpOn(); 86: 87: PmpSetAdr($07f0); 88: m($ea);m($00);m($00);m($c0);m($ff); 89: 90:# MemDsp($7f0); 91: 92: adr = $400; # adr:ffc00 93: PmpSetAdr(adr); 94: 95: m($8c);m($c8);m($8e);m($d8);m($8e);m($c0);m($8e);m($d0); 96: m($bc);m($e0);m($01);m($bb);m($35);m($00);m($ba);m($00); 97: m($80);m($e8);m($0d);m($00);m($e8);m($03);m($00);m($e9); 98: m($fd);m($ff);m($c6);m($06);m($e0);m($03);m($00);m($ee); 99: m($c3);m($c6);m($06);m($e0);m($03);m($03);m($8a);m($07); 100: m($43);m($08);m($c0);m($74);m($07);m($a2);m($e2);m($03); 101: m($ee);m($e9);m($f2);m($ff);m($c3);m($48);m($65);m($6c); 102: m($6c);m($6f);m($21);m($0d);m($0a);m($00); 103: 104: PmpOff(); 105: 106: LATA[0]=LATA[0]|1; # on reset:a0 107: BusRelease(); 108: Timer_ = 1; 109: while ( Timer_ ); 110: LATA[0]=LATA[0]&$fffe; # off reset:a0 111: 112: while ((LATC[-1]&$40)=0); # wait ready on 113: 114: PicSrv(); 115: 116: BusReq(); 117:} :run Hello! :


 この時のロジアナ波形を貼っておきます。左端でRESETがオフになることでV20が動作を開始し、中央部のHLDACがhighになっている部分がV20からの'H'(Hello!の最初の文字)出力要求に対してPICが処理している部分となります。

PICとV20のインタフェース確認時の波形サンプル



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

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

レトロマイコン86ボードの構想(その3)V20の動作確認 [8086]

 今回は8088互換チップであるV20(uPD70108H)の簡単な動作確認を行ってみたので記録しておきます。
 前回のPIC24FJのPMP(パラレルマスタポート)機能の確認ではPICとメモリを実装した状態でしたが、ブレッドボードにV20の配線を追加したところ、不安定な状態でなかなか改善しなかったので古いブレッドボードをあまり使っていないものに交換し再度配線し直したところなんとか安定動作するようになりました。

 しかし後述するようにV20のクロックが8MHzの場合は安定に動作していますが、16MHzでは動作しません。

 V20の動作確認をするにあたり、ハンドアセンブルでは辛いのでアセンブラ環境が必要になりますが、free(BSDライセンス)でWindows環境でも使えるNASMを使うことにしました。
 NASMはダウンロードしたアーカイブファイルを解凍してpathを通せばいいだけなのでインストールも楽でWindowsのレジストリが変更されることもありません。

 リンカはVisualStudioのものが使えるようですが、単一のソースファイルであれば(複数ソースをリンクしないのであれば)、-o オプションでバイナリファイルを作成するとアセンブルされたコードの入ったファイルが生成されます。
 このバイナリファイルをPic24CPMの開発時に作成したpicleのステートメントに変換するツールを使いpicleのステートメントに変換し、picleソースに入れ込んでいます。

 ニーモニックの表記でメモリアクセス時は[]で囲むように統一されているのでワークエリアのアドレスなのか、中身なのか混乱することが無い等、インテルのニーモニックより改善されていて使い易くなっています。しかし英語のマニュアルが217ページあり、斜め読みするだけでもある程度の時間が必要です(プアなマニュアルよりは細かく記載されている方が絶対いいけどね)

 V20の動作確認のために下のリストのような簡単なものを作りました。

V20動作確認ソース
1 ;***************************** 2 ; Pic24V20 test 3 ; 2019/07/26 by skyriver 4 ;***************************** 5 6 7 CPU 8086 8 9 segment code 10 11 org 0200h 12 13 00000000 8CC8 start: mov ax, cs 14 00000002 8ED8 mov ds, ax 15 00000004 B83412 mov ax,1234h 16 00000007 A3[0D00] mov [data],ax 17 0000000A E9FDFF jmp $ 18 0000000D 90 data: nop 19 0000000E 90 nop 20 0000000F 90 nop 21 00000010 90 nop 22


 処理内容としてはプログラムの末尾に0x1234を書込むという単純なものです。
 メモリ(K6T4008C1B-DB70)は512KBのものを1個使用していて、V20のメモリ空間(1MB)の半分のサイズですが、V20のリセット直後の実行アドレスがメモリのエンド領域(0xffff0)なのでメモリ空間の後半に前半と同じイメージが見えてアクセスできるようにしています。

 アセンブルとpicleステートメントへの変換操作は

アセンブルとpicleステートメントへの変換操作
C:\src\picle\V20\asm\nasm>type asm.bat nasm -l %1.lst -o %1.bin %1.asm C:\src\picle\V20\asm\nasm>asm v20test C:\src\picle\V20\asm\nasm>nasm -l v20test.lst -o v20test.bin v20test.asm C:\src\picle\V20\asm\nasm>bin2state <v20test.bin >v20test.txt


こんな感じです。

 下記はV20動作テスト用のpicleソースを表示後、実行した際のログです。
 V20のプログラム実行により0x020dからの2バイトが想定通り0x1234に書き換えられていることが判ります。
 41行目でV20がリセット直後に実行する0xffff0アドレスに 0000:0200 へのファージャンプ命令を書込んでいます。

PMP機能確認用picleソース
:l 1:# V20 run test 2019/07/26 2:# by skyriver 3: 4:use LibCpm; 5:use LibSpi; 6: 7: 8:proc MemDsp( adr ) { 9: var i; 10: PmpSetAdr( adr ); 11: i = MemRd(); 12: PrnStr_("\n"); 13: PrnHex_(adr); 14: PrnStr_(" :"); 15: for ( i=0; i<8; i=i+1 ) { 16: PrnStr_(" "); 17: PrnHexB_(MemRd()); 18: } 19:} 20: 21: 22:proc m( data ) { 23: MemWr( data ); 24:} 25: 26: 27:proc main() { 28: var adr; 29: init(); 30: initPmp(); 31:# initSpi(); 32:# initSd(); 33: 34: LATA[0]=LATA[0]|1; # on reset:a0 35: BusReq(); 36: LATA[0]=LATA[0]&$fffe; # off reset:a0 37: 38: PmpOn(); 39: 40: PmpSetAdr($07f0); 41: m($ea);m($00);m($02);m($00);m($00); 42: 43: MemDsp($7f0); 44: 45: adr = $0200; 46: PmpSetAdr(adr); 47: 48: m($8c);m($c8);m($8e);m($d8);m($b8);m($34);m($12);m($a3); 49: m($0d);m($02);m($e9);m($fd);m($ff);m($90);m($90);m($90); 50: m($90); 51: 52: dump(adr); 53: PmpOff(); 54: 55: LATA[0]=LATA[0]|1; # on reset:a0 56: BusRelease(); 57: Timer_ = 1; 58: while ( Timer_ ); 59: LATA[0]=LATA[0]&$fffe; # off reset:a0 60: 61: Timer_ = 10; 62: while ( Timer_ ); 63: 64: BusReq(); 65: PmpOn(); 66: PrnStr_( "\n------------" ); 67: MemDsp($7f0); 68: dump(adr); 69: PmpOff(); 70:} :run 07F0 : EA 00 02 00 00 DD 61 FF 0200 : 8C C8 8E D8 B8 34 12 A3 0D 02 E9 FD FF 90 90 90 0210 : 90 90 22 CC 22 AD 61 FA B1 BB 1A E5 02 A7 08 FB 0220 : 35 AC 09 7D 9C 16 80 DD 42 BB 96 BB 04 3D D0 7B 0230 : 51 FB 5E D7 AA 23 C0 2F 51 34 1C F6 01 FD 16 FB 0240 : 70 7F 27 7B B0 3E 0A 56 42 F3 74 DB 40 5B 01 B6 0250 : 0A BE 6E BB 84 5E 48 D5 D3 DF 04 56 20 75 03 1A 0260 : 7C AA 0D 7C 8A BA C9 8F CE DD 3E E5 B8 FB 01 F7 0270 : 91 F8 E9 3A 03 EF 02 F6 CA F9 00 F7 45 EF 51 7E ------------ 07F0 : EA 00 02 00 00 DD 61 FF 0200 : 8C C8 8E D8 B8 34 12 A3 0D 02 E9 FD FF 34 12 90 0210 : 90 90 22 CC 22 AD 61 FA B1 BB 1A E5 02 A7 08 FB 0220 : 35 AC 09 7D 9C 16 80 DD 42 BB 96 BB 04 3D D0 7B 0230 : 51 FB 5E D7 AA 23 C0 2F 51 34 1C F6 01 FD 16 FB 0240 : 70 7F 27 7B B0 3E 0A 56 42 F3 74 DB 40 5B 01 B6 0250 : 0A BE 6E BB 84 5E 48 D5 D3 DF 04 56 20 75 03 1A 0260 : 7C AA 0D 7C 8A BA C9 8F CE DD 3E E5 B8 FB 01 F7 0270 : 91 F8 E9 3A 03 EF 02 F6 CA F9 00 F7 45 EF 51 7E :


 冒頭でも書いたように V20(16MHz対応版)のクロックを16MHにすると動作しなかったので8Mhzにして動作確認しています。
 それぞれのクロックでのメモリリード時の波形サンプルを下図に示します。この時のロジアナのサンプリング周波数は50MHzなので分解能は20nsです。

 16MHzの波形の方はアドレスラッチストローブ(LATCH)の立下りととアドレス線(AD0)の変化までの時間が20ns(50MHz相当)なので結線の接触抵抗が生じるブレッドボードでは厳しいかもしれません。回路的にはV20のクロックをジャンパピンにより8MHz/16MHzの切り換え可能にし、プリント基板化した際に16Mzで動作するか確認する予定です。

クロック8MHz時のメモリリード波形サンプル(結果:OK)


クロック16MHz時のメモリリード波形サンプル(結果:NG)


 今回使用しているV20は uPD70108HCZ-16 なのですがreset中のWR/、RD/信号に関して、マニュアルにはハイレベルに保たれると書かれていますが、今回使用しているものでは下図のロジアナ波形のOE/とWR/に示すようにRESETがハイレベルの時でもローレベル(プルアップするとハイレベルになったのでハイインピーダンス状態と思われる)でした。
 reset解除後、6バイト読込んでからジャンプ(A15:low)していますが、ジャンプ命令は5バイトなので最後の1バイトはプリフェッチによるアクセスですね。

 また、hold 時にASTBがハイインピーダンスにならないことも、今回のようにアドレスとデータを分離前のバスをPICで制御する場合は使いづらいです。ロジックICを使えば簡単に対応できますが、今回は抵抗を使って対処しています。

マニュアル記載内容


reset解除直後の波形サンプル



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

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

レトロマイコン86ボードの構想(その2) [8086]

 86ボード制作ですが、PIC24FJのPMP(パラレルマスタポート)機能について実験してみました。

 今回はシリアル通信をアサインするピンを変更するのでブートローダー側のシリアルも変更が必要でPic24FJ用ブートローダーのOneBitLoaderを入れるところからです。
 久々にOneBitLoaderの最初の立ち上げ画面を見ました。
 次にローダーを使ってpicleコンパイラを書込み、その後はpicleのセルフコンパイル環境でソースを変更し、コンパイルの繰り返し作業なのでローダーすらほとんど使いません。

OneBirLoaderの最初の立ち上げ画面


 V20(8088相当品)を使用することを想定しているので8bitのデータバスに下位アドレスがマルチプレクスする半多重化アドレッシングモードを使用します。
 データ線とアドレス線がマルチプレクスされることでPIC24側のI/Oに少し余裕ができます。
 PMP機能では下図のようにタイミングをパラメータにより色々設定可能なので数通りのパラメータパターンについてロジアナで確認してみました。

PMP半多重化アドレッシングタイミング


 タイミングの調整要素としては上図に書かれているように WAITB,WAITM,WAITE(それぞれBegin、Middle、Endの略だと思う)があり、全てゼロの場合の最速タイミングが下図です。PIC24のクロックは内蔵クロックを使用して32MHzにしています。
 モニタした信号はメモリアクセスのための下記の信号です。
  • MCS/ チップセレクト
  • OE/ リードストローブ
  • WR/ ライトストローブ
  • LATCH 下位アドレスラッチ用のHC573へのG信号
  • AD0 データ線のLSBビットの信号

PMPライトタイミング(wait無し)


 今回もアクセスタイムが70nsのメモリを使用する予定なので WR/ はもっと広げないと駄目ですね。LATCHもマージンを大きくし、ノイズの発生も少なくするためにもっと広げたいと思います。
 下の図が3通りのパラメータで設定した場合のロジアナ波形です。WR/幅が140nsでlatch幅が80nsでlatch後20ns程度アドレスを保持しているWAITB:1,WAITM:2,WAITE:1 を採用することにします。
 その時、PIC の PMCON と PMMODE のレジスタの設定値はそれぞれ 0x0ba0、0x0a49 になります。
★2019/07/15 修正
 採用パターンのWAITEを0から1に修正(latch後のアドレス保持時間の確保のため))

PMPライトタイミング(WAITB:1, WAITM:1, WAITE:1)


PMPライトタイミング(WAITB:1, WAITM:2, WAITE:1)


PMPライトタイミング(WAITB:1, WAITM:2, WAITE:0)


 参考として WAITB:1,WAITM:2,WAITE:1 時のメモリリードタイミングが下図です。

PMPリードタイミング(WAITB:1, WAITM:2, WAITE:1)


 今回の確認に使用したpicleソースと実行結果を貼っておきます。

PMP機能確認用picleソース
:l 1:# V20 memory test 2019/07/13 2:# by skyriver 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var Pcon; 8: 9:proc initP() { 10: PMCON=$0600; #PMMODE[1],PMADDR[2] 11: PMMODE=$0602; 12: PMADDR=$0604; 13: PMDAT=$0608; 14: PMAEN=$060c; 15: PMSTAT=$060e; 16: 17: Pcon=$0ba0; # 0000 1011 1010 0000 18: PMCON[0]=Pcon; 19: PMMODE[0]=$0a49; #0000 1010 0100 1001 20: PMAEN[0]=$4701; # PMAEN 0100 0111 0000 0001 21:} 22: 23: 24:proc PmOn() { 25: BusReq(); 26: while ((LATC[-1]&$100)=0) {} # wait HOLDAC 27: PMCON[0] = Pcon|$8000; 28:} 29: 30: 31:proc PmOff() { 32: PMCON[0] = Pcon; # PMP off 33:} 34: 35: 36:proc MemDsp( adr ) { 37: var i,j; 38: PmpSetAdr( adr ); 39: i = MemRd(); 40:# for ( i= 0; i < 16; i=i+1 ) { 41: for ( i= 0; i < 1; i=i+1 ) { 42: PrnStr_( "\n" ); 43: PrnHex_( adr ); 44: PrnStr_( " :" ); 45: for ( j=0; j< 8; j=j+1 ) { 46: PrnStr_( " " ); 47: PrnHexB_( MemRd() ); 48: } 49: adr = adr + 16; 50: } 51:} 52: 53:proc main() { 54: var adr; 55: init(); 56:# initPmp(); 57: initP(); 58:# initSpi(); 59:# initSd(); 60: 61: LATA[0]=LATA[0]|1; # on reset:a0 62: 63:# PmpOn(); 64: PmOn(); 65: PmpSetAdr(0); 66: MemWr($01); 67: MemWr($02); 68: MemWr($04); 69: MemWr($08); 70: MemWr($10); 71: MemWr($20); 72: MemWr($40); 73: MemWr($80); 74: 75: MemDsp(0); 76: 77:# BusRelease(); 78: LATA[0]=LATA[0]&$fffe; # off reset:a0 79:} :run 0000 : 01 02 04 08 10 20 40 80 :



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

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