parts/z80/sdc: add sdcInitialize

Also, adjust SD card recipe. Straightforward initialization and read!
This commit is contained in:
Virgil Dupras 2019-05-08 16:03:54 -04:00
parent 3d82d7fb30
commit 12ca2bd53e
4 changed files with 108 additions and 71 deletions

View File

@ -131,3 +131,85 @@ sdcCmdR7:
out (SDC_PORT_CSHIGH), a
ret
; Initialize a SD card. This should be called at least 1ms after the powering
; up of the card. Sets result code in A. Zero means success, non-zero means
; error.
sdcInitialize:
push hl
push de
push bc
call sdcWakeUp
; Call CMD0 and expect a 0x01 response (card idle)
; This should be called multiple times. We're actually expected to.
; Let's call this for a maximum of 10 times.
ld b, 10
.loop1:
ld a, 0b01000000 ; CMD0
ld hl, 0
ld de, 0
ld c, 0x95
call sdcCmdR1
cp 0x01
jp z, .cmd0ok
djnz .loop1
; Nothing? error
jr .error
.cmd0ok:
; Then comes the CMD8. We send it with a 0x01aa argument and expect
; a 0x01aa argument back, along with a 0x01 R1 response.
ld a, 0b01001000 ; CMD8
ld hl, 0
ld de, 0x01aa
ld c, 0x87
call sdcCmdR7
cp 0x01
jr nz, .error
xor a
cp h ; H is zero
jr nz, .error
cp l ; L is zero
jr nz, .error
ld a, d
cp 0x01
jp nz, .error
ld a, e
cp 0xaa
jr nz, .error
; Now we need to repeatedly run CMD55+CMD41 (0x40000000) until we
; the card goes out of idle mode, that is, when it stops sending us
; 0x01 response and send us 0x00 instead. Any other response means that
; initialization failed.
.loop2:
ld a, 0b01110111 ; CMD55
ld hl, 0
ld de, 0
call sdcCmdR1
cp 0x01
jr nz, .error
ld a, 0b01101001 ; CMD41 (0x40000000)
ld hl, 0x4000
ld de, 0x0000
call sdcCmdR1
cp 0x01
jr z, .loop2
or a ; cp 0
jr nz, .error
; Success! out of idle mode!
; At this point, you are ready to read and write data.
jr .success
.error:
ld a, 0x01
jr .end
.success:
xor a
.end:
pop bc
pop de
pop hl
ret

View File

@ -11,7 +11,7 @@ jr init
; Why not use this unused space between 0x02 and 0x28 for a jump table?
jp printstr
jp printHex
jp sdcWakeUp
jp sdcInitialize
jp sdcSendRecv
jp sdcWaitResp
jp sdcCmd
@ -29,6 +29,8 @@ init:
ld sp, hl
im 1
call aciaInit
xor a
call blkSel
call shellInit
; TODO - block device creation
@ -43,9 +45,15 @@ ACIA_RAMSTART .equ RAMSTART
.define STDIO_PUTC call aciaPutC
STDIO_RAMSTART .equ ACIA_RAMEND
#include "stdio.asm"
SHELL_RAMSTART .equ STDIO_RAMEND
.define SHELL_IO_GETC call aciaGetC
.define SHELL_IO_PUTC call aciaPutC
BLOCKDEV_RAMSTART .equ STDIO_RAMEND
BLOCKDEV_COUNT .equ 1
#include "blockdev.asm"
; List of devices
.dw aciaGetC, aciaPutC, 0, 0
SHELL_RAMSTART .equ BLOCKDEV_RAMEND
.define SHELL_IO_GETC call blkGetCW
.define SHELL_IO_PUTC call blkPutC
SHELL_EXTRA_CMD_COUNT .equ 0
#include "shell.asm"

View File

@ -1,9 +1,9 @@
JUMP_PRINTSTR .equ 0x03
JUMP_PRINTHEX .equ 0x06
JUMP_SDCWAKEUP .equ 0x09
JUMP_SDCSENDRECV .equ 0x0c
JUMP_SDCWAITRESP .equ 0x0f
JUMP_SDCCMD .equ 0x12
JUMP_SDCCMDR1 .equ 0x15
JUMP_SDCCMDR7 .equ 0x18
JUMP_PRINTSTR .equ 0x02
JUMP_PRINTHEX .equ 0x05
JUMP_SDCINITALIZE .equ 0x08
JUMP_SDCSENDRECV .equ 0x0b
JUMP_SDCWAITRESP .equ 0x0e
JUMP_SDCCMD .equ 0x11
JUMP_SDCCMDR1 .equ 0x14
JUMP_SDCCMDR7 .equ 0x17

View File

@ -1,62 +1,9 @@
#include "jumptable.inc"
.org 0x9000
call JUMP_SDCWAKEUP
; We expect a 0x01 R1 response
ld hl, sCmd
call JUMP_PRINTSTR
ld a, 0b01000000 ; CMD0
ld hl, 0
ld de, 0
ld c, 0x95
call JUMP_SDCCMDR1
cp 0x01
call JUMP_SDCINITALIZE
or a
jp nz, .error
ld hl, sOk
call JUMP_PRINTSTR
; We expect a 0x01 R1 response followed by 0x0001aa R7 response
ld hl, sCmd
call JUMP_PRINTSTR
ld a, 0b01001000 ; CMD8
ld hl, 0
ld de, 0x01aa
ld c, 0x87
call JUMP_SDCCMDR7
ld a, d
cp 0x01
jp nz, .error
ld a, e
cp 0xaa
jr nz, .error
ld hl, sOk
call JUMP_PRINTSTR
; Now we need to repeatedly run CMD55+CMD41 (0x40000000) until we
; the card goes out of idle mode, that is, when it stops sending us
; 0x01 response and send us 0x00 instead. Any other response means that
; initialization failed.
ld hl, sCmd
call JUMP_PRINTSTR
.loop1:
ld a, 0b01110111 ; CMD55
ld hl, 0
ld de, 0
call JUMP_SDCCMDR1
cp 0x01
jr nz, .error
ld a, 0b01101001 ; CMD41 (0x40000000)
ld hl, 0x4000
ld de, 0x0000
call JUMP_SDCCMDR1
cp 0x01
jr z, .loop1
cp 0
jr nz, .error
; Success! out of idle mode!
ld hl, sOk
call JUMP_PRINTSTR
; Alright, normally we should configure block size and all, but this is
; too exciting and we'll play it dirty: we'll read just enough bytes
@ -78,17 +25,17 @@
call JUMP_PRINTSTR
; Command sent, no error, now let's wait for our data response.
ld b, 20
.loop3:
.loop1:
call JUMP_SDCWAITRESP
; 0xfe is the expected data token for CMD17
cp 0xfe
jr z, .loop3end
jr z, .loop1end
cp 0xff
jr nz, .error
djnz .loop3
djnz .loop1
jr .error
.loop3end:
.loop1end:
ld hl, sGettingData
call JUMP_PRINTSTR
; Data packets follow immediately