Z8S180/TMPZ84C015/(Z80+8251+8255)/(Z80+SIO+PIO)に移植した同じ「最初のモニタ」をKL5C80B12Cにも移植したいと思います。
今回、モード設定は、ノーマルモードで動作させるので、MODE0(27pin)/MODE1(26pin)の端子は、Hレベル(Vcc)に設定します。
MMUの設定は、内部RAMは使用せず、M1CSにチップセレクトされるRAMを使用します。このRAMは、0xe0000から配置されます。
では早速、モニタプログラムを確認していきます。
KL5C80B12C特有のレジスタを定義していきます。
ここでは、コントロールレジスタSCR0/1、MMUレジスタBBR1~4/BR1~4、シリアル通信用レジスタUART_D/C、パラレルポートPP2~4D/PPBCを定義しました。
;;KL5C80 System control register
SCR0 .equ 0x3a
SCR1 .equ 0x3b
;;KL5C80 Memory management unit
BBR1 .equ 0x00
BR1 .equ 0x01
BBR2 .equ 0x02
BR2 .equ 0x03
BBR3 .equ 0x04
BR3 .equ 0x05
BBR4 .equ 0x06
BR4 .equ 0x07
;;KL5C80 UART
UART_D .equ 0x38
UART_C .equ 0x39
;;KL5C80 Parallel port B
PP2D .equ 0x30
PP3D .equ 0x31
PP4D .equ 0x32
PPBC .equ 0x33
続いて、コントールレジスタで、RxC/TxC(シリアル用クロック入力)及びHALT端子等を汎用ポートから各専用ポートに切り替えました。
Port0のP20~P27を確認用に出力に設定していますが、ここではコメントしています。SDCARDに接続するポートと同じなので、出力ポートが衝突してしまいます。SDCRADを未接続のとき、P20~P27で出力するときのみ、コメントを外してください。
start: ;cold start
ld a,0b00000001 ;RxC,TxC Port set
out (SCR0),a
ld a,0b00001111 ;NMI,BREQ,BACK,HALT,M1 set Active mode : 1 wait set
out (SCR1),a
; ld a,0b00000011 ;Parallel port B 2x OutPut Mode
; out (PPBC),a
続いて、MMUの設定をします。
内蔵RAMを無効にするために、BBR4には0x3fを設定しています。
RAMは、64Kエリアの論理アドレス0x8000から0xffffまでに物理アドレス0xe0000~0xe0e7fffまでを割り当てます。
この設定をBBR3及びBR3に対して設定します。
まずは、論理アドレス(0x8000)を0x400で割り、0x01引きます。
0x8000/0x400-1=0x1f (0b00011111)
この値が、BBRレジスタの5-0bitの値となります。
次に物理アドレス(0xe0000)を0x400で割り、先ほどのBBRレジスタに0x01を足した値を引きます。
0xe0000/0x400-(0x1f+0x01)=0x360 (10bit= 9-0bit)(0b1101100000)
この値がBRレジスタの7-0bit(計算した結果の9-2bit)、BBRレジスタ7-6bit(計算した結果の1-0bit)の値となります
したがって、BBR、BRの値を2進で表し16進に直すと次のようになります。
BBR=0b00111110 = 0x1f
BR =0b11011000 = 0xd8
ld a,0x3f ;Built-in ram non set 0xfe00-0xffff
out (BBR4),a
ld a,0x1f ;MMU 0xe0000-0xe7ffff setting 0x8000
out (BBR3),a
; out (BBR2),a
; out (BBR1),a
ld a,0xf0 ;mmu 0xffe00 mode0
out (BR4),a
ld a,0xd8 ;mmu 0xe0000 mode0
out (BR3),a
; out (BR2),a
; out (BR1),a
続いて、スタックポインタを0x0000に設定したのち、シリアル通信用レジスタを初期化します。初期化した後は、オープニングメッセージを表示し、プロンプト表示したのちコマンド入力待ちになります。
ld sp,0x0000 ;stack pointer set
call com_init ;serial channel initialize
ld hl,msg_op ;opening message display
call msgout
prompt: ld a,">" ;main routine
call putchar ;prompt display
call getchar
call putchar
シリアル通信の初期化は、8ビット、ノンパリティー、1ストップビットで、RxC/TxC入力クロックを 1/16に設定しています。(38400pbs)
com_init:
ld a,0b01001110 ;8bit NonParity 1StopBit 1/16Portrait
out (UART_C),a
ld a,0b00000101 ;Rx or Tx Enable
out (UART_C),a
ret
シリアル入出力はUART_Cをチェックした後、Aレジスタに入力データ、または、Aレジスタの内容を出力します。
getchar:
in a,(UART_C) ;Rx status in
bit 1,a ;RxRdy ?
jr z,getchar
in a,(UART_D) ;Rx data in
ret
putchar:push af
putchar01:
in a,(UART_C) ;Tx status in
bit 0,a ;TxRdy ?
jr z,putchar01
pop af
out (UART_D),a ;Tx data out
ret
RAM領域をモニタで読み書きしてみました。
とりあえず、0x8000で確認。
書き換えはOKのようです。
Monitor KL5C80 CPU ver0.71 by Pinecone 2020/10/16
>?
? Help
d MemoryDump
m MemoryChange
l HexFileLoad
j jump
i I/oRegister
c Call
>d 8000
addr +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
8000 A8 AA 55 55 55 75 AA AA A2 AA 55 55 27 54 AA AA
>m 8000 A8 00
>m 8000 00 ff
>d 8000
addr +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
8000 FF AA 55 55 55 75 AA AA A2 AA 55 55 27 54 AA AA
>
以下に、ソースプログラムとHEXファイルを提示しています。
次回は、64K化RAMモニタ、およびSDCARDの読み書き、CP/Mへのブートコマンドを組み込んだモニタを作成していきたいと思います。
; KL5C80 monitor ver0.71 by Pinecone 2020/10/16
;
; KL5C80 cpu
; rom 0000h -- 7fffh
; ram fe00h -- ffffh(MMU setting)
; Clock 10MHz (ext.clock 20MHz)
;
; KL5C80 cpu mode setting
; mode: Normal mode (M1CS or M0CS Activity)
; MODE0(27pin):H(Vcc)
; MODE1(26pin):H(Vcc)
; serial communication
; extemal Clock 614.4KHz(4.9152MHz TC74HC4040 1/8 Frequency division)
; Band Rate:38400 8bits 1Stopbits none Parity (81N)
; assembler
; program start 0000H
; main 0100H
;
; assemblers ASxxxx and ASlink V5.10
; file name KL5C80_moni.asm
; $ asz80 -l -s -o KL5C80_moni.asm
; $ aslink -i KL5C80_moni
; $ UV-EPROM writer (TL866(2)PLUS KL5C80_moni.ihx
;
.z80
.area TEST(ABS)
;;KL5C80 System control register
SCR0 .equ 0x3a
SCR1 .equ 0x3b
;;KL5C80 Memory management unit
BBR1 .equ 0x00
BR1 .equ 0x01
BBR2 .equ 0x02
BR2 .equ 0x03
BBR3 .equ 0x04
BR3 .equ 0x05
BBR4 .equ 0x06
BR4 .equ 0x07
;;KL5C80 UART
UART_D .equ 0x38
UART_C .equ 0x39
;;KL5C80 Parallel port B
PP2D .equ 0x30
PP3D .equ 0x31
PP4D .equ 0x32
PPBC .equ 0x33
.org 0x0000
jp start
.org 0x100
start: ;cold start
ld a,0b00000001 ;RxC,TxC Port set
out (SCR0),a
ld a,0b00001111 ;NMI,BREQ,BACK,HALT,M1 set Active mode : 1 wait set
out (SCR1),a
; ld a,0b00000011 ;Parallel port B 2x OutPut Mode
; out (PPBC),a
ld a,0x3f ;Built-in ram non set 0xfe00-0xffff
out (BBR4),a
ld a,0x1f ;MMU 0xe0000-0xe7ffff setting 0x8000
out (BBR3),a
; out (BBR2),a
; out (BBR1),a
ld a,0xf0 ;mmu 0xffe00 mode0
out (BR4),a
ld a,0xd8 ;mmu 0xe0000 mode0
out (BR3),a
; out (BR2),a
; out (BR1),a
ld sp,0x0000 ;stack pointer set
call com_init ;serial channel initialize
ld hl,msg_op ;opening message display
call msgout
prompt: ld a,">" ;main routine
call putchar ;prompt display
call getchar
call putchar
cp "?" ;help ?
call z,help
cp "d" ;memory display?
call z,dump
cp "m" ;memory rewrite ?
call z,memory
cp "l" ;hex file load?
call z,loadhex
cp "j" ;address jump?
call z,jump
cp "i" ;i/o register rewite
call z,ioreg
cp "c"
call z,calling ;address call
cp 0x0d
jr z,prompt
cp 0x00
jr z,prompt
call cr
jr prompt
help: ld hl,help_msg ;help ?
call msgout
ret
cr:
ld a,0x0d
call putchar
ret
jump: ;address jump?
ld a," "
call putchar
call input_hl ;dump address input
cp 0x00
jr nz,crret
ld a," "
call putchar
ld a,"y"
call putchar
ld a,":"
call putchar
call getchar
cp "y"
jr nz,crret
call cr
jp (HL)
crret:
call cr
ret
calling: ;address call?
ld a," "
call putchar
call input_hl ;call address input
cp 0x00
jr nz,crret
ld a," "
call putchar
ld a,"y"
call putchar
ld a,":"
call putchar
call getchar
cp "y"
jr nz,crret
call cr
ld de,callret
push de
jp (HL)
callret:
ret
loadhex:
call loadhexline ;load 1line Hex file
cp 0xff ;hex file read err
jr z,loadhexerr
cp 0x01 ;hex file end?
jr nz,loadhex
ld a,0x0d
call putchar
ld a,"O"
call putchar
ld a,"K"
call putchar
ld a,0x0d
call putchar
ret
loadhexerr:
ld a,0x0d ;hex file read skip
call putchar
ld a,"E"
call putchar
ld a,"R"
call putchar
ld a,"R"
call putchar
ld a,0x0d
call putchar
ret
loadhexline:
ld a,0x0d
call putchar
ld d,0x00 ;checksum count clr
call getchar ;record mark is ":"
cp ":"
jr nz,loadhexlineerr
call input_l ;data size 1byte
ld b,l ;checksum = checksum + data size
ld a,d
add b
ld d,a
call input_hl ;offset address 2byte
push hl
pop ix ;offset address HLreg >> IXreg
ld a,d ;checksum = checksum + address Low
add l
add h ;checksum = checksum + address Hi
ld d,a
call input_l ;record type
ld a,l
cp 0x00 ;data record
jr nz,checkrecord
;; *** data record job ****
data_hex:
call input_l ;read hex 1byte in Lreg(hex)
ld (ix),l ;offset address < hex data
inc ix ;offset address +1
ld a,l
add d ;cheksum Dreg = Dreg + Lreg
ld d,a
djnz data_hex ;Breg(data size) == 0?
call input_l ;chechsum OK?
ld a,d
add l
cp 0x00
jr nz,loadhexlineerr
call getchar
cp 0x0a ;load 1line hex LF?
jr nz,loadhexlineerr
ld a,0x00
ret
checkrecord: ;end record ?
cp 0x01
jr nz,loadhexlineerr
call input_l
ld a,l
cp 0xff
jr nz,loadhexlineerr
ld a,0x01
ret
loadhexlineerr:
ld a,0xff ;read record err (no support)
ret
dump: ;memory dump
ld a," "
call putchar
call input_hl ;dump address input
cp 0x00
jr z,dump1
push iy ;memory dump address set
pop hl
dump1:
call dump_hl ;memory dump
push hl ;memory address IY set
pop iy
ret
memory: ;memory change
ld a," " ;space
call putchar
call input_hl ;change memory address
cp 0x00
jr z,memory1 ;no address hex code
ld a,0x0d
call putchar
ret
memory1:
ld a," " ;current memory display
call putchar
ld a,(HL)
call hex_a_disp
ld a," "
call putchar
push hl
call input_l ;new memory conntents input
cp 0x00
jr z,memory2
pop hl
xor a
ret
memory2:
ld c,l ;memory contents update
pop hl
ld (hl),c
ld a,0x0d
call putchar
ret
ioreg: ;ioreg change
ld a," " ;space
call putchar
call input_l ;change i/o register
cp 0x00
jr z,ioreg1 ;no address hex code
ld a,0x0d
call putchar
ret
ioreg1:
ld a," " ;current i/o address display
call putchar
ld b,0x00
ld c,l
in a,(c)
call hex_a_disp
ld a," "
call putchar
call input_l ;new i/o conntents address input
cp 0x00
jr z,ioreg2
xor a
ret
ioreg2:
ld a,l ;new i/o address update
out (c),a
ld a,0x0d
call putchar
ret
input_l: ;input Lreg hex (1byte)
push bc
ld b,0x02
jr input_loop
input_hl: ;input HLreg hex (2byte)
push bc
ld b,0x04
input_loop:
ld hl,0x0000 ;HL reg cler
jr input_hl2
shift_hl:
add hl,hl ;HL reg shift left 4bit
add hl,hl
add hl,hl
add hl,hl
input_hl2:
call getchar ;input ascii hex 1char
call putchar
call ascii_hex ;ascii hex 1char >> Areg
cp 0xff
jr z,input_hl_err
and 0x0f ;Areg low order 4bit >> Lreg
or l
ld l,a
djnz shift_hl
input_hl_end:
pop bc
xor a ;OK >> Areg 0x00
ret
input_hl_err:
ld a,0xff ;NG >> Areg 0xff
pop bc
ret
dump_hl: ;memory dump 1line(+0 -- +f)
ld a,0x0d
call putchar
push hl
ld hl,dump_msg ;dump address msg output
call msgout
pop hl
ld a,h ;dump address HLreg
call hex_a_disp ;dump address output
ld a,l
call hex_a_disp
ld a," "
call putchar
call putchar
ld b,0x10 ;address --> address +0f
hl_disp:
ld a,(HL) ;dump addres data (HL)
inc HL
call hex_a_disp
ld a," "
call putchar
djnz hl_disp
ld a,0x0d
call putchar
ret
hex_a_disp: ;Areg(HEX) >> putchar(areg)
push af
rrca ;7-4bit Right shift
rrca
rrca
rrca
call hex_ascii ;3-0bit Hex >> Hex ascii(0-F)
call putchar ;7-4bit putchar
pop af
call hex_ascii ;3-0bit Hex >> Hex ascii(0-F)
call putchar ;3-0bit putchar
ret
ascii_hex:
sub 0x30
jr c,err_hex
cp 0x0A ;0-9
jr c,hex_1_9
sub 0x11
cp 0x06 ;A-F
jr c,hex_A_F
sub 0x20
cp 0x06 ;a-f
jr nc,err_hex
hex_A_F:
add 0x0a
hex_1_9:
ret
err_hex:ld a,0xff
ret
hex_ascii: ;Areg(HEX) >> Areg(ascii code)
and a,0x0f
cp 0x0a
jr c,ascii0_9
add 0x37
ret
ascii0_9:
add 0x30
ret
msgout:
ld a,(hl) ;(HL)reg is output disp at 0x00
cp 0x00
ret z
call putchar
inc hl
jr msgout
getchar:
in a,(UART_C) ;Rx status in
bit 1,a ;RxRdy ?
jr z,getchar
in a,(UART_D) ;Rx data in
ret
putchar:push af
putchar01:
in a,(UART_C) ;Tx status in
bit 0,a ;TxRdy ?
jr z,putchar01
pop af
out (UART_D),a ;Tx data out
ret
;
com_init:
ld a,0b01001110 ;8bit NonParity 1StopBit 1/16Portrait
out (UART_C),a
ld a,0b00000101 ;Rx or Tx Enable
out (UART_C),a
ret
;
msg_op: .str "Monitor KL5C80 CPU ver0.71 by Pinecone 2020/10/16"
.db 0x0d
.db 0x00
help_msg:
.db 0x0d
.str "? Help"
.db 0x0d
.str "d MemoryDump"
.db 0x0d
.str "m MemoryChange"
.db 0x0d
.str "l HexFileLoad"
.db 0x0d
.str "j jump"
.db 0x0d
.str "i I/oRegister"
.db 0x0d
.str "c Call"
.db 0x0d
.db 0x00
dump_msg:
.str "addr +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F"
.db 0x0d
.db 0x00
.end
HEXファイル
:03000000C3000139
:200100003E01D33A3E0FD33B3E3FD3063E1FD3043EF0D3073ED8D305310000CD870321907F
:2001200003CD69033E3ECD7C03CD7303CD7C03FE3FCC5F01FE64CC5402FE6DCC6A02FE6C32
:20014000CCC101FE6ACC6C01FE69CC9E02FE63CC9601FE0D28CEFE0028CACD660118C521B6
:20016000C403CD6903C93E0DCD7C03C93E20CD7C03CDD902FE00201A3E20CD7C033E79CD9E
:200180007C033E3ACD7C03CD7303FE792004CD6601E9CD6601C93E20CD7C03CDD902FE00D4
:2001A00020F03E20CD7C033E79CD7C033E3ACD7C03CD7303FE7920DACD660111C001D5E946
:2001C000C9CDFB01FEFF2819FE0120F53E0DCD7C033E4FCD7C033E4BCD7C033E0DCD7C035F
:2001E000C93E0DCD7C033E45CD7C033E52CD7C033E52CD7C033E0DCD7C03C93E0DCD7C0321
:200200001600CD7303FE3A2048CDD402457A8057CDD902E5DDE17A858457CDD4027DFE0069
:200220002020CDD402DD7500DD237D825710F3CDD4027A85FE002019CD7303FE0A20123E9C
:2002400000C9FE01200BCDD4027DFEFF20033E01C93EFFC93E20CD7C03CDD902FE002803E2
:20026000FDE5E1CDFF02E5FDE1C93E20CD7C03CDD902FE0028063E0DCD7C03C93E20CD7CDC
:20028000037ECD30033E20CD7C03E5CDD402FE002803E1AFC94DE1713E0DCD7C03C93E20CC
:2002A000CD7C03CDD402FE0028063E0DCD7C03C93E20CD7C0306004DED78CD30033E20CD36
:2002C0007C03CDD402FE002802AFC97DED793E0DCD7C03C9C506021803C506042100001829
:2002E0000429292929CD7303CD7C03CD4303FEFF2809E60FB56F10E9C1AFC93EFFC1C93E36
:200300000DCD7C03E5211304CD6903E17CCD30037DCD30033E20CD7C03CD7C0306107E23A7
:20032000CD30033E20CD7C0310F43E0DCD7C03C9F50F0F0F0FCD5D03CD7C03F1CD5D03CD1A
:200340007C03C9D6303813FE0A380ED611FE063806D620FE063003C60AC93EFFC9E60FFECE
:200360000A3803C637C9C630C97EFE00C8CD7C032318F6DB39CB4F28FADB38C9F5DB39CBF2
:200380004728FAF1D338C93E4ED3393E05D339C94D6F6E69746F72204B4C3543383020439D
:2003A000505520766572302E3731202062792050696E65636F6E6520323032302F31302F56
:2003C00031360D000D3F2048656C700D64204D656D6F727944756D700D6D204D656D6F727A
:2003E000794368616E67650D6C2048657846696C654C6F61640D6A206A756D700D6920494E
:200400002F6F52656769737465720D632043616C6C0D006164647220202B30202B31202BE3
:2004200032202B33202B34202B35202B36202B37202B38202B39202B41202B42202B43203C
:0A0440002B44202B45202B460D0015
:00000001FF