TMPZ84C015でCP/MシステムをSDCARDに読み書きし、ブートするプログラムを作成しましたが、同様にZ8S180についてもプログラムを作成してみました。
前回のBIOSへの対応と同じように、TMPZ84C015のプログラムからZ8S180用に変更していきました。
実際にプログラムを動作させ確認してみます。
まずは、アセンブルします。(ソースファイル名はz8s180_cpm_rw005.asm、最後の方でソースは展開しています)
$ asz80 -l -s -o z8s180_cpm_rw005.asm
$ aslink -i z8s180_cpm_rw005
モニタに入り、64Kモニタに切り替えた後、CPM.HEX、z8s180_bios304.ihxのhexファイルをlコマンドで読み込みます。
続いて、今回作成したz8s180_cpm_rw005.ihxを同じくlコマンドで読み込みます。
jコマンドで 0x8000へジャンプします。
>j 8000 y:
:SDHC
read >> r :write >> w CP/M go >> g key in:
SDCARDにシステム(CCP+BDOS)書き込みします。
wキーでwriteを選択し、0000ブロックから000bブロック、アドレスdc00より書き込み指定し、yキーで書き込み実行します。
read/write start block No:0000
read/write block:000b
read/write addr:dc00
Yes: read/write ok!
続いてBIOSを書き込みます。
000bブロックから 0004ブロック、アドレスf200より書き込みしてします。
>j 8000 y:
:SDHC
read >> r :write >> w CP/M go >> g key in:w
read/write start block No:000b
read/write block:0004
read/write addr:f200
Yes: read/write ok!
>
これで 書き込みされたので、一旦電源を切り、モニタを立ち上げ、tコマンドで64Kモニタに切り替えます 。
もう一度cpm_rw005.ihxをlコマンドで読込します。
j 8000で 8000番地にジャンプします。
今度は、bキーでCP/Mシステムをbootします。
j 8000 y:
:SDHC
read >> r :write >> w CP/M boot >> b key in:b
CP/M system boot !
:SDHC
62K CP/M VERS 2.2
A>
ちゃんとブートできました。速度もZ8S180のほうが早いような気がします。
(Z8S180は33MHz版を使用して、64Kram時はモニタ上で外部クロック16MHzを2倍速で動作させています。)
次はモニタ上でブートできるようにしたいと思います。
今回のソースを展開しました。
;z80 (Z8S180) cp/m V2.2 system read/write by Pinecone 2020/04/08
; Z8S180 cpu
; ram 0000h -- ffffh(MMU setting)
; External clock 16MHz
; Z8S180 serial communication (Ch0)
; extemal Clock
;
; spi Interface (sd-card)
; i/o address
; INPUT-PORT 0x84(r) 74HC541
; OUTPUT-PORT 0x84(w) 74HC574
; assembler
; program start 8000H
; main 8000H
;
; assemblers ASxxxx and ASlink V5.10
; file name z8s180_cpm_rw005.asm
; $ asz80 -l -s -o z8s180_cpm_rw005.asm
; $ aslink -i z8s180_cpm_rw005
; $ z180_moni73(spi) l command Hex load jump 0x8000
;
.z180
;;spi i/o port setting
INPUTP .equ 0x84 ;;74HC541
OUTPUTP .equ 0x84 ;;74HC574
;OUTPUT-PORT
S_DI .equ 7 ;0b10000000 D7
S_CS .equ 6 ;0b01000000 D6
S_CLK .equ 5 ;0b00100000 D5
;INPUT-PORT
DO .equ 7 ;0b10000000 D7
TDR0 .equ 0x06 ;ch0 serial
RDR0 .equ 0x08
STAT0 .equ 0x04
CNTLA0 .equ 0x00
CNTLB0 .equ 0x02
.area CPM_RW(ABS)
.org 0x8000
; spi read, write. boot
;
;
start:
call init_spi
ld hl,rwg_msg
call msgout
call getchar
call putchar
cp "r"
jr z,read
cp "w"
jr z,write
cp "b"
jr z,cpm_boot
ret
read:
call cr
call spi_read
ret
write:
call cr
call spi_write
ret
cpm_boot:
ld hl,0x0000 ;CP/M system block 0x0000 start
ld (rw_block_no),hl
ld hl,0x000b ;ccp+bdos >0x0b
ld (rw_block),hl
ld hl,0xdc00 ;62K cp/m ccp top addr >> 0xdc00
ld (rw_addr),hl
call spi_read_go
ld hl,0x000b ;CP/M bios block 0x000b start
ld (rw_block_no),hl
ld hl,0x0004 ;bios >0x04
ld (rw_block),hl
ld hl,0xf200 ;62K cp/m bios top addr >> 0xf200
ld (rw_addr),hl
call spi_read_go
ld hl,cpm_boot_msg
call msgout
jp 0xf200
init_spi:
push af
xor a
set S_CS,a ;CS="H"
set S_DI,a ;DI="H"
out0 (OUTPUTP),a
ld b,80 ;80 clok output
call loopspii
pop af
xor a
out0 (OUTPUTP),a ;CS="L" DI="L" CLK="L"
call cmd0_out
cp 0x01
jp nz,init_err
call cmd8_out
cp 0x01
jp nz,init_err
call cmd55_out
cp 0x01
jp nz,init_err
call acmd41_out
call cmd58_out
ld a,(r7)
bit 7,a
jp z,init_err
bit 6,a
jr z,SD_ver2
ld hl,sdhc_msg
init_msg:
call msgout
call set_cs
ret
SD_ver2:
ld hl,sd_ver2_msg
jr init_msg
init_err:
ld hl,spi_init_err_msg
call msgout
ld a,0x0d
call putchar
jp 0x0000
set_cs:
xor a
set S_CS,a ;CS="H"
set S_DI,a ;DI="H"
out0 (OUTPUTP),a
ret
cmd0_out:
ld hl,cmd0
call cmd_out
call r1_resp
ret
cmd8_out:
call dummy_data
ld hl,cmd8
call cmd_out
call r1_resp
cp 0x01
ret nz
ld b,4
ld hl,r7
cmd8_r:
call resp
ld (hl),a
inc hl
djnz cmd8_r
ld a,0x01
ret
cmd55_out:
call dummy_data
ld hl,cmd55
call cmd_out
call r1_resp
ret
acmd41_out:
call dummy_data
ld hl,acmd41 ;sd-card Initialize
call cmd_out
call r1_resp
cp 0x00
ret z
call cmd55_out
jr acmd41_out
cmd58_out:
call dummy_data
ld hl,cmd58
call cmd_out
call r1_resp
push af
ld b,4
ld hl,r7
cmd58_r:
call resp
ld (hl),a
inc hl
djnz cmd58_r
cmd58_r_d:
ld hl,r7
ld b,4
cmd58_r_d_loop:
inc hl
djnz cmd58_r_d_loop
ld a,0x0d
call putchar
pop af
ret
cr:
ld a,0x0d
call putchar
ret
spi_read:
call data_in
cp 0x00
ret z
ld hl,yes_msg
call msgout
call getchar
cp "y"
ret nz
call spi_read_go
call cr
ret
spi_write:
call data_in
cp 0x00
ret z
ld hl,yes_msg
call msgout
call getchar
cp "y"
ret nz
call spi_write_go
ret
data_in:
call cr
ld hl,rw_sblock_no_msg
call msgout
call input_hl
cp 0x00
jr z,spi_data_in01
call cr
xor a
ret
spi_data_in01: ;read/write block no
call cr
ld (rw_block_no),hl
ld hl,rw_block_msg
call msgout
call input_hl
cp 0x00
jr z,spi_data_in02
call cr
xor a
ret
spi_data_in02:
call cr
ld (rw_block),hl ;read/write block
ld hl,rw_addr_msg
call msgout
call input_hl
cp 0x00
jr z,spi_data_in03
call cr
xor a
ret
spi_data_in03:
call cr
ld (rw_addr),hl ;read/write addr
ld a,0xff
ret
spi_write_go:
ld hl,(rw_block_no)
ld a,(r7)
bit 6,a
jp z,write_SD_ver2
ld a,h ;SDHC
ld (cmd25+03),a
ld a,l
ld (cmd25+04),a
jr spi_write4
write_SD_ver2: ;Ver2
ld a,h
ld (cmd25+02),a
ld a,l
ld (cmd25+03),a
spi_write4:
call dummy_data
ld hl,cmd25
call cmd_out
call r1_resp
cp 0x00
jp nz,cmd25_err
ld d,0xff
call spi_8bit
sector_write_loop:
ld hl,(rw_addr)
ld d,0xfc ;cmd25 data token
call spi_8bit
;; spi write 256byte 1st blok
ld b,0x00
cmd25_w: ;1st 256byte write
ld d,(hl)
inc hl
call spi_8bit ; D reg >> write data
djnz cmd25_w
; 2st write 256byte 1st blok
ld b,0x00
cmd25_w2st: ;2st 256byte write
ld d,(hl)
inc hl
call spi_8bit ; D reg >> write data
djnz cmd25_w2st
ld (rw_addr),hl
ld d,0xff
call spi_8bit ;crc
ld d,0xff
call spi_8bit ;crc
call r1_resp
and 0x0f
cp 0x05
jr nz,cmd25_err2
cmd25_wch:
call resp
cp 0x00
jr z,cmd25_wch
ld d,0xff
call spi_8bit
ld hl,(rw_block)
dec hl
ld (rw_block),hl
ld a,h ;HL = 0?
or l
jr nz,sector_write_loop
ld d,0xfd ;cmd25 stop token
call spi_8bit
ld d,0xff
call spi_8bit
cmd25_wch2:
call resp
cp 0x00
jr z,cmd25_wch2
call dummy_data
call set_cs ;set CS
ld hl,rw_ok_msg
call msgout
call cr
xor a
ret
cmd25_err:
cmd25_err2:
ld hl,cmd25_err_msg
call msgout
call set_cs ;set CS
ld a,0x01
ret
spi_read_go:
ld hl,(rw_block_no)
ld a,(r7)
bit 6,a
jp z,read_SD_ver2
ld a,h ;SDHC
ld (cmd18+03),a
ld a,l
ld (cmd18+04),a
jr spi_read01
read_SD_ver2: ;Ver2
ld a,h
ld (cmd18+02),a
ld a,l
ld (cmd18+03),a
spi_read01:
call dummy_data
ld hl,cmd18
call cmd_out
call r1_resp
cp 0x00
jp nz,cmd18_err
sector_read_loop:
cmd18_st:
call r1_resp ;read data start response?
cp 0xfe ;data start byte 0xfe?
jr nz, cmd18_st
ld hl,(rw_addr)
ld b,0x00
cmd18_r:
call resp ;read data
ld (hl),a
inc hl
djnz cmd18_r
; 2st dummy read
ld b,0x00
cmd18_r2st: ;2st 256byte write
call resp
ld (hl),a
inc hl
djnz cmd18_r2st
ld (rw_addr),hl
call resp ;crc Skipping read
call resp ;crc Skipping read
ld hl,(rw_block)
dec hl
ld (rw_block),hl
ld a,h ;HL = 0?
or l
jr nz,sector_read_loop
ld d,0xff ;dummy data 0xff(cs low)
call spi_8bit
ld hl,cmd12 ;stop cmd
call cmd_out ;cmd12 Issue
ld d,0xff
call spi_8bit
call r1_resp
cp 0x00 ;response is 0x00 read mode OK?
jr nz,cmd18_err
cmd18_wch:
call resp
cp 0x00
jr z,cmd18_wch
call set_cs
xor a
ret
;; 1 sector write
cmd18_err:
cmd18_err2:
ld hl,cmd25_err_msg
call msgout
call set_cs
ld a,0x01
ret
;**************************************************
cmd_out: ;command out
push hl
push bc
ld b,0x06 ;command line word count
cmd_out1:
ld d,(hl) ;command line area
call spi_8bit
inc hl
djnz cmd_out1
pop bc
pop hl
ret
r1_resp:
call resp
cp 0xff
jr z,r1_resp
ret
resp:
ld d,0xff
call spi_8bit
ld a,e
ret
cmd0_msg:
.str "CMD0:"
.db 0x00
dummy_data:
xor a
set S_CS,a ;CS="H"
set S_DI,a ;DI="H"
out0 (OUTPUTP),a
ld b,8 ;1clok output
call loopspii
xor a
set S_CS,a ;CS="H"
set S_DI,a ;DI="H"
out0 (OUTPUTP),a
ret
loopspii:
res S_CLK,a ;CLK L
out0 (OUTPUTP),a
nop
nop
nop
nop
nop
nop
nop
nop
set S_CLK,a ;CLK H
out0 (OUTPUTP),a
nop
nop
nop
nop
nop
djnz loopspii
ret
spi_8bit: ;outdata Dreg,inputdata Ereg
push bc
ld c,0x00
ld b,0x08
loopspi:
xor a
rlc d
rra
res S_CLK,a ;CLK L
out0 (OUTPUTP),a
nop
nop
nop
nop
nop
nop
set S_CLK,a ;CLK H
out0 (OUTPUTP),a
in0 a,(INPUTP)
rlca
rl e
djnz loopspi
xor a
set S_DI,a ;DI H
out0 (OUTPUTP),a
pop bc
ret
msgout:
ld a,(hl) ;(HL)reg is output disp at 0x00
cp 0x00
ret z
call putchar
inc hl
jr msgout
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
hex_ascii: ;Areg(HEX) >> Areg(ascii code)
and a,0x0f
cp 0x0a
jr c,ascii0_9
add 0x37
ret
ascii0_9:
add 0x30
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
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
getchar:
in0 a,(STAT0)
rlca
jr nc,getchar
in0 a,(RDR0)
and 0x7f
ret
putchar:
push af
putchar01:
in0 a,(STAT0)
bit 1,a
jr z,putchar01
pop af
out0 (TDR0),a
ret
com_init:
push af
ld a,0x64
out0 (CNTLA0),a
ld a,0x07
out0 (CNTLB0),a
pop af
ret
sdhc_msg:
.str ":SDHC"
.db 0x0d
.db 0x00
sd_ver2_msg:
.str ":SD Ver2"
.db 0x0d
.db 0x00
spi_init_err_msg:
.str "Spi Init Err"
.db 0x0d
.db 0x00
cmd17_err_msg:
.str "cmd17 Err"
.db 0x0d
.db 0x00
cmd24_err_msg:
.str "cmd24 Err"
.db 0x0d
.db 0x00
cmd25_err_msg:
.str "cmd25 Err"
.db 0x0d
.db 0x00
rw_sblock_no_msg:
.str " read/write start block No:"
.db 0x00
rw_block_msg:
.str " read/write block:"
.db 0x00
rw_addr_msg:
.str " read/write addr:"
.db 0x00
yes_msg:
.str " Yes:"
.db 0x00
rw_ok_msg:
.str " read/write ok!"
.db 0x00
rwg_msg:
.str " read >> r :write >> w CP/M boot >> b key in:"
.db 0x00
cpm_boot_msg:
.db 0x0d
.str " CP/M system boot !"
.db 0x0d
.db 0x00
cmd0: ;;48bit(6byte) Fixed length
.db 0x40 ;;command index
.db 0x00 ;;argument
.db 0x00 ;;argument
.db 0x00 ;;argument
.db 0x00 ;;argument
.db 0x95 ;;CRC
cmd8:
.db 0x48
.db 0x00
.db 0x00
.db 0x01
.db 0xaa
.db 0x87
cmd55:
.db 0x77
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0xff
acmd41:
.db 0x69
.db 0x40
.db 0xff
.db 0x80
.db 0x00
.db 0xff
cmd58:
.db 0x7a
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0xff
cmd16:
.db 0x50
.db 0x00
.db 0x00
.db 0x02
.db 0x00
.db 0xff
cmd17:
.db 0x51
.db 0x00
.db 0x00
.db 0x02
.db 0x00
.db 0xff
cmd18:
.db 0x52
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0xff
cmd12:
.db 0x4c
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0xff
cmd23:
.db 0x57
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0xff
cmd24:
.db 0x58
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0xff
cmd25:
.db 0x59
.db 0x00
.db 0x00
.db 0x00
.db 0x00
.db 0xff
r7:
.ds 4
rw_block_no:
.ds 2
rw_block:
.ds 2
rw_addr:
.ds 2
.end