6502CPUでマイコンボード(2)

6502

前回 6502CPUを秋月電子Bタイプユニバーサル基板へ搭載して動かすことができました。また、参考にしたGrantさんの回路とアドレスを合わせてあったので Grant’s BASIC 6502も動作確認できました。今後6502CPUの機械語プログラムを行うためにも、ぜひ機械語モニターを動かしてみたいところであります。

Universal Monitor for 6502を動かす

ソースディレクトリ構成

6502CPUで動く機械語モニターですが、Electrelicさん作のUniversal Monitorがソースつきで公開されていて機能も充実していますので、MC6850シリアルに対応してみたいと思いました。

ダウンロード | Electrelic
ソースコード Universal Monitor のソースコードは以下からダウンロードできます。 HTTP 最新版は unimon-latest.tar.gz で取得できます。 過去のものが必要な場合は にあります。毎晩、subversion リポジトリに変化があった場合に tarball を生成しています。ブランチ...

上記のダウンロードページで「最新版」のソースをいただいてきて展開してみると、6502 というどんぴしゃのディレクトリがありまして、以下のような構成となっています。

.
├── 6502
    ├── config    (構成定義ファイル)
    └── dev          (各種デバイス用ドライバ)

configディレクトリにある config.inc には各種デバイス用ドライバで使うデバイスの入出力アドレスシンボル、初期化定数が定義されています。

devディレクトリには、デバイスに合わせた入出力ルーチンが定義されたモジュールが入っています。

これらを修正してmakeしてあげれば動くはず。ちなみにアセンブラはわたしが以前から使っている The Macro Assembler AS を使われています。

構成定義へMC6850用定義を追加

以下のようなかたちで、MC6850用定義を追加しました。条件アセンブリの構文としては 1にしたところが有効で 0にしたところは無効になるようです。

USE_DEV_6551 = 0
       :
       :
USE_DEV_6850 = 1
IF USE_DEV_6850
	;;
ACIACS:	EQU	$A000		; CTL Register
ACIADT:	EQU	$A001		; DATA Register
ACIA_V1:	EQU	$03		; RESET
ACIA_V2:	EQU	$15		; Control: 8bit, 9600bps
ENDIF
       :
       :
USE_DEV_EMILY = 0

MC6850シリアルLSI(ACIA)の$A000(コントロールレジスター)と$A001(データレジスター)の番地に名前をつけます。今回のシステムはメモリーマップドI/Oなのでメモリーの一部の番地にI/Oチップがつながっているのです。
また、初期化用の値として2つのEQU定義を追加します。

MC6850(ACIA)用ドライバモジュール

次にconfig.incで定義したシンボルを使って、MC6850(ACIA)用ドライバモジュールを作ります。以下のように、INIT(初期化)、CONIN(1文字入力)、CONST(ステータスチェック)、CONOUT(1文字出力)の4ルーチンを定義するかたちになります。

;;;
;;;	MCS6850 Console Driver
;;;

INIT:
	LDA	#ACIA_V1
	STA	ACIACS
	LDA	#ACIA_V2
	STA	ACIACS
	RTS
	
CONIN:
	LDA	ACIACS
	AND	#$01
	BEQ	CONIN
	LDA	ACIADT
	RTS
	
CONST:
	LDA	ACIACS
	AND	#$01
	RTS
	
CONOUT:
	PHA
CO0:
	LDA	ACIACS
	AND	#$02
	BEQ	CO0
	PLA
	STA	ACIADT
	RTS

MC6850のコントロールについては、SBC6800データパックのACIA版MIKBUGのソースを参考にさせていただきました。

  • 初期化はconfig.incで定義した$03(マスターリセット)と$15(8bit/ノンパリ/ストップビット1+1/16分周)を、MC6850(ACIA)のコントロールレジスターへ出力します。
  • 1文字入力はACIAのコントロールレジスターをチェックして$01(Receive Data Register Full)が立つのを待ってデータレジスターから読み出します。
  • ステータスチェックはACIAのステータスレジスター(コントロールレジスター)の$01(Receive Data Register Full)が立っているかどうかをアキュームレーターへ入れて返します。
  • 1文字出力は、アキュームレーターに渡ってきた文字コードをACIAのデータレジスターへ出力します。送信前にステータスレジスターに$02(Transmit Data Register Empty)が立っていることを確認します。

makefileへの追加 & make実行

MC6850(ACIA)用デバイスルーチンを追加しましたので、makefileの以下の行にdev_6850.asmを追記します。

devs :=	dev/dev_6551.asm dev/dev_emily.asm dev/dev_6850.asm

さて、あとはMacやLinuxの場合はGNU makeで make コマンドでビルドできることになりますが、ここでいつもりハマりにはいりまして….以下のようなエラーで悩まされました。

6502CPUの条件ブランチ命令は8bitの範囲(-128〜+127バイトの範囲)でしか飛べません。Z80の相対ジャンプJR命令みたいな感じ。でも、どうみても近場のアドレスなのにToo BIGだというエラーなわけで悩みました。

実は、コンパイラのビルドに起因するバグだったようで、そのときの私のMacに入っていたASLが2019-09-25 [1.42 Bld 150]、最新は2020-04-05 [1.42 Bld 162]です。
Windows版としてバイナリ配布されているasw(v1.42 Bld 162)を使ってアセンブリしたところ、何事もなくビルドが成功しました。….orz なんてことだ…
前方にあるラベルへのブランチが、ことごとくエラーとなっていたみたいです。

ROM焼きと稼働確認

若干のハマりはありましたが、ビルドに成功してIntelHex形式のオブジェクトデータができましたので、いつものTL866CSを使って256kBフラッシュROM(28C256型)に書き込みしまして稼働確認をしました。

ちなみに28C256型フラッシュROMへ書き込む際は、UniversalMonitorのIntelHexが$Fx00の場合、TL866CSの書き込みソフトでロードする際に $7×00へ読み込むと良いです。
以下がUniversal Monitor for 6502CPUのROMを搭載したマイコンの写真と、稼働させたときのTeraTERMのスクリーンショットです。

次回はLチカ

わたしの6502マイコン用としてビルドしたUniversal MonitorのソースとIntelHexファイルはgithubに添付してあります。ご参考まで。

K65-SBC/src at master · kuninet/K65-SBC
6502CPU Single Board Computer Project. Contribute to kuninet/K65-SBC development by creating an account on GitHub.

機械語モニターが動いたので、次は6502CPUの機械語プログラムを作ってtomi9さん作のSBC-IOを使ってLEDチカチカ(Lチカ)させてみたいと思います。
その顛末はまた次回以降で…

コメント