R6504 CPUのシングルボードマイコン

6502

R6504という、6502系CPUでDIP28ピンというイカすCPUをeBayでゲットしたので、マイコンボードを作ってみました。全メモリー空間8kBで メモリーマップドでI/Oデバイスもそこに含めなきゃいけないという縛り付きです。

プリント基板化しまして、実はちゃんと動いていたのですが、テストプログラムをミスっていたりして思い込みでテストを続けてハマったという記録ですw

R6504CPUについて

R6504 CPUですが、ネットの海を散策すると出てくるロックウェルR65xx系CPUのデータシートによると以下のようにDIP 28ピンというこじんまりしたパッケージのCPUです。

ロックウェルデータシートから引用

私の知ってる8bit PCUというとZ80 CPUとかMC6800 MPUとかDIPパッケージ 40ピンの大型の石というイメージでしたが、R6504は28ピンという こじんまりしたパッケージです。

中身はApple ][とかファミコンで使われた6502系のCPUです。(ファミコンは正確には6502そのものではないみたいですけど..) アクセスできるメモリー容量が8kBに制限されたというだけで中身は一緒。DIP28ということで組み込み用途などを想定しているのかな??と思ったりします。

アドレスシングできる範囲が8kBですので、アドレスバスもA0~A12です。あと制御信号も最低限になって、クロックIN/OUT、R/W#、RES#、IRQ#だけです。割り込み信号があるのが気に入りました。
R65xxのほかの品種のDIP28ピンCPUでは、別の信号線を生かしてあったりして、なかなか楽しいやつです。

R6504シングルボードマイコン回路全景

以前65C02 CPUでシングルボードマイコンを作りましたので、その回路をベースにしたのと MicroKIMの回路を参考にアドレスデコーダに74LS154を使ったりしまして以下のような回路にしました。

I/Oデバイスは65系のR6532(RIOT)、W65C51(ACIA)を使います。R6532(RIOT)はRAM 128バイト(!)とI/Oとタイマーが内蔵されているイカすやつです。W65C51(ACIA)シリアルICは、以前ちょっとハマりましたが一応動かすことはできたので、せっかくなので65xx系の石で揃えたいとチョイスしました。

アドレスデコーダはオープンコレクタの74LS145にして、8kBを8等分した領域を結線してプルアップすることでデコード信号を出します。この方法はMicroKIMの回路図で知ったのですが74LS138とかLS139を使うより簡素化できて素敵だなと思ったので。

メモリーは8kBの品種で十分だったのですが、手元にあったのか27C256とか32kBのものだったのでそちらを採用。

メモリーデバイスなどで使うRD#/WR#信号も74LS00でいつものようにφ2信号と合わせます。アドレスデコードにもLS00を使ったので、全部使い切った!という達成感がありました。

プリント基板に組み付けたあとテストしたこと

ACIAが返事しない

まずハマったのはW65C51(ACIA)が無応答というところでした。以前も6502マイコンで動かしたUniversalMonitorのメモリー配置等を設定しなおしてリビルドしたROMを焼いて基板にさして電源ONしましたがダメ。

ちなみに、UniversalMonitorをビルドするためのconfig.incの設定は以下です。

;;; -*- asm -*-
;;;
;;; Universal Monitor 6502 config file (K6504-SBC)
;;;

;;;
;;; Memory
;;;

ROM_B:	EQU	$1600
ENTRY:	EQU	$1F80		; Entry point
	
WORK_B:	EQU	$0000		; Must fit in ZERO page
STACK:	EQU	$01FF

BUFLEN:	EQU	16		; Buffer length ( 16 or above )

;;;
;;;  Options
;;;

USE_IDENT = 1			; CPU Identification
USE_REGCMD = 1			; Register related commands
	
;;;
;;; MOS Technology MCS6551
;;;

USE_DEV_6551 = 1
	IF USE_DEV_6551
	;;
ACIADR:	EQU	$1200		; Data Register
ACIASR:	EQU	$1201		; Status Register
ACIACM:	EQU	$1202		; Command Register
ACIACR:	EQU	$1203		; Control Register
ACCR_V:	EQU	$1E		; Control: 8bit, 9600bps
ACCM_V:	EQU	$0B		; Command: No-parity
	ENDIF

入出力ルーチンは、以前ハマったときのロジックのままとしました。

いつもならオープニングメッセージが出るところですが、無応答!

画像

それならと思って以下のエコーバックプログラムを試してみますが、うんともすんともいいません。ROMに焼いて電源ONでスタートできるように$1FFAあたりから NMIベクタやリセットベクタなどもちゃんと焼いたのですが….

	CPU	6502

TARGET:	EQU	"6502"

RIOT_DATA_A: EQU	$1080		
RIOT_DDR_A:	EQU	$1081		
RIOT_DATA_B: EQU	$1082		
RIOT_DDR_B:	EQU	$1083	
ACIADR:	EQU	$1200		; Data Register
ACIASR:	EQU	$1201		; Status Register
ACIACM:	EQU	$1202		; Command Register
ACIACR:	EQU	$1203		; Control Register
ACCR_V:	EQU	$0E		; Control: 8bit, 9600bps
ACCM_V:	EQU	$0B		; Command: No-parity

	ORG	$1600

CSTART:
	JSR WAIT_SUB
;	
	LDA	#$FF
	STA	RIOT_DDR_A
	STA	RIOT_DDR_B
;
	LDA #$AA
	STA	RIOT_DATA_A
	LDA #$55
	STA	RIOT_DATA_B

	JSR WAIT_SUB

;
;	
	LDA #$55
	STA	RIOT_DATA_A
	LDA #$AA
	STA	RIOT_DATA_B
;
	LDA	#ACCR_V
	STA	ACIACR
	LDA	#ACCM_V
	STA	ACIACM

	JSR WAIT_SUB

;
LOOP:
	LDA	ACIASR
	AND	#$08
	BEQ	LOOP
	LDA	ACIADR
;
	STA	ACIADR
;
DELAY_LOOP   LDY   #4    ;Get delay value (clock rate in MHz 2 clock cycles)
;
MINIDLY   LDX   #$68      ;Seed X reg
DELAY_1   DEX         ;Decrement low index
  BNE   DELAY_1   ;Loop back until done
;
  DEY         ;Decrease by one
  BNE   MINIDLY   ;Loop until done

	JMP	LOOP

	;;
	;; Vector area
	;; 

	ORG	$1FFA

	FDB	$0000		; NMI
	FDB	CSTART		; RESET
	FDB	CSTART		; IRQ/BRK

	END

RIOT(RAM and IO TIMER)でLEDチカチカはOK

とりあえず、アセンブラのどこまで動いているか分からなかったので、別のI/OデバイスのR6532(RIOT)でLEDチカチカをさせてみることにしました。

	CPU	6502

TARGET:	EQU	"6502"

RIOT_DATA_A: EQU	$1080		
RIOT_DDR_A:	EQU	$1081		
RIOT_DATA_B: EQU	$1082		
RIOT_DDR_B:	EQU	$1083	
ACIADR:	EQU	$1200		; Data Register
ACIASR:	EQU	$1201		; Status Register
ACIACM:	EQU	$1202		; Command Register
ACIACR:	EQU	$1203		; Control Register
ACCR_V:	EQU	$0E		; Control: 8bit, 9600bps
ACCM_V:	EQU	$0B		; Command: No-parity

	ORG	$1600

CSTART:
	JSR WAIT_SUB
;	
	LDA	#$FF
	STA	RIOT_DDR_A
	STA	RIOT_DDR_B
;
	LDA #$AA
	STA	RIOT_DATA_A
	LDA #$55
	STA	RIOT_DATA_B

	JSR WAIT_SUB

;
;	
	LDA #$55
	STA	RIOT_DATA_A
	LDA #$AA
	STA	RIOT_DATA_B
;
	LDA	#ACCR_V
	STA	ACIACR
	LDA	#ACCM_V
	STA	ACIACM

	JSR WAIT_SUB

;
LOOP:
	LDA #$80
	STA	RIOT_DATA_A
	LDA #$01
	STA	RIOT_DATA_B
;
	JSR WAIT_SUB

	LDA	ACIASR
	AND	#$08
	BEQ	LOOP
	LDA	ACIADR
;
	PHA
	LDA #$40
	STA	RIOT_DATA_A
	LDA #$04
	STA	RIOT_DATA_B
	PLA
;

	JSR WAIT_SUB
;
	STA	ACIADR
;
	PHA
	LDA #$20
	STA	RIOT_DATA_A
	LDA #$02
	STA	RIOT_DATA_B
	PLA
;


DELAY_LOOP   LDY   #4    ;Get delay value (clock rate in MHz 2 clock cycles)
;
MINIDLY   LDX   #$68      ;Seed X reg
DELAY_1   DEX         ;Decrement low index
  BNE   DELAY_1   ;Loop back until done
;
  DEY         ;Decrease by one
  BNE   MINIDLY   ;Loop until done

	LDA #$10
	STA	RIOT_DATA_A
	LDA #$01
	STA	RIOT_DATA_B

	JMP	LOOP

WAIT_SUB:
	LDY #$FF
LOOP3:
	LDX #$FF
LOOP4:
	NOP
	NOP
	NOP
	DEX
	BNE LOOP4
	DEY
	BNE LOOP3
	RTS

	;;
	;; Vector area
	;; 

	ORG	$1FFA

	FDB	$0000		; NMI
	FDB	CSTART		; RESET
	FDB	CSTART		; IRQ/BRK

	END

上記のプログラムをROMに焼いて、無事LEDチカチカはできました! ちゃんと動くプログラムがROMに焼けるとちょっとモチベーションが上がります。

Universal MonitorをROMに焼いた時のリセットベクタとかのアドレスも自信がなかったのですが、LEDチカチカがROMで起動してちゃんと動くので問題なさそうです。

画像

最初 アセンブラのニーモニックを間違ってしまい リテラルのつもりが”#”をつけ忘れて $00-$FFのゼロページRAMアドレスからデータをロードするプログラムになってたり、間違いがありまして悩みました。MC6800とか65xx系CPUは$0000番地~$00FF番地までのゼロページにアクセスする際は 1バイトのアドレス指定でOKなのです。しばらくZ80とかをさわっていてそちらの頭になっていたので、「1バイトの指定はリテラル(即値)」という思い込みがありました。

おかげで、リテラル(即値)で指定した$55とか$AAのような一つ置きにLEDが点灯するパターンを送ってるのに、ランダムなパターンでLEDが点滅したりして、しばし悩んだのでした。実はRAMのアドレス $55とか$AAの値がLEDに表示されていたというオチでした。RAMもちゃんと動いていたのですな。

ACIAが返事しない その2

R6532(RIOT)経由でLEDチカチカができるようになりましたので、ACIAのプログラムが動かない原因をさぐるため ロジアナで波形を観測したり、printfデバグならぬ LEDチカチカデバグをして プログラムがどこまで動いたか探ってみました。

画像
画像

R6504のデータシートを見ていたら、プルアップ抵抗値が2.2kとか1kとか書いてあったりしたので、10kの集合抵抗を外して 抵抗を並べてみました。特に変化なしでした。

画像

シリアル用のクロックを外部発振して入力ではなくて、W65C51の内部発振器にクリスタルを直接つなげているのが悪いのか?と思って発振周波数を XTL-OUT端子 7番ピンでテスターの周波数カウンター機能で計測してみましたが、問題なし。

もしかして、R6504 CPUはデータバスが弱いのでHCT245とかで補強してやる必要があるのか?と思って子亀基板を作ってみましたがダメ。

この基板ですが、両面ユニバーサル基板を使って隣のランドとハンダを盛って短絡することで、ほぼ配線を済ませたのです。けっこう こういう子基板を作るのは楽しいです。

W65C51シリアルICの内部発信器で水晶を発振させるのがイカンのかと思い、水晶発振器を外部接続してみたり、W65C02で実績のあるMC6850で実験じゃと思って子基板を作ってみたりしましたが、状況は変化なしでした。こちらの子基板は単芯電線で配線してみました。これもまた楽しい。

画像

結局、初期化の前に「待つ」

Twitterでも「CPUが立ち上がったタイミングで、まだACIAの初期化が終わってないかも?」という助言をいただいて、ACIA初期化の前にちょっと長めにWAITルーチンをいれてみたところ無事Universal Monitorが稼働しました。なんとー!! そこかー。

プログラムとしては、65系のXレジスタとYレジスタというインデックスレジスタがあるんですが、そこに255を入れて 2重ループにしました。けっこう待ってますね。

無事 モニターも稼働しまして、R6532が持ってる128バイト(!!)のRAMとかに書き込みテストもできてちゃんと動作確認がとれました。

まとめ

今回は もともとちゃんと動いていたR6504マイコンボードのハードが問題かも?とか思っていろいろと子基板作ったり、プルアップ抵抗値を変えてみたり、アドレスデコードが問題か?と思って配線し直してみたりしましたが…

結局は のテストプログラムがイマイチだったというオチでした。でもそのおかげて、いろいろと測定したりトライアンドエラーしてみたりして楽しかったのでヨシであります。

コメント