2014.12.30

前へ
次へ
ホームページトップへ戻る

MYCPU80でCP/Mを!
超巨大基板の8080互換HCMOS・CPUでCP/Mを走らせてしまおうという、なんとも狂気なプロジェクトです!


[第90回]


●エラーの原因は/LDプログラムにありました

前回書きましたように、/LDを実行すると受信エラーになるのですが、CPMにエントリした後にMBASIC.COMのロードやSTARTREK.BASのロードでは受信エラーが発生しないことから、/LDに問題があるらしいと目星はつけたのですけれど、一体そのどこに原因があるのかということを明らかにしなければ、このまま19200bpsを使うというわけにはいきません。
実は受信エラーはロードのためのアドレス情報を読んだあと、続くデータの最初の1バイトを読んだ後で発生していました。
受信エラーが発生するとLEDが点灯することでわかるのですが、そのときMYCPU80のHLレジスタの表示がロード先メモリアドレス+1を示していることからそれがわかりました。
繰り返し試してみて必ずそうなることが特徴的でした。
おそらくはオーバーランエラーだろうと目星をつけて、/LDプログラムの受信サイクル時間を調べてみることにしました。

下はMYCPU80に移植したZB3BASICの/LDプログラムから関係する部分を抜き出して、そこに命令の実行クロックを追記したものです。

              ;;; LD
1C95 13       LD:INX D
1C96 CD5110   	CALL ADRD
1C99 CDAE10   LD2:CALL SIN   18+168=186
1C9C CDF61C   	CALL MEMWR2;********14.12.26   18+54=72
1C9F 23       	INX H   12 or 8
1CA0 CD2710   	CALL HDCMP  18+56=74
1CA3 CA991C   	JZ LD2  8
1CA6 DA991C   	JC LD2  12 ________186+72+12+74+8+12=364clk*0.5us=182us
1CA9 C3A318   	JMP ENTRY
              ;
              ;
1CF6 F5       MEMWR2:PUSH PSW   8
1CF7 7C       	MOV A,H     6
1CF8 B7       	ORA A       10
1CF9 F23FE2   	JP RAMWR    8
1CFC F1       	POP PSW     8
1CFD 77       	MOV M,A     6
1CFE C9       	RET         8    8+6+10+8+8+6+8=54
              ;
10AE C34E11   JMP SIN    12+8+6+6+8+100+10+8+8=168
              ;
114E C5       SIN:PUSH B  8
114F 3EFF     	MVI A,FF  6
1151 47       	MOV B,A   6
1152 D398     	OUT 98    8
1154 CDA002   	CALL SINSB   18+82=100
1157 B7       	ORA A     10
1158 C1       	POP B     8
1159 C9       	RET       8
              ;;;
              ;
02A0 DB98     SIN:IN 98    8
02A2 0F       	RRC        10
02A3 DAA002   	JC SIN     8
02A6 3EFE     	MVI A,FE;BUSY   6
02A8 D398     	OUT 98     8
02AA DB94     	IN 94      8
02AC 4F       	MOV C,A    6
02AD 3EFF     	MVI A,FF;READY  6
02AF D398     	OUT 98     8
02B1 79       	MOV A,C    6
02B2 C9       	RET        8      8+10+8+6+8+8+6+6+8+6+8=82
              ;
1027 C39511   HDCMP:JMP HDCP  12+6+10+4+6+10+8=56
;
              ;;;HL-DE COMP
1195 7C       HDCP:MOV A,H  6
1196 BA       CMP D   10
1197 C0       RNZ     4
1198 7D       MOV A,L 6
1199 BB       CMP E   10
119A C9       RET     8
              ;;;

1バイトのデータを受信してメモリに格納するサイクルはアドレス1C99〜1CA8のループで行なわれています。
1回の実行クロック数は364クロックになりました。
MYCPU80のCPUクロックは2MHzですからそこに記してありますように、1回の実行時間は182μsになります。
思っていたよりも意外に短い時間です。
ちなみに9600bpsの場合1バイトの受信にかかる時間は1/960×1000≒1.042msです。
19200bpsの場合にはその半分の0.521msです。

おや。
それならば、このプログラムではオーバーランは起きないはずですね。
38400bpsでもいけそうです。
むむ。
ということは…。
問題はアドレス1C96のCALL ADRDにありそうです。

/LDの仕組みはこうです。
Windows側でキー入力した
/LD ファイルネーム,ssss,eeee0d0a
を解読して、最初にssss,eeee0d0aを文字コードで送信したあとで、データ本体を送出します。
ssssはロード開始アドレス、eeeeは終了アドレスを示す16進数各4桁の文字(ASCII)です。
ADRDは最初に送られてきた11バイトの文字データを解読してロード開始アドレスと全体のバイト数を算出するルーチンです。
どうやらここで時間がかかっているようです。
おお。
今気が付きました。
そういうことならば、先にWindows側でアドレスを文字からバイナリに変換して送信すれば、ADRDで計算する手間が省けますね。
それは後の対策としまして、どうせ乗りかかった船ですから、ADRDの実行時間も計算してみました。

1C96 CD5110   	CALL ADRD
;
1051 C33B12   ADRD:JMP ADRD1  12+2046=2058clk*0.5us=1.029ms
;
              ;;;ADDRESS READ
