Shop OBEX P1 Docs P2 Docs Learn Events
P2 SD PASM Driver Demo using SPIN2 (also uses Serial Monitor) v.209 — Parallax Forums

P2 SD PASM Driver Demo using SPIN2 (also uses Serial Monitor) v.209

Cluso99Cluso99 Posts: 18,069
edited 2020-05-08 08:23 in Propeller 2
SD Driver (pasm)

Here is my latest SD PASM Driver and demo in SPIN2 :)

It utilises my Serial Monitor (pasm) too :)

2929-05-08: Update v.209
Added spin call routines to the SD driver (and Serial Monitor) to simplify calling from spin.
Now returns $0 on success, -1=$FFFF_FFFF on failure.

2020-05-06: Update v.208
Code support for old bytemode SD cards removed
Fixed a bug where the initialisation clocks were failing due to 5us calculated at 20MHz with pullup on P59. Now works to 360MHz.
Returns status and checked in spin
- pnut v34r works only with P59 pullup
- fastspin 4.1.8 reports failure due to bug - will be fixed in next fastspin release
General tidy code tidyup.
Both SDDriver_208.spin2 and SDDriver_Equ.spin2 must be used as a pair.
Option to write sector commented out.

2020-05-06: Update: v.207c
New spin routines initialiseSD, readCSDCID, readSector, writeSector.
SD Driver now returns status for the preceeding calls but not checked in spin.

WARNING / NOTES:
* Always use the matching pair SDDriver_Code_207c.spin2 with SDDriver_Equ.spin2
* Option commented out to read, modify, write, read, fix, write, read sector $0000_0001 - It will temporarily overwrite sector $0000_0001 on your SD Card !!!
* Error detection working in the SD Driver but does not work in spin!!!
* Debug code displays the working registers and sector data to the serial port

Compiles with fastspin v4.1.8 (cannot load using pnut v34r)
C:\P2\Propeller_II_Latest\SDDriver_207>type f2.bat
f418 %1.spin2 -2 -l
l418 %1.binary -b115200 -t -SINGLE
C:\P2\Propeller_II_Latest\SDDriver_207>f2 sddriver_demo2


Here is an output on windows command prompt using fastspin...
.....
C:\P2\Propeller_II_Latest\SDDriver_209>l418 sddriver_demo209.binary -b115200 -t -SINGLE
( Entering terminal mode.  Press Ctrl-] to exit. )
P2-Monitor V1.51
P2-SDDriver x209
pass
  100: 00 00 00 00  01 46 04 F6  25 00 C0 FD  4F 08 63 6E   '.....F..%...O.cn'
  104: 50 00 00 00  00 02 00 00  87 00 00 00  00 00 00 00   'P...............'
  108: FF 00 00 00  00 00 00 00  FF FF FF FF  02 46 04 F6   '.............F..'
  10C: 00 00 00 00  65 D8 00 F6  66 DA 00 F6  6C 44 02 F6   '....e...f...lD..'

pass
  100: 00 00 00 00  01 46 04 F6  00 C1 0F 00  DD CD 07 72   '.....F.........r'
  104: 4A 00 00 00  00 00 00 00  87 00 00 00  01 00 00 00   'J...............'
  108: FF 00 00 00  FE 00 00 00  FF FF FF FF  00 00 00 00   '................'
  10C: 00 00 00 00  65 D8 00 F6  66 DA 00 F6  6C 44 02 F6   '....e...f...lD..'

FC100: 03 53 44 53  4C 31 36 47  80 14 F3 4A  67 01 15 69   '.SDSL16G...Jg..i'
FC110: EC 02 90 FD  1A C8 06 F6  F6 01 88 FC  64 05 D8 FC   '............d...'

pass
  100: 00 00 00 00  00 00 00 00  00 C1 0F 00  13 64 C8 72   '.............d.r'
  104: 51 00 00 00  00 00 00 00  87 00 00 00  01 00 00 00   'Q...............'
  108: FF 00 00 00  FE 00 00 00  FF FF FF FF  00 00 00 00   '................'
  10C: 00 00 00 00  65 D8 00 F6  66 DA 00 F6  6C 44 02 F6   '....e...f...lD..'

FC100: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC110: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC120: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC130: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC140: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC150: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC160: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC170: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC180: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC190: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC1A0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC1B0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC1C0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC1D0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC1E0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC1F0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC200: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC210: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC220: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC230: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC240: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC250: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC260: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC270: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC280: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC290: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC2A0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC2B0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 82   '................'
FC2C0: 03 00 0C FE  FF FF 00 20  00 00 00 AC  DA 01 00 00   '....... ........'
FC2D0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC2E0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
FC2F0: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 55 AA   '..............U.'

*

