Close

Z80 (CP/M) Writing to SD Card

A project log for 3-Chip Z80 Design

Combining a Z80 retro design with a modern PSoC CPU.

land-boardscomland-boards.com 10/25/2019 at 11:060 Comments

Digging into SD card writes means shifting gears from the Boot BIOS source code since the Boot BIOS code only does reads. The CP/M BIOS code (CBIOS128.LST) which does the reads/writes after booting. Here's the BIOS code for writes to the SD Card:

0754   EAC4             ;================================================================================================
0755   EAC4             ; Write physical sector to host
0756   EAC4             ;================================================================================================
0757   EAC4             
0758   EAC4             writehst:
0759   EAC4 F5                  PUSH     AF
0760   EAC5 C5                  PUSH     BC
0761   EAC6 E5                  PUSH     HL
0762   EAC7             
0763   EAC7 DB 89       wrWait1: IN    A,(SD_STATUS)
0764   EAC9 FE 80               CP    128
0765   EACB 20 FA               JR    NZ,wrWait1
0766   EACD             
0767   EACD CD 2B EA            CALL     setLBAaddr
0768   EAD0                     
0769   EAD0 3E 01               LD    A,$01    ; 01 = Write block
0770   EAD2 D3 89               OUT    (SD_CONTROL),A
0771   EAD4                 
0772   EAD4 0E 04               LD     c,4
0773   EAD6 21 D2 FB            LD     HL,hstbuf
0774   EAD9             wr4secs:
0775   EAD9 06 80               LD     b,128
0776   EADB             wrByte:
0777   EADB                 
0778   EADB DB 89       wrWait2: IN    A,(SD_STATUS)
0779   EADD FE A0               CP    160 ; Write buffer empty
0780   EADF 20 FA               JR    NZ,wrWait2
0781   EAE1             
0782   EAE1 7E                  LD     A,(HL)
0783   EAE2 D3 88               OUT    (SD_DATA),A
0784   EAE4 23                  INC     HL
0785   EAE5 05                  dec     b
0786   EAE6 20 F3               JR     NZ, wrByte
0787   EAE8             
0788   EAE8 0D                  dec     c
0789   EAE9 20 EE               JR     NZ,wr4secs

The command to write to the SD card is 0x01. This is distinguished from reads which have a command of 0x00. The function SDWriteCommand( ) needs to call the read SD function or write SD function depending on the value.

The status value will require some thought. Here's the three values used by the sector read and sector write functions under the Z80 FPGA version of CP/M:

CP/M sectors are 128-bytes. Grant's code performed a tradeoff and set the sector size to 512-bytes. That's taken care of with the wr4secs loop. 

I messed around with the status values and got writes partly working (at least not hanging). I got this:

>RUN
>SAVE "MY.BAS"

Close error
>BYE

And the directory looks messed up:

A>dir
A: DOWNLOAD COM : LOAD     COM : PIP      COM : STAT     COM
A: SUBMIT   COM : DDT      COM : DISPLAY  COM : DUMP     COM
A: ED       COM : ASM      COM : BBCBASIC COM : POWER    COM
A: MBASIC   COM : BAS      BAS : BLINKLED BAS : blinkled bas
A: 0@@@  : .@@@  : 2@@@  : 2@@@

I think I'll go back to the PSoC debugger side. First I need to create a new SD so that I don't mess up this one.

I did copy the 128MB disk using HxD and should be able to re-create it again if I had to.

Discussions