123B CD4510   ADRD1:CALL ASHX4   18+930=948
123E DA8B16   JC WHAT    4
1241 13       INX D      12 or 8
1242 E5       PUSH H     8
1243 CD4510   CALL ASHX4 18+930=948
1246 DA8B16   JC WHAT    4
1249 42       MOV B,D    6
124A 4B       MOV C,E    6
124B D1       POP D      8
124C CD2710   CALL HDCMP  18+56=74
124F DA7F16   JC HOWDP   4
1252 EB       XCHG    16
1253 C9       RET   8   948+4+12+8+948+4+6+6+8+74+4+16+8=2046
              ;;;
1045 C30B12   ASHX4:JMP AHX4   12+918=930
;
              ;;;ASCII TO HEX
11E2 D630     AHX1:SUI 30   10   
11E4 D8       RC      4
11E5 FE0A     CPI 0A  10
11E7 3F       CMC     6
11E8 D0       RNC     4
11E9 FE31     	CPI 31    10
11EB DAF011   	JC AHX12  12 or 8
11EE D620     	SUI 20    10
11F0 FE11     AHX12:CPI 11   10
11F2 D8       RC       4
11F3 FE17     CPI 17   10
11F5 3F       CMC      6
11F6 D8       RC       4
11F7 D607     SUI 07   10
11F9 C9       RET   8    10+4+10+6+4+10+8+10+10+4+10+6+4+10+8=114
;
11FA 7C       AHX2:MOV A,H   6
11FB CDE211   CALL AHX1    18+114=132
11FE D8       RC     4
11FF 07       RLC    10
1200 07       RLC    10
1201 07       RLC    10
1202 07       RLC    10
1203 67       MOV H,A     6
1204 7D       MOV A,L     6 
1205 CDE211   CALL AHX1   18+114=132
1208 D8       RC        4
1209 B4       ORA H     10
120A C9       RET   8   6+132+4+10+10+10+10+6+6+132+4+10+8=348
;
120B CD1712   AHX4:CALL AHXS  18+424=442
120E D8       RC        4
120F 47       MOV B,A   6
1210 CD1712   ASH22:CALL AHXS  18+424=442
1213 D8       RC        4
1214 6F       MOV L,A   6
1215 60       MOV H,B   6
1216 C9       RET       8   442+4+6+442+4+6+6+8=918  
;
1217 EB       AHXS:XCHG   16
1218 56       MOV D,M     6
1219 23       INX H       12 or 8
121A 5E       MOV E,M     6
121B 23       INX H       12 or 8
121C EB       XCHG        16
121D C3FA11   JMP AHX2  12+348=360,,16+6+12+6+8+16+360=424
              ;;;

結果は思った通りでした。
アドレスデータを受信してからADRDルーチンが終了するまでに1.029msかかっていました。
これでは19200bpsでは完全にアウトです。
9200bpsでもぎりぎりですが、PICの場合1バイトの受信バッファを内蔵していますから2バイト目を受信完了するまでに前の1バイトを引き取ればオーバーランにはなりません。
19200bpsで2バイト目の受信でエラーが発生したのはそのためです。

どうやらここに原因があるらしいことはわかりましたが、念のためにWindows側のプログラムに細工をして、このことを確かめてみました。

下はWindows側のプログラムの/LDの一部分です。


if(m==4){	
			strout("JP 1848 ",0);
		    	xb=x+rfsize-1;
			adout(x);
			strcat(outbf,",\0");
			adout(xb);
			dhlout(0x0d);
			dhlout(0x0a);
				//if(!hidwrite())break;
			if(!write()){close();break;}
			}
		else{
			strout("JP 0033\n",0);
			if(!write()){close();break;}
			}
		prints("sleep,,,");//test
		Sleep(1000);
		prints("sleep end");//test
		i=0;
		while(1){

アドレスデータの送出後にSleep(1000)を挿入してみました。
本来ならばSleep(10)でも十分なはずなのですがそれでは駄目でした。
Sleep(10)は10msウエイトですがその時間はシステムに依存するようであまり正確ではないようです。
なので思い切りよく1000msのウエイトをかけてみました。

その結果は下のログにあります通り、受信エラーにならずに正常に受信できました。
このログだけからはエラーの有無はよくわかりませんが、MYCPU80側ではエラーLEDが点灯することなく、正しく受信できました。

logfile mycpu80log\12291722.txt open
mzbdos3L 2014.12.29 by Chunichidenko

MYCPU80に接続しました(19200bps)
0001 001E - z
1000 00C3 - 
*** mycpu80 zb3basic ****
>/ld mtkmon3.btk,8ffc
loading MTKMON3.BTK ...sleep,,,sleep end02f8(760)bytes loaded,from 8FFC to 92F3
>/exit
0000 00C3 - 
リモート接続を終了しました
logfile closed at Mon Dec 29 22:39:51 2014

さてそういうことになりますと、次はこの問題の解決策です。
まさかSleepで逃げるってのはないでしょうねえ。
今回の途中のところに書きましたように、Windows側のプログラムで先にアドレス情報をASCIIからバイナリに変換してから送出するというのも有り、だと思います。

そのことにつきましてはまた次回に書くことにいたします。

MYCPU80でCP/Mを![第90回]
2014.12.30upload

前へ
次へ
ホームページトップへ戻る