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マイコンボードのハードが問題かも?とか思っていろいろと子基板作ったり、プルアップ抵抗値を変えてみたり、アドレスデコードが問題か?と思って配線し直してみたりしましたが…
結局は のテストプログラムがイマイチだったというオチでした。でもそのおかげて、いろいろと測定したりトライアンドエラーしてみたりして楽しかったのでヨシであります。
コメント