Shop OBEX P1 Docs P2 Docs Learn Events
SPin2 SD card directory display — Parallax Forums

SPin2 SD card directory display

Has anyone got a very simple SPin2 app or obj to read an SPi connected SD card and display on the terminal.

To show that it is working and reading files, a bit of a SD Card "hello world"

Thanks

Comments

  • AndyPropAndyProp Posts: 60
    edited 2024-01-23 09:32

    Read from SD Card and display some contents of a file

    CON 
      _clkfreq  = 300_000_000
    
    CON
      HEAPSIZE = 32768
    
    VAR
      long f1
      byte bstr[512]
    
    OBJ
       c : "libc.a"               ' C standard library
    
    PUB main() : err | i,ch
      err := _mount(@"/sd", c._vfs_open_sdcard())
      debug(sdec(err))
      ifnot err
        f1 := c.fopen(@"/sd/test.txt",@"rb")
        debug(sdec(f1))
        ifnot f1
          debug("Error at open")
        else
          c.fread(@bstr, 511, 1, f1)
          debug(zstr(@bstr))
        c.fclose(f1)
    
    
  • Just posted this FAT32 object to the OBEX. Tried to make it as simple to use as possible.

    CON
      _CLKFREQ = 80_000_000
      _SD_MISO = 58                   
      _SD_SCK  = 61                   
      _SD_MOSI = 59                   
      _SD_CS   = 60                   
    VAR
      byte  buffer[2048]
    OBJ
      sd : "SD card driver"
    PUB main() 
      if sd.mount(_SD_CS, _SD_MOSI, _SD_MISO, _SD_SCK)
        sd.openFile(string("filename.txt"))
        sd.read(@buffer,sd.fileSize())
        debug(zstr(@buffer))
    
  • @ChrisGadd said:
    Just posted this FAT32 object to the OBEX. Tried to make it as simple to use as possible.

    CON
      _CLKFREQ = 80_000_000
      _SD_MISO = 58                   
      _SD_SCK  = 61                   
      _SD_MOSI = 59                   
      _SD_CS   = 60                   
    VAR
      byte  buffer[2048]
    OBJ
      sd : "SD card driver"
    PUB main() 
      if sd.mount(_SD_CS, _SD_MOSI, _SD_MISO, _SD_SCK)
        sd.openFile(string("filename.txt"))
        sd.read(@buffer,sd.fileSize())
        debug(zstr(@buffer))
    

    I tried it, did not work on my card, I am having a hard time with cards at the moment anyway so it does not surprise me.

    I can list the directory in Taqoz via Flexprop terminal and see a text file exists but that's about it.

    Attached an image of mine in case you like to test that type too.

  • Re-verified that it works with all of my cards, all but the 512MB are SDHC, in a full-size socket and on the P2 eval board micro socket, all good provided it's formatted as FAT32.
    The mounting/initialization routines are based on FSRW, and the spi routines on sdspi_fast_bashed.

  • @ChrisGadd said:
    Re-verified that it works with all of my cards, all but the 512MB are SDHC, in a full-size socket and on the P2 eval board micro socket, all good provided it's formatted as FAT32.
    The mounting/initialization routines are based on FSRW, and the spi routines on sdspi_fast_bashed.

    Thanks Chris, I will have a look in a few days when I get some new boards.

    It would be interesting if somehow you could make a version in Forth & Taqoz or working together so that Taqoz has the 32 bit ability

  • Hello all,

    (First post...apologies in advance.) I need to be able store large files on an SD card using the P2 Edge Module.

    I was unable to get fsrw or Chris Gadd's code to even mount an SD card. I modified AndyProp's spin2/C code (below) and it usually mounts in 1-3 tries, and fread seems to work with mode "rb". However, I could not get fwrite() to work. Even worse, if I just open a file with mode "rwb" and read it, the code below erases the file contents.

    I am using flexprop 6.9.10 with P2 default commands, and, like Chris, a SanDisk Extreme 32GB SDHC. I can verify the file contents before and after using my mac.

    I noticed that in the zip file for flexprop at /include/libc/stdio , fwrite() only does a fflush(), which looks quite different from the fwrite() in glibc.

    My goal is to be able to reliably write buffers of byte and long data to SD card files, and am quite stuck. I am barely conversational in C, so any help would be appreciated!

    CON 
      _clkfreq  = 300_000_000
    
    CON
      HEAPSIZE = 32768
    
    VAR
      long f1, f2
      byte bstr[512]
    
    OBJ
       c : "libc.a"               ' C standard library
    
    PUB main() : err_open | i,ch
      err_open := _mount(@"/sd", c._vfs_open_sdcard())
      debug(sdec(err_open))
      ifnot err_open
        repeat i from 1 to 3
          f1 := c.fopen(@"/sd/filename.txt",@"rwb") 
          debug(sdec(f1))
          ifnot f1
            debug("Error at open, ", sdec_long(i))
            waitms(100)
          else
            quit
        debug("Exited open loop, ", sdec_long(i))
        c.fread(@bstr, 9, 1, f1)
        debug(zstr(@bstr))
        bstr[0] := "Z"
        debug(zstr(@bstr))
    {      
        c.fwrite(@bstr, 9, 1, f1)
    }      
        c.fclose(f1)
    
  • JonnyMacJonnyMac Posts: 9,214

    I had to make a small tweak to it, but I got Ray Allen's port of FSRW for the P2 working. That said, many of my apps require access to the flash chip so the convoluted cross connection between SD and flash -- pushed by a person no long part of this community -- was a stupid idea. If you can give up four pins for SD access, and a couple more for power control and card detect, Ray's code may work for you. I found it a lot faster than Chris's code (I'm running canonical [not compiled] Spin2). In my case I am using it inside an audio player for laser tag, and in one case I have to convert a single gunshot into a machine gun sound by opening and restarting the same file every 75ms.

    I made my own uSD accessory that includes a PFET (suggested by Terry Trap) so that the Px can cycle uSD power. Chip has one of these and is working on a Parallax uSD object that can access up to two files simultaneously.

  • That is a great h/w design for uSD; saving power will be important in my final design. Would be nice to see it in a P2 Edge Module rev!

    My first attempt was with FSRW; mount consistently failed. The fact that the above code at least mounts the card after a few tries and reads a file makes me wonder if there are lurking timing issues with all of these.

    Hoping to see Chip's uSD object...for me, one file at a time is OK. Also hoping it will include create/write.

  • ersmithersmith Posts: 6,112

    @shannon1949 said:
    I was unable to get fsrw or Chris Gadd's code to even mount an SD card. I modified AndyProp's spin2/C code (below) and it usually mounts in 1-3 tries, and fread seems to work with mode "rb". However, I could not get fwrite() to work. Even worse, if I just open a file with mode "rwb" and read it, the code below erases the file contents.

    "rwb" would be interpreted the same as "wb" which would indeed erase the existing file contents. If you want to read the existing data but possibly append to it later, use "r+b".

    I'm also not sure about the 300_000_000 clock frequency. I'd suggest starting at the officially supported 180_000_000 and working your way up from there. It's possible that some combination of hardware and software flakiness is causing you trouble at the higher frequency.

  • evanhevanh Posts: 16,178
    edited 2025-01-29 13:53

    @shannon1949 said:
    My first attempt was with FSRW; mount consistently failed. The fact that the above code at least mounts the card after a few tries and reads a file makes me wonder if there are lurking timing issues with all of these.

    The old driver code that comes with FSRW has a number of bugs. Primarily it doesn't wait for card ready. Try this driver - https://forums.parallax.com/discussion/comment/1563810/#Comment_1563810

  • evanhevanh Posts: 16,178
    edited 2025-01-29 14:19

    @shannon1949 said:
    I am using flexprop 6.9.10 with P2 default commands, and, like Chris, a SanDisk Extreme 32GB SDHC. I can verify the file contents before and after using my mac.

    I noticed that in the zip file for flexprop at /include/libc/stdio , fwrite() only does a fflush(), which looks quite different from the fwrite() in glibc.

    Update your Flexspin to v7. There is lots of changes to the built-in filesystem underpinnings. If you are designing your own board then there is now also option for 4-bit SD mode of operation and wiring. Nice speed up when using Flexspin - https://forums.parallax.com/discussion/comment/1563936/#Comment_1563936

    EDIT: Hmm, that Spin2 edition of the tester might be out of date for the new 4-bit SD mode driver. It should be fine for the default SPI mode driver though.

  • Thanks all. I upgraded to flexprop 7.0.0 and have Spin2/C code that mounts the SD card and can read, write, and append to an existing file on the SD card. But I also need to create a file that does not exist on the SD card. No matter what mode string (w, w+, wb, w+b, etc.) I try, the c.fopen() call fails if the file does not exist. I've attached my code below (value of _clkfreq seems to make no difference). If anyone has an Edge module and SD card to check, or can advise, I'd be grateful.

    CON
      '' _clkfreq  = 307_200_000
      _clkfreq  = 180_000_000  
    
    CON
      HEAPSIZE = 32768
    
    VAR
      long f1
      long max_open_tries
    
    OBJ
       c : "libc.a"               ' C standard library
    
    PUB main() : err_mount | i, ch
    
      max_open_tries := 5  
    
      '' --------------
      '' Mount SD
      '' --------------
      err_mount := -1
      repeat until err_mount == 0
        err_mount := _mount(@"/sd", c._vfs_open_sdcard())
        debug(sdec(err_mount))
        waitms(5)
    
      ifnot err_mount
    
        '' --------------
        '' Create file
        '' --------------
    
        repeat i from 1 to max_open_tries
          ''  wb == Create in binary mode (will wipe out contents if exists)
          f1 := c.fopen(@"/sd/filename10.txt",@"w+") 
          debug(sdec(f1))
          ifnot f1
            debug("Error at create open, ", sdec_long(i))
            waitms(5)
            if i == max_open_tries
              debug("...last try failed")
          else
            quit
        debug("Exited create/open loop, ", sdec_long(i))
    
        c.fclose(f1)
    
  • @shannon1949 That's because filename10.txt is not a valid FAT filename (max. 8 characters).
    If you really need to, you can add

    #define FF_USE_LFN 1
    #pragma exportdef FF_USE_LFN
    

    to the top of your file to enable LFN support, but this blows up the memory usage.

    Also:

    • use just libc, not libc.a - the latter will not give you the constants for fseek
    • The actual error codes are in errno. Try debug(zstr(c.strerror(errno)))
  • Thanks very much. In my testing of writing/reading/appending, my filename happened to be <=8 characters!! I will test to see if memory usage for long file names works in my program.

    @Wuerfel_21 said:
    @shannon1949 That's because filename10.txt is not a valid FAT filename (max. 8 characters).
    If you really need to, you can add

    #define FF_USE_LFN 1
    #pragma exportdef FF_USE_LFN
    

    to the top of your file to enable LFN support, but this blows up the memory usage.

    Also:

    • use just libc, not libc.a - the latter will not give you the constants for fseek
    • The actual error codes are in errno. Try debug(zstr(c.strerror(errno)))
Sign In or Register to comment.