Copy sdc driver to blkfs

This commit is contained in:
Virgil Dupras 2020-04-23 13:55:00 -04:00
parent a19376df6c
commit 8fbbf5209a
19 changed files with 191 additions and 11 deletions

View File

@ -4,7 +4,7 @@ MASTER INDEX
70 Implementation notes 100 Block editor
200 Z80 assembler 260 Cross compilation
280 Z80 boot code 350 ACIA driver
370 SD Card driver

4
blk/370 Normal file
View File

@ -0,0 +1,4 @@
SD Card driver
Load the z80 part with "372 LOAD", the Forth part with
"374 LOAD".

View File

@ -1,7 +1,6 @@
( n -- n )
( Initiate SPI exchange with the SD card. n is the data to
send. )
CODE _sdcSR
CODE _sdcSR ( n -- n )
HL POPqq,
chkPS,
A L LDrr,
@ -12,10 +11,4 @@ CODE _sdcSR
HL PUSHqq,
;CODE
CODE _sdcSel
SDC_CSLOW OUTnA,
;CODE
CODE _sdcDesel
SDC_CSHIGH OUTnA,
;CODE
373 LOAD

9
blk/373 Normal file
View File

@ -0,0 +1,9 @@
CODE _sdcSel
SDC_CSLOW OUTnA,
;CODE
CODE _sdcDesel
SDC_CSHIGH OUTnA,
;CODE

16
blk/374 Normal file
View File

@ -0,0 +1,16 @@
( -- n )
: _idle 0xff _sdcSR ;
( -- n )
( _sdcSR 0xff until the response is something else than 0xff
for a maximum of 20 times. Returns 0xff if no response. )
: _wait
0 ( cnt )
BEGIN
_idle
DUP 0xff = IF DROP ELSE SWAP DROP EXIT THEN
1+
DUP 20 = UNTIL
DROP 0xff
;
375 386 LOADR

10
blk/375 Normal file
View File

@ -0,0 +1,10 @@
( -- )
( The opposite of sdcWaitResp: we wait until response is 0xff.
After a successful read or write operation, the card will be
busy for a while. We need to give it time before interacting
with it again. Technically, we could continue processing on
our side while the card it busy, and maybe we will one day,
but at the moment, I'm having random write errors if I don't
do this right after a write, so I prefer to stay cautious
for now. )
: _ready BEGIN _idle 0xff = UNTIL ;

16
blk/376 Normal file
View File

@ -0,0 +1,16 @@
( c n -- c )
( Computes n into crc c with polynomial 0x09
Note that the result is "left aligned", that is, that 8th
bit to the "right" is insignificant (will be stop bit). )
: _crc7
XOR ( c )
8 0 DO
2 * ( <<1 )
DUP 255 > IF
( MSB was set, apply polynomial )
0xff AND
0x12 XOR ( 0x09 << 1, we apply CRC on high bits )
THEN
LOOP
;

16
blk/377 Normal file
View File

@ -0,0 +1,16 @@
( c n -- c )
( Computes n into crc c with polynomial 0x1021 )
: _crc16
SWAP DUP 256 / ( n c c>>8 )
ROT XOR ( c x )
DUP 16 / XOR ( c x^x>>4 )
SWAP 256 * ( x c<<8 )
OVER 4096 * XOR ( x c^x<<12 )
OVER 32 * XOR ( x c^x<<5 )
XOR ( c )
;
( send-and-crc7 )
( n c -- c )
: _s+crc SWAP DUP _sdcSR DROP _crc7 ;

16
blk/378 Normal file
View File

@ -0,0 +1,16 @@
( cmd arg1 arg2 -- resp )
( Sends a command to the SD card, along with arguments and
specified CRC fields. (CRC is only needed in initial commands
though). This does *not* handle CS. You have to
select/deselect the card outside this routine. )
: _cmd
_wait DROP ROT ( a1 a2 cmd )
0 _s+crc ( a1 a2 crc )
ROT 256 /MOD ROT ( a2 h l crc )
_s+crc _s+crc ( a2 crc )
SWAP 256 /MOD ROT ( h l crc )
_s+crc _s+crc ( crc )
0x01 OR ( ensure stop bit )
_sdcSR DROP ( send CRC )
_wait ( wait for a valid response... )
;

16
blk/379 Normal file
View File

@ -0,0 +1,16 @@
( cmd arg1 arg2 -- r )
( Send a command that expects a R1 response, handling CS. )
: SDCMDR1 _sdcSel _cmd _sdcDesel ;
( cmd arg1 arg2 -- r arg1 arg2 )
( Send a command that expects a R7 response, handling CS. A R7
is a R1 followed by 4 bytes. arg1 contains bytes 0:1, arg2
has 2:3 )
: SDCMDR7
_sdcSel
_cmd ( r )
_idle 256 * _idle + ( r arg1 )
_idle 256 * _idle + ( r arg1 arg2 )
_sdcDesel
;

16
blk/380 Normal file
View File

@ -0,0 +1,16 @@
: _err _sdcDesel ABORT" SDerr" ;
( Initialize a SD card. This should be called at least 1ms
after the powering up of the card. )
: SDC$
( Wake the SD card up. After power up, a SD card has to receive
at least 74 dummy clocks with CS and DI high. We send 80. )
10 0 DO _idle DROP LOOP
( 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. )
0 ( dummy )
10 0 DO ( r )
DROP 0x40 0 0 SDCMDR1 ( CMD0 )
DUP 0x01 = IF LEAVE THEN
LOOP 0x01 = NOT IF _err THEN ( cont. )

10
blk/381 Normal file
View File

@ -0,0 +1,10 @@
( Then comes the CMD8. We send it with a 0x01aa argument and
expect a 0x01aa argument back, along with a 0x01 R1
response. )
0x48 0 0x1aa ( CMD8 )
SDCMDR7 ( r arg1 arg2 )
0x1aa = NOT IF _err THEN ( arg2 check )
0 = NOT IF _err THEN ( arg1 check )
0x01 = NOT IF _err THEN ( r check )
( cont. )

13
blk/382 Normal file
View File

@ -0,0 +1,13 @@
( Now we need to repeatedly run CMD55+CMD41 (0x40000000)
until 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. )
BEGIN
0x77 0 0 SDCMDR1 ( CMD55 )
0x01 = NOT IF _err THEN
0x69 0x4000 0x0000 SDCMDR1 ( CMD41 )
DUP 0x01 > IF _err THEN
NOT UNTIL
( Out of idle mode! Success! )
;

15
blk/383 Normal file
View File

@ -0,0 +1,15 @@
: _sdc@ ( dstaddr blkno -- )
_sdcSel 0x51 ( CMD17 ) 0 ROT ( a cmd 0 blkno ) _cmd
IF _err THEN
_wait 0xfe = NOT IF _err THEN
0 SWAP ( crc a )
512 0 DO ( crc a )
DUP _idle ( crc a a n )
DUP ROT C! ( crc a n )
ROT SWAP _crc16 ( a crc )
SWAP 1+ ( crc a+1 )
LOOP
DROP ( crc1 )
_idle 256 * _idle + ( crc2 )
_wait DROP _sdcDesel
= NOT IF _err THEN ;

7
blk/384 Normal file
View File

@ -0,0 +1,7 @@
: SDC@
2 * DUP BLK( SWAP ( b a b )
_sdc@
1+ BLK( 512 + SWAP
_sdc@
;

16
blk/385 Normal file
View File

@ -0,0 +1,16 @@
: _sdc! ( srcaddr blkno -- )
_sdcSel 0x58 ( CMD24 ) 0 ROT ( a cmd 0 blkno ) _cmd
IF _err THEN
_idle DROP 0xfe _sdcSR DROP
0 SWAP ( crc a )
512 0 DO ( crc a )
C@+ ( crc a+1 n )
ROT OVER ( a n crc n )
_crc16 ( a n crc )
SWAP ( a crc n )
_sdcSR DROP ( a crc )
SWAP ( crc a )
LOOP
DROP ( crc ) 256 /MOD ( lsb msb )
_sdcSR DROP _sdcSR DROP
_wait DROP _sdcDesel ;

7
blk/386 Normal file
View File

@ -0,0 +1,7 @@
: SDC!
2 * DUP BLK( SWAP ( b a b )
_sdc!
1+ BLK( 512 + SWAP
_sdc!
;

View File

@ -7,7 +7,6 @@ EMUL = $(BASEDIR)/emul/hw/rc2014/classic
BOOTSRCS = conf.fs \
$(EDIR)/xcomp.fs \
drvz80.fs \
$(BASEDIR)/drv/sdc.z80 \
$(FDIR)/icore.fs \
$(EDIR)/stop.fs

View File

@ -1 +1,2 @@
352 LOAD ( acia.z80 )
372 LOAD ( sdc.z80 )