Comments

  • This seems like it might be useful. What sort of transfer rates are you seeing with this driver and the cards you are using Cluso?

    Can you just run the SD part without the extra monitor components or are there dependencies?
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-05 01:39
    rogloh wrote: »
    This seems like it might be useful. What sort of transfer rates are you seeing with this driver and the cards you are using Cluso?

    Can you just run the SD part without the extra monitor components or are there dependencies?
    Both are separate entities and can be located anywhere in hub (hubexec) and use any registers.
    They can each be called from pasm or spin.

    There are No dependencies between the monitor and the sd :)

    I haven't done any timing tests and it will be slower than if it were in cog.
    Maybe later I will copy the send/recv routine to cog to execute faster. It will fit in less than 16 longs. The routine does both send and receive combined. Due to required delays in the silicon the receive and transmit combined are without penalty.
    This is the loop which could then be a cog rep
    .nextbit        rol     sd.dataout,      #1         wc  ' \ prepare output bit (DI=0/1)..
                    outl    #sd.ck                          ' | CLK=0  (already 0 first time)
                    outc    #sd.di                          ' / write output bit: output on CLK falling edge
                    waitx   #2                              ' |   setup time to be safe
                    outh    #sd.ck                          ' \ CLK=1
                    waitx   #3                              ' |   setup time to be safe
                    testp   #sd.do                      wc  ' | read input bit:   sample on CLK rising edge
                    rcl     sd.reply,        #1             ' / accum DO input bits
                    djnz    sd.bitcnt,       #.nextbit      '   8/32 bits?
                    outl    #sd.ck                          ' CLK=0 on exit
    

    I have had extreme difficulty in getting this to run due to all sorts of compiler issues with errant addressing. It's only with Eric's latest v4.1.8 that I can compile this and then it ran first time! Same driver pasm as I've been trying to get running for the last 6+ months. Been extremely frustrating :(

    BTW I've stripped the FAT32 file LOAD and RUN from the code. It now only uses 16 cog registers and not all of them are necessary as I'm going to strip all old SD Card support for sector byte addressing. So only SDHC+ using addressing in sectors.
  • roglohrogloh Posts: 5,787
    edited 2020-05-05 03:05
    Thanks for answering that Cluso.

    So from what I see here at 21 clocks per loop iteration (EDIT: if you use REP instead of DJNZ) it seems the best speed in a COG running this loop would be about 8.6Mbps or just a little over 1 MB/s at 180MHz raw SPI transfer rate, and in practice this will be lowered with loop setup overheads/latency of course. Maybe a REP loop would be good to use instead of the DJNZ in Hub-exec mode (assuming interrupts can be delayed by the 8 bits) so that the 8 instructions in the loop fit entirely in the single HUB transfer with the FIFO refill and the branch penalty is then eliminated?

    Also if we wish to go faster, I imagine a Smartpin approach can be taken hopefully getting us closer to 25Mbps, though it would then become a different implementation to this and it might be able to make use of the streamer at some point too. There may be other SPI implementations that already do that...haven't gone hunting around myself.
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-05 13:55
    Here is a new spin2 demo that just initialises the SD card, reports if it worked (not a proper test!!), and then reads sector 0, then calls the monitor.

    Uses the files in the first post excluding SDDriver_Demo.spin2

    Postedit: Should always test those quickies :( There's a bug in the compiler so it always fails :(
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-05 13:58
    2020-05-05 Update v.207c

    There is a new update to my SD Driver, Equates and Demo files in the top post. Please replace all SDDriver files. Monitor files have not changed but are included.

    There is plenty of debug info output to the serial terminal which can be disabled if required.
  • evanhevanh Posts: 15,916
    rogloh wrote: »
    ... Maybe a REP loop would be good to use instead of the DJNZ in Hub-exec mode (assuming interrupts can be delayed by the 8 bits) so that the 8 instructions in the loop fit entirely in the single HUB transfer with the FIFO refill and the branch penalty is then eliminated?
    Doesn't work that way. The FIFO only prefetches in a straight line. Even the special REP looping still looks like a branch to the FIFO.
    Also if we wish to go faster, I imagine a Smartpin approach can be taken hopefully getting us closer to 25Mbps, though it would then become a different implementation to this and it might be able to make use of the streamer at some point too. There may be other SPI implementations that already do that...haven't gone hunting around myself.
    Best next step is streamer for SPI data and smartpin for SPI clock. This then allows easy going to dualSPI mode.

  • evanhevanh Posts: 15,916
    Oh, man, just worked out that SD booting can't have the optional 100 ms serial override window like the EEPROM can have. That was a bit of an oversight. :(


  • Cluso99Cluso99 Posts: 18,069
    evanh wrote: »
    Oh, man, just worked out that SD booting can't have the optional 100 ms serial override window like the EEPROM can have. That was a bit of an oversight. :(
    Can you explain a little more please?
    Do you mean that the SD is not looking for the serial while trying to boot the SD? If so, then yes it doesn't look. We were lucky to get SD booting!

    BTW You can put a pullup on P59 to prevent the SD booting. This is required to use pnut as otherwise pnut doesn't find the P2. Fastspin/LoadP2 works fine.




  • Cluso99Cluso99 Posts: 18,069
    Updated first post with v.208 plus info :sunglasses:
  • evanhevanh Posts: 15,916
    I mean the mask ROM boot up options. What would've been convenient is doing testing and SD updates via serial port, without removing the SD card - Just like as is done with the EEPROM. The way it is, the moment there is a valid boot file on the SD card you lose the ability to control it from the serial port.
  • evanhevanh Posts: 15,916
    edited 2020-05-06 09:10
    P60 pull-up should have been this:
    Serial window of 100ms, then SD card. If SD card fails then serial window of 60s.

  • Cluso99Cluso99 Posts: 18,069
    evanh wrote: »
    I mean the mask ROM boot up options. What would've been convenient is doing testing and SD updates via serial port, without removing the SD card - Just like as is done with the EEPROM. The way it is, the moment there is a valid boot file on the SD card you lose the ability to control it from the serial port.
    Agreed. You can do it by switching P59 pullup on which prevents the SD card booting but that's operating a switch (if it exists).

    However, there is another way...
    The SD boot file could then listen on the serial port and do whatever it is supposed to be doing at the same time.

    We were very limited to what Chip would let us (Peter and I) do in the ROM as Chip was understandably not willing to let us do anything that might cause his boot code to not work. Chip's code tests for the pullups and then jumps to my SD code, or in the case of the autobaud strings, Chip jumps to my SD or Peter's TAQOZ. It was only at the last minute that the SD code was changed to return to Chip's code on failure. Originally it was supposed to stop.
  • evanhevanh Posts: 15,916
    At least I now know why it is the way it is.

  • Cluso99Cluso99 Posts: 18,069
    edited 2020-05-07 23:10
    Calling Formats

    SDinit initialises the SD Card.
    This routine must be called before any other routine (readCSDCID, readSector, writeSector) is called.
    This routine currently requires bufad to be preset with an address for the hub sector buffer. I need to check if bufads is actually used by the routine as I think it no longer needs to be set.

    readCSDCID
    This routine requires bufad to be preset with an address for the hub sector buffer. The CSD (16 bytes) followed by CID (16 bytes) will be placed into hub at the address specified by bufad.

    readSector
    This routine requires sector to be preset with the (raw) sector address and bufad to be preset with an address for the hub sector buffer. The sector (512 bytes) will be placed into hub at the address specified by bufad.

    writeSector
    This routine requires sector to be preset with the (raw) sector address and bufad to be preset with an address for the hub sector buffer. The sector (512 bytes) will read from hub at the address specified by bufad and written to the sector on the card.

    Status
    All the above routines (SDInit, readCSDCID, readSector, writeSector) return status in the status cog register. It's value can be checked by comparing the value in status with the predefined constant success. Currently success will be signaled by status returning $A5 and an error will be signaled by status returning $FFFF_FFFF.
    Further status information can be obtained by examining the cmdout cog register which contains the last command sent to the card. Note the command sent to the card is "OR"ed with $40.

    SD Card Pins used are currently hardcoded to the P2 boot standard of P60=#CS, P61=CLK, P59=DI(MOSI in to card), P58=DO(MISO out from card).

    Cog Register Usage is currently $100-$10C but may be changed and recompiled. See/change _regs equate in the SDDriver_EQU.spin2 file.

    Hub Code Space is currently $FC560-~$FC880+ but may be changed and recompiled. See/change _hub equate in the SDDriver_EQU.spin2 file.

    Hub sector buffer can be set to use $FC100[512] if desired as this is in the ROM booter space which can be reused (at least for now). The Serial Monitor uses $FC000[80] so don't use this space please.

    Disable Boot from SD Card
    This can be done by enabling a 10K pullup on P59 (a switch on P2EVAL pcbs) which forces the booter to go to the serial download routine.

    History and Gotchas

    My P2 SD Driver is based on the code I wrote for the P2 ROM plus a couple of tweeks and then some tidyup and removal of the support for really old cards using byte based addressing (2GB and less), and the file load and run sections which are probably better done with fsrw or FATEngine (Kye's) in spin. I spent some serious time back then finding out why many SD Cards do not release (float) DO after the whole transaction and I implemented this in the RevB silicon ROM. We were on a time schedule and I continued after the ROM code was frozen and found one obscure way where the DO may not be released although I think that path is unlikely.

    This new code should now, under all circumstances, release DO after a transaction/routine (ie Initialise, readCSDCID, readSector, writeSector), and all SD Card pins are also floated too. This means sharing the pins with the Flash (or others) should work properly provided the pins are also released (floated) by other software.

    In the last few days I've been finally been able to get my serial debug code (BTW is it a serial driver also) working and found that SD Card initialisation was sometimes failing. This was because I had coded the initialisation clocks used a hardcoded 5us which was calculated based on RC mode ~20MHz and 100Hz clocks. I've updated this to 5us 360MHz which should work up to 400MHz which would be over the max P2 clock range. Note this routine does not know the actual clock/frequency used - in the ROM at boot time this was known to be around ~22MHz.


  • Cluso99Cluso99 Posts: 18,069
    Version 209 updated on first post.

    Note there is also a Serial Monitor demo too.
Sign In or Register to comment.