SSブログ
English Version

レトロマイコン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) 
共通テーマ:趣味・カルチャー