1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 15:38:08 +11:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Virgil Dupras
29a6ee128d core: fix PSP leak in CASE..ENDCASE 2020-04-18 22:05:11 -04:00
Virgil Dupras
a2d89de557 drv/sdc: implement core words in z80
In addition to making the driver significantly faster, it allows us
to make SDC port configuration opaque to sdc.fs.
2020-04-18 20:33:51 -04:00
Virgil Dupras
a70366aa43 drv/sdc: Implement SDC!
This has been tested in the RC2014 emulator. I could edit blocks with
the Block Editor and they would correctly be written to SDC.
2020-04-18 19:39:28 -04:00
Virgil Dupras
47a7133b8b drv/sdc: Implement "SDC@" as a BLK@ word
"0 LIST" in the RC2014 emulator w/ SD card works!
2020-04-18 18:00:13 -04:00
Virgil Dupras
f3c92684a0 link: improve reliability by never relinking last word
It's not possible to reliably determine its end and with some memory
initialization scenarios, it makes RLDICT fail.
2020-04-18 16:51:48 -04:00
8 changed files with 108 additions and 50 deletions

View File

@ -2,8 +2,8 @@
FORGET x -- Rewind the dictionary (both CURRENT and HERE) FORGET x -- Rewind the dictionary (both CURRENT and HERE)
up to x's previous entry. up to x's previous entry.
PREV a -- a Return a wordref's previous entry. PREV a -- a Return a wordref's previous entry.
WHLEN a -- n Get word header length from wordref. That is, WORD( a -- a Get wordref's beginning addr.
name length + 3. a is a wordref

View File

@ -1,12 +1,3 @@
: SDC_CSHIGH 6 ;
: SDC_CSLOW 5 ;
: SDC_SPI 4 ;
: _sdcSR SDC_SPI PC! SDC_SPI PC@ ;
: _sel 0 SDC_CSLOW PC! ;
: _desel 0 SDC_CSHIGH PC! ;
( -- n ) ( -- n )
: _idle 0xff _sdcSR ; : _idle 0xff _sdcSR ;
@ -93,30 +84,31 @@
( cmd arg1 arg2 -- r ) ( cmd arg1 arg2 -- r )
( Send a command that expects a R1 response, handling CS. ) ( Send a command that expects a R1 response, handling CS. )
: SDCMDR1 _sel _cmd _desel ; : SDCMDR1 _sdcSel _cmd _sdcDesel ;
( cmd arg1 arg2 -- r arg1 arg2 ) ( cmd arg1 arg2 -- r arg1 arg2 )
( Send a command that expects a R7 response, handling CS. A R7 ( 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 is a R1 followed by 4 bytes. arg1 contains bytes 0:1, arg2
has 2:3 ) has 2:3 )
: SDCMDR7 : SDCMDR7
_sel _sdcSel
_cmd ( r ) _cmd ( r )
_idle 256 * ( r h ) _idle 256 * ( r h )
_idle + ( r arg1 ) _idle + ( r arg1 )
_idle 256 * ( r arg1 h ) _idle 256 * ( r arg1 h )
_idle + ( r arg1 arg2 ) _idle + ( r arg1 arg2 )
_desel _sdcDesel
; ;
: _err _sdcDesel ABORT" SDerr" ;
( Initialize a SD card. This should be called at least 1ms ( Initialize a SD card. This should be called at least 1ms
after the powering up of the card. r is result. after the powering up of the card. )
Zero means success, non-zero means error. )
: SDC$ : SDC$
( Wake the SD card up. After power up, a SD card has to ( 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 receive at least 74 dummy clocks with CS and DI high. We
send 80. ) send 80. )
10 0 DO 0xff SDC_SPI PC! LOOP 10 0 DO _idle DROP LOOP
( call cmd0 and expect a 0x01 response (card idle) ( call cmd0 and expect a 0x01 response (card idle)
this should be called multiple times. we're actually this should be called multiple times. we're actually
@ -128,16 +120,16 @@
SDCMDR1 SDCMDR1
DUP 0x01 = IF LEAVE THEN DUP 0x01 = IF LEAVE THEN
LOOP LOOP
0x01 = NOT IF 1 EXIT THEN 0x01 = NOT IF _err THEN
( Then comes the CMD8. We send it with a 0x01aa argument ( Then comes the CMD8. We send it with a 0x01aa argument
and expect a 0x01aa argument back, along with a 0x01 R1 and expect a 0x01aa argument back, along with a 0x01 R1
response. ) response. )
0b01001000 0 0x1aa ( CMD8 ) 0b01001000 0 0x1aa ( CMD8 )
SDCMDR7 ( r arg1 arg2 ) SDCMDR7 ( r arg1 arg2 )
0x1aa = NOT IF 2 EXIT THEN ( arg2 check ) 0x1aa = NOT IF _err THEN ( arg2 check )
0 = NOT IF 3 EXIT THEN ( arg1 check ) 0 = NOT IF _err THEN ( arg1 check )
0x01 = NOT IF 4 EXIT THEN ( r check ) 0x01 = NOT IF _err THEN ( r check )
( Now we need to repeatedly run CMD55+CMD41 (0x40000000) ( Now we need to repeatedly run CMD55+CMD41 (0x40000000)
until the card goes out of idle mode, that is, when until the card goes out of idle mode, that is, when
@ -147,24 +139,23 @@
BEGIN BEGIN
0b01110111 0 0 ( CMD55 ) 0b01110111 0 0 ( CMD55 )
SDCMDR1 SDCMDR1
0x01 = NOT IF 5 EXIT THEN 0x01 = NOT IF _err THEN
0b01101001 0x4000 0x0000 ( CMD41 ) 0b01101001 0x4000 0x0000 ( CMD41 )
SDCMDR1 SDCMDR1
DUP 0x01 > IF DROP 6 EXIT THEN DUP 0x01 > IF _err THEN
NOT UNTIL NOT UNTIL
( Out of idle mode! Success! ) ( Out of idle mode! Success! )
0
; ;
( dstaddr blkno -- f ) ( dstaddr blkno -- )
: SDC@ : _sdc@
_sel _sdcSel
0x51 ( CMD17 ) 0x51 ( CMD17 )
0 ROT ( a cmd 0 blkno ) 0 ROT ( a cmd 0 blkno )
_cmd _cmd
IF _desel 0 EXIT THEN IF _err THEN
_wait _wait
0xfe = NOT IF _desel 0 EXIT THEN 0xfe = NOT IF _err THEN
0 SWAP ( crc a ) 0 SWAP ( crc a )
512 0 DO ( crc a ) 512 0 DO ( crc a )
DUP ( crc a a ) DUP ( crc a a )
@ -179,6 +170,46 @@
_idle 256 * _idle 256 *
_idle + ( crc2 ) _idle + ( crc2 )
_wait DROP _wait DROP
_desel _sdcDesel
= ( success if crc1 == crc2 ) = NOT IF _err THEN
;
: SDC@
2 * DUP BLK( SWAP ( b a b )
_sdc@
1+ BLK( 512 + SWAP
_sdc@
;
( srcaddr blkno -- )
: _sdc!
_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 ( lsb )
_sdcSR DROP
_wait DROP
_sdcDesel
;
: SDC!
2 * DUP BLK( SWAP ( b a b )
_sdc!
1+ BLK( 512 + SWAP
_sdc!
; ;

21
drv/sdc.z80 Normal file
View File

@ -0,0 +1,21 @@
( n -- n )
( Initiate SPI exchange with the SD card. n is the data to
send. )
CODE _sdcSR
HL POPqq,
chkPS,
A L LDrr,
SDC_SPI OUTnA,
NOP, NOP,
SDC_SPI INAn,
L A LDrr,
HL PUSHqq,
;CODE
CODE _sdcSel
SDC_CSLOW OUTnA,
;CODE
CODE _sdcDesel
SDC_CSHIGH OUTnA,
;CODE

View File

@ -183,7 +183,6 @@ void sdc_spi_wr(SDC *sdc, uint8_t val)
return; return;
} }
if (cmd == 24) { if (cmd == 24) {
fprintf(stderr, "cmd24\n");
if (sdc->fp) { if (sdc->fp) {
fseek(sdc->fp, arg2*512, SEEK_SET); fseek(sdc->fp, arg2*512, SEEK_SET);
} }

View File

@ -58,9 +58,9 @@
( During a CASE, the stack grows by 1 at each ENDOF so that ( During a CASE, the stack grows by 1 at each ENDOF so that
we can fill all those ENDOF branching addrs. So that we we can fill all those ENDOF branching addrs. So that we
know when to stop, we put a 0 on PSP. That's our stopgap. ) know when to stop, we put a 0 on PSP. That's our stopgap. )
: CASE 0 ; IMMEDIATE : CASE 0 COMPILE >R ; IMMEDIATE
: OF : OF
COMPILE OVER COMPILE = COMPILE I COMPILE =
[COMPILE] IF [COMPILE] IF
; IMMEDIATE ; IMMEDIATE
: ENDOF [COMPILE] ELSE ; IMMEDIATE : ENDOF [COMPILE] ELSE ; IMMEDIATE
@ -70,10 +70,11 @@
hit 0. ) hit 0. )
: ENDCASE : ENDCASE
BEGIN BEGIN
DUP NOT IF DROP EXIT THEN DUP NOT IF
DROP COMPILE R> COMPILE DROP EXIT
THEN
[COMPILE] THEN [COMPILE] THEN
AGAIN AGAIN
COMPILE DROP
; IMMEDIATE ; IMMEDIATE
: CREATE : CREATE
@ -154,17 +155,18 @@
- ( a-o ) - ( a-o )
; ;
: WHLEN : WORD(
1- C@ ( name len field ) DUP 1- C@ ( name len field )
127 AND ( 0x7f. remove IMMEDIATE flag ) 127 AND ( 0x7f. remove IMMEDIATE flag )
3 + ( fixed header len ) 3 + ( fixed header len )
-
; ;
: FORGET : FORGET
' DUP ( w w ) ' DUP ( w w )
( HERE must be at the end of prev's word, that is, at the ( HERE must be at the end of prev's word, that is, at the
beginning of w. ) beginning of w. )
DUP WHLEN - HERE ! ( w ) WORD( HERE ! ( w )
PREV CURRENT ! PREV CURRENT !
; ;

View File

@ -39,9 +39,6 @@
1+ 1+
; ;
( Get word addr, starting at name's address )
: '< ' DUP WHLEN - ;
( Relink atom at a, applying offset o with limit ol. ( Relink atom at a, applying offset o with limit ol.
Returns a, appropriately skipped. Returns a, appropriately skipped.
) )
@ -127,6 +124,10 @@
The output of this word is 3 numbers: top copied address, The output of this word is 3 numbers: top copied address,
top copied CURRENT, and then the beginning of the copied dict top copied CURRENT, and then the beginning of the copied dict
at the end to indicate that we're finished processing. at the end to indicate that we're finished processing.
Note that the last word is always skipped because it's not
possible to reliably detect its end. If you need that last
word, define a dummy word before calling RLDICT.
) )
( target -- ) ( target -- )
: RLDICT : RLDICT
@ -142,7 +143,7 @@
( H@+2 == offset ) ( H@+2 == offset )
H@ 2+ ! ( ) H@ 2+ ! ( )
( We have our offset, now let's copy our memory chunk ) ( We have our offset, now let's copy our memory chunk )
H@ @ DUP WHLEN - ( src ) H@ @ WORD( ( src )
DUP H@ -^ ( src u ) DUP H@ -^ ( src u )
DUP ROT SWAP ( u src u ) DUP ROT SWAP ( u src u )
H@ 4 + ( u src u dst ) H@ 4 + ( u src u dst )
@ -154,9 +155,9 @@
offset by u+4. +4 before, remember, we're using 4 bytes offset by u+4. +4 before, remember, we're using 4 bytes
as variable space. ) as variable space. )
4 + ( u+4 ) 4 + ( u+4 )
DUP H@ + ( u we ) DUP CURRENT @ WORD( + ( u we )
DUP .X CRLF DUP .X CRLF
SWAP CURRENT @ + ( we wr ) SWAP CURRENT @ PREV + ( we wr )
DUP .X CRLF DUP .X CRLF
BEGIN ( we wr ) BEGIN ( we wr )
DUP ROT ( wr wr we ) DUP ROT ( wr wr we )
@ -169,7 +170,7 @@
DUP ( wr wr ) DUP ( wr wr )
PREV ( oldwr newwr ) PREV ( oldwr newwr )
SWAP ( wr oldwr ) SWAP ( wr oldwr )
DUP WHLEN - ( wr we ) WORD( ( wr we )
SWAP ( we wr ) SWAP ( we wr )
( Are we finished? We're finished if wr-4 <= H@ ) ( Are we finished? We're finished if wr-4 <= H@ )
DUP 4 - H@ <= DUP 4 - H@ <=

View File

@ -10,6 +10,7 @@ BOOTSRCS = conf.fs \
$(FDIR)/boot.fs \ $(FDIR)/boot.fs \
$(FDIR)/z80c.fs \ $(FDIR)/z80c.fs \
$(BASEDIR)/drv/acia.z80 \ $(BASEDIR)/drv/acia.z80 \
$(BASEDIR)/drv/sdc.z80 \
$(FDIR)/icore.fs \ $(FDIR)/icore.fs \
$(EDIR)/xstop.fs $(EDIR)/xstop.fs

View File

@ -2,5 +2,8 @@
0xf000 CONSTANT RS_ADDR 0xf000 CONSTANT RS_ADDR
0x80 CONSTANT ACIA_CTL 0x80 CONSTANT ACIA_CTL
0x81 CONSTANT ACIA_IO 0x81 CONSTANT ACIA_IO
4 CONSTANT SDC_SPI
5 CONSTANT SDC_CSLOW
6 CONSTANT SDC_CSHIGH
RAMSTART 0x70 + CONSTANT ACIA_MEM RAMSTART 0x70 + CONSTANT ACIA_MEM