Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 40

Thread: Problem reading from SD card directly into PSRAM

  1. #1
    Junior Member
    Join Date
    Jan 2020
    Posts
    15

    Problem reading from SD card directly into PSRAM

    Hi,

    I'm having trouble reading directly from the SD card into PSRAM. I'm using a Teensy 4.1 with one 8MB PSRAM chip. When I pass a pointer in PSRAM to the FsFile read function, the read would often fail. The same read succeeds reliably when I pass a pointer in the internal RAM. The T4.1 is not connected to anything so it seems that the PSRAM access is interfering with the SD card access. Has anyone seen similar problems? I created a test program to reproduce it.

    Code:
    #include "SdFat.h"
    
    #define BUFSIZE (256*1024)
    #define FILENAME "TESTFILE.BIN"
    
    SdFs sd;
    FsFile file;
    char itcmBuf[BUFSIZE];
    EXTMEM char psramBuf[BUFSIZE];
    
    bool runTest(int variant){
      Serial.print("running variant ");
      Serial.println(variant);
      file.open(FILENAME);
      if(!file){
        Serial.println("file open failed");
        return false;
      }
      int total_bytes_read = 0;
      while(file.available()){
        int bytes_read;
        if(variant == 1){
          bytes_read = file.read(psramBuf, BUFSIZE);
        }else{
          bytes_read = file.read(itcmBuf, BUFSIZE);
        }
    
        if(bytes_read < 0){
          Serial.print("read failed after ");
          Serial.print(total_bytes_read);
          Serial.println(" bytes");
          file.close();
          return false;
        }else{
          //Serial.println("read ok");
          total_bytes_read += bytes_read;
        }
    
        if(variant == 3 || variant == 4){
          memcpy(psramBuf, itcmBuf, BUFSIZE);
          if(variant == 4){
            arm_dcache_flush_delete(psramBuf, BUFSIZE);
          }
        }
      }
      Serial.println("reads succeeded");
      file.close();
      return true;
    }
    
    void setup() {
      Serial.begin(115200);
      while(!Serial);
      while (!sd.begin(SdioConfig(FIFO_SDIO))) {
        Serial.println("SdFs begin() failed");
      }
      sd.chvol();
    
      // stress test
      // while(runTest(4));
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      Serial.println("Select test variant");
      Serial.println("1: SD -> PSRAM");
      Serial.println("2: SD -> ITCM");
      Serial.println("3: SD -> ITCM, ITCM -> PSRAM");
      Serial.println("4: SD -> ITCM, ITCM -> PSRAM with cache flush");
      int variant = 0;
      while(variant == 0){
        while(!Serial.available());
        char c = Serial.read();
        if(c >= '1' && c <= '4'){
          variant = c - '0';  
        }
      }
      runTest(variant);
    }
    The test has 4 variants:
    1: Read from SD to PSRAM. This fails most of the time
    2: Read from SD to ITCM. This passes reliably.
    3: Read from SD to ITCM then copy to PSRAM. This fails occasionally.
    4: Read from SD to ITCM then copy to PSRAM and flush the PSRAM cache. This passes reliably.

    Place a large file named TESTFILE.BIN in the root of the SD card and enter the variant in the serial console when prompted.

    I'm using Arduino 1.8.13, Teensyduino 1.53 and Bill Greiman's latest SdFat-beta. I tried 2 SD cards (SDXC with EXFAT and SDHC with FAT32) and the result is the same. I don't think it's a problem with the soldering because I tried Paul's PSRAM test and it passed. And I don't think it's a problem with the SD card or the SdFat library either because the reads into ITCM works reliably.

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Have not seen this noted as done or tried or done it here.

    The TeensyDuino 1.54 Beta 5 has integrated a release version ( not Beta ) of the Greiman SdFat to replace the standard SD library.

    Not sure that will offer a FIX for the issue - but will lead to repro case for resolution in current code with all code and elements under PJRC control during beta into release of TD 1.54.

  3. #3
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Also note - there have been posts like "tried Paul's PSRAM test and it passed" - but then other usage fails until solder joints are reflowed or cleaned.

    Noted as: "large file named TESTFILE.BIN" - but not how large? 1MB or something closer to 8MB?

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    I can confirm this.
    Have you informed Bill Greimann?
    He should know, at least, why read returns an error here. Seems to be totally random?

  5. #5
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    I tried reflowing the solder and adding more solder to make sure the connection is good but it didn't fix the problem. I will try the 1.54 beta. Thanks.

    I used a file around 100MB.

  6. #6
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    I'm using the beta. Does not help.
    Looking the schematic, there are again no pullups on the SD lines..

  7. #7
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    @Frank B: I haven't informed Bill Greimann. I didn't think it's the SdFat library's fault. I will try with the 1.54 beta see if the same thing happens there.

  8. #8
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    Same here. I tried with Arduino 1.8.13 and Teensyduino 1.54 beta5 and it didn't fix the problem.

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Edited the code to work with TD 1.54 b5:
    Code:
    #include <SD.h>
    #include <SPI.h>
    
    // https://forum.pjrc.com/threads/65851-Problem-reading-from-SD-card-directly-into-PSRAM?p=266951&viewfull=1#post266951
    
    #define BUFSIZE (256*1024)
    #define FILENAME "TESTFILE.BIN"
    
    // SdFs sd;
    File file;
    char itcmBuf[BUFSIZE];
    EXTMEM char psramBuf[BUFSIZE];
    
    bool runTest(int variant){
      Serial.print("running variant ");
      Serial.println(variant);
      file = SD.open(FILENAME);
      if(!file){
        Serial.println("file open failed");
        return false;
      }
      int total_bytes_read = 0;
      while(file.available()){
        int bytes_read;
        if(variant == 1){
          bytes_read = file.read(psramBuf, BUFSIZE);
        }else{
          bytes_read = file.read(itcmBuf, BUFSIZE);
        }
    
        if(bytes_read < 0){
          Serial.print("read failed after ");
          Serial.print(total_bytes_read);
          Serial.println(" bytes");
          file.close();
          return false;
        }else{
          //Serial.println("read ok");
          total_bytes_read += bytes_read;
        }
    
        if(variant == 3 || variant == 4){
          memcpy(psramBuf, itcmBuf, BUFSIZE);
          if(variant == 4){
            arm_dcache_flush_delete(psramBuf, BUFSIZE);
          }
        }
      }
      Serial.println("reads succeeded");
      file.close();
      return true;
    }
    
    void setup() {
      Serial.begin(115200);
      while(!Serial);
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
    
        if (!SD.begin(BUILTIN_SDCARD)) {
        Serial.println("Card failed, or not present");
        // don't do anything more:
        return;
      }
      Serial.println("card initialized.");
    
      // stress test
      // while(runTest(4));
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      Serial.println("Select test variant");
      Serial.println("1: SD -> PSRAM");
      Serial.println("2: SD -> ITCM");
      Serial.println("3: SD -> ITCM, ITCM -> PSRAM");
      Serial.println("4: SD -> ITCM, ITCM -> PSRAM with cache flush");
      int variant = 0;
      while(variant == 0){
        while(!Serial.available());
        char c = Serial.read();
        if(c >= '1' && c <= '4'){
          variant = c - '0';  
        }
      }
      runTest(variant);
    }
    Here shows file size ( I renamed a 2MB ZIP for testfile ). It can work with 'variant 1' - 'variant 4' does not seem to fail.
    Code:
    Initializing SD card...initialization done.
    System Volume Information/
      IndexerVolumeGuid                               76
    TESTFILE.BIN                                      2299501
    done!
    
    T:\tCode\RAM\SDtoPSRAM\SDtoPSRAM.ino Jan 17 2021 14:00:46
    card initialized.
    Select test variant
    1: SD -> PSRAM
    2: SD -> ITCM
    3: SD -> ITCM, ITCM -> PSRAM
    4: SD -> ITCM, ITCM -> PSRAM with cache flush
    running variant 1
    read failed after 0 bytes
    Select test variant
    1: SD -> PSRAM
    2: SD -> ITCM
    3: SD -> ITCM, ITCM -> PSRAM
    4: SD -> ITCM, ITCM -> PSRAM with cache flush
    running variant 1
    read failed after 524288 bytes
    Select test variant
    1: SD -> PSRAM
    2: SD -> ITCM
    3: SD -> ITCM, ITCM -> PSRAM
    4: SD -> ITCM, ITCM -> PSRAM with cache flush
    running variant 1
    reads succeeded
    Select test variant
    1: SD -> PSRAM
    2: SD -> ITCM
    3: SD -> ITCM, ITCM -> PSRAM
    4: SD -> ITCM, ITCM -> PSRAM with cache flush

  10. #10
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    Yes the same thing happens.

    Maybe it's the same problem as here: https://github.com/PaulStoffregen/SD...a9176826a6cfae
    SOmbody has to take a look... don't know if the SD Controller does this fix automatically...would be amazing - i don't think so. It was needed because of missing pullups.

  11. #11
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    The reason for this is patch is a bit complicated.. If the connections have no pullup, they can toggle when the interface pauses. Maybe beacuse lines in the near toggle.
    The chance that this happens may increase when the PS-RAM gets accessed..

    Of course this is just a shot in the blue.
    But it WAS a problem on earlier Teensys and other! MCUs

    Bill copied this patch for his library, too. But I'm not that sure that it is still there.. for the new MCUs...

  12. #12
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Quote Originally Posted by Frank B View Post
    Yes the same thing happens.

    Maybe it's the same problem as here: https://github.com/PaulStoffregen/SD...a9176826a6cfae
    SOmbody has to take a look... don't know if the SD Controller does this fix automatically...would be amazing - i don't think so. It was needed because of missing pullups.
    Not finding : SDHC_ReleaseGPIO()

    In TD 1.54 sources here?

  13. #13
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    Don't know...

    And I can't find the old thread :-(
    I remember the SD Spec says, the pullups are required. I guess the controller thinks they are there...
    The patch was a workaround. And it took me a long time to identify the problem..

  14. #14
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Closest is the below in : ...\hardware\teensy\avr\libraries\SdFat\src\SdCard \SdioTeensy.cpp
    Code:
    #elif defined(__IMXRT1062__)
    //------------------------------------------------------------------------------
    static void gpioMux(uint8_t mode) {
    ...

  15. #15
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    I think this is the equivalent for T4.1 https://github.com/greiman/SdFat-bet....cpp#L308-L309 . IOMUXC_SW_PAD_CTL_PAD_PUS(1) means 47K ohm pullup. I can try IOMUXC_SW_PAD_CTL_PAD_PUS(3) for 22K ohm pullup.

  16. #16
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    With IOMUXC_SW_PAD_CTL_PAD_PUS(3), it takes longer to fail but still fails.

    edit: This may not be true. I may have just gotten lucky.

  17. #17
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Quote Originally Posted by jcj83429 View Post
    I think this is the equivalent for T4.1 https://github.com/greiman/SdFat-bet....cpp#L308-L309 . IOMUXC_SW_PAD_CTL_PAD_PUS(1) means 47K ohm pullup. I can try IOMUXC_SW_PAD_CTL_PAD_PUS(3) for 22K ohm pullup.
    That is in the spot of code noted in p#14.

    Those "#if defined(ARDUINO_TEENSY41) " in "static void enableGPIO(bool enable) {" would preclude that from working on Teensy 4.0 with SDIO soldered on - but should use the same code?

  18. #18
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    Sorry too late here - almost midnight - have to work tomorrow.
    Again - this is a shot into the blue. I don't know if it is the problem - but for me, it seems not too unlikely.
    I can be totally wrong, of course.

    Good night.

  19. #19
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    I found the fix. Change
    Code:
    #if defined(ARDUINO_TEENSY41)
                                  IOMUXC_SW_PAD_CTL_PAD_DSE(1) |
    to
    Code:
    #if defined(ARDUINO_TEENSY41)
                                  IOMUXC_SW_PAD_CTL_PAD_DSE(6) |
    The SD -> PSRAM test case is passing reliably now. I will submit a pull request. Thanks for your suggestion to look in this area.

    PR is here: https://github.com/greiman/SdFat-beta/pull/66
    Last edited by jcj83429; 01-18-2021 at 05:11 AM. Reason: add PR link

  20. #20
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    Glad that you found it! Perfect!
    Those things are hard to find.

  21. #21
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Indeed that change makes this work in setup():
    Code:
    	while(runTest(1));
    So this need changed and also the :: "#if defined(ARDUINO_TEENSY41) "

    Should also include :: #if defined(ARDUINO_TEENSY40)

    It won't have PSRAM - but it will need to work when the SDIO pins are wired.

  22. #22
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    Agreed. It should be there for the 4.0, too.

  23. #23
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Added #ifdef note to the PR on the Greiman repository ... tested compile on T_4.1 - but not to run on T_4.0

  24. #24
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    @jcj: Can you do a pullrequest for your Opus addition to the Codecs? Thank you.

  25. #25
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,462
    Tested to work - Using a T_4.0 with loglow/TallDog T_4.0 board PCB to present SDIO pins to an SD socket.

    That does not have PSRAM - but with reduced BUFFER it will use processor memory instead when EXTRAM is requested!

    With this change to post #9 code above it does work on ALL 4 Variants presented to read from SD - just showing the BUILTIN_SDCARD on T_4.0 is usable!

    Code:
    #if defined(ARDUINO_TEENSY41)
    #define BUFSIZE (256*1024)
    #elif defined(ARDUINO_TEENSY40) 
    #define BUFSIZE (200*1024)
    #endif

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •