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

Thread: Problem reading from SD card directly into PSRAM

  1. #26
    Senior Member
    Join Date
    Nov 2012
    Posts
    296
    You need to test any driver mod with files of at least 8 GiB on the popular SD cards from Samsung, Sandisk and the new Kingston Canvas Plus. I also test on older cards. You need to use a variety of write patterns then test read. Modern cards change read timing, buffering and cache use depending on how the card was was written.

    The Kingston Canvas cards mark regions by the type access that is expected, that's why this card is popular with Raspberry PI users, random read access to small OS files is good.

    I will soon be releasing a new version of the Teensy driver that makes major changes to the SD access pattern. It allows overlap of sending to the SD card with program execution by filling the SDIO FIFO and returning while the data is sent to the SD.

    These new cards pull lots of current when they program flash since pages are extremely large on big cards, The SD spec now allows Record Units to be up to 512 KiB so I now test on 256GB and soon 512GB cards.
    Last edited by Bill Greiman; 01-18-2021 at 11:58 AM.

  2. #27
    Senior Member
    Join Date
    Nov 2012
    Posts
    296
    Could you tell me what driver strength mods you think would work and I will include them in my tests. I have a number of Tennsy 4.1 and 3.6 boards running tests on my new Teensy driver mods.

    I am in the process of adding new SDIO drivers to SdFat so I will be going to standard base class for SDIO drivers.

  3. #28
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    For 4.1, please use 7. 6 also works in my test but 7 is probably safer.

    I don't know if any change is needed for 3.6.

  4. #29
    Senior Member
    Join Date
    Nov 2012
    Posts
    296
    I am testing with 7 for the soon, I hope, release of the next beta. I have had lots of setbacks with fixes for cards that are very popular.

    I am feeling good about mods to the Teensy driver. On Teensy 4.1 busy test plus overlap of SDIO bus activity with program execution means this statement executes in no more than 11 usec.
    Code:
      // The first sector puts the controller in write mode and takes about
      // 11 usec on a Teensy 4.1. About 5 usec is required to write a sector
      // when the controller is in write mode.
      if (!file.isBusy()) {
        if (512 != file.write(buf, 512)) {
          // Handle write error.
        }
      }
    This allows simple high speed data loggers with use of a new ring buffer class in the beta.

  5. #30
    Senior Member
    Join Date
    Nov 2012
    Posts
    296
    I set the drive strength to 7 and looked at the SD CLK signal with a SD sniffer board. It is really being driven. The noise I made with scope probes only caused a data error once.

    I suspect the error occurred when I probed the CMD line and the error appeared in the command response when Teensy was reading, not driving CMD.

    I tested with lots of SD cards and all seems OK.

  6. #31
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,501
    With this edit in ...\hardware\teensy\avr\libraries\SdFat\src\SdCard \SdioTeensy.cpp:
    Code:
    static void enableGPIO(bool enable) {
      const uint32_t CLOCK_MASK = IOMUXC_SW_PAD_CTL_PAD_PKE |
    #if defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY40) 
                                  IOMUXC_SW_PAD_CTL_PAD_DSE(7) |
    I ran code below on a T_4.1 and T_4.0 ( using TallDog PCB to present SDIO to SD card - with no PSRAM - defaults to chip RAM ).

    SD card is New 32GB 'Team'. Added Timing and throughput notes to prior code:
    Code:
    running variant 1
    reads succeeded 2299501 bytes in 100268 us at 22.933548 MB/sec
    1: SD -> PSRAM
    2: SD -> ITCM
    running variant 2
    reads succeeded 2299501 bytes in 100266 us at 22.934006 MB/sec
    <edit> : one edit to the code is enter 'a' to repeat the following 'variant' 10 times in a row > like "a1"

    Edit of prior code that showed failure with lower DSE() on PSRAM buffer read: : Using TD 1.54 b5 with SD.h mapped to Sd Fat
    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
    
    #if defined(ARDUINO_TEENSY41)
    #define BUFSIZE (256*1024)
    #elif defined(ARDUINO_TEENSY40)
    #define BUFSIZE (200*1024)
    #endif
    #define FILENAME "TESTFILE.BIN"
    
    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;
    	uint32_t rTime = micros();
    	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);
    			}
    		}
    	}
    	rTime = micros() - rTime;
    	Serial.printf("reads succeeded %lu bytes in %lu us at %f MB/sec\n", total_bytes_read, rTime, (float)total_bytes_read/rTime );
    	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
    #if 0
    	uint32_t lCnt = 0;
    	while (runTest(1)) {
    		lCnt++;
    		if ( !(lCnt % 10) ) Serial.printf("\t%lu\t", lCnt );
    	}
    #endif
    }
    
    void loop() {
    	int repeats = 1;
    	// 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 == 'a') {
    			repeats = 10;
    		}
    		if (c >= '1' && c <= '4') {
    			variant = c - '0';
    		}
    	}
    	while ( repeats > 0 ) {
    		runTest(variant);
    		repeats--;
    	}
    }
    Last edited by defragster; 01-19-2021 at 08:46 PM.

  7. #32
    Senior Member
    Join Date
    Nov 2012
    Posts
    296
    I posted a new version of SdFat-beta with the drive strength mod. It also has two examples that demonstrate new features in the Teensy SDIO driver.

    Try the TeensyDmaAdcLogger and TeensySdioLogger examples.

  8. #33
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,501
    @Bill Greiman - is there a feel for the coincidence of the 2.0.5 b1 timeline being weeks away from release that might coincide with TD 1.54 for use as SD.h ? ... both of course being unknown? Or is the new sdFat beta known to be farther out from release?

    Added a quick variant #5/6 to the prior posted code where #5 just adds 5MB to the file and #6 removes the file then writes 5MB writing from PSRAM when available.
    Here on a T_4.1 with PSRAM:
    Code:
    running Write variant 5
    write succeeded 5242880 bytes in 270332 us at 19.394226 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 270351 us at 19.392864 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 274697 us at 19.086048 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 272272 us at 19.256039 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 445823 us at 11.760003 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 508780 us at 10.304808 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 522286 us at 10.038331 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 367491 us at 14.266689 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 380814 us at 13.767561 MB/sec
    running Write variant 5
    write succeeded 5242880 bytes in 390015 us at 13.442765 MB/sec
    Select test variant
    1: SD -> PSRAM
    2: SD -> ITCM
    3: SD -> ITCM, ITCM -> PSRAM
    4: SD -> ITCM, ITCM -> PSRAM with cache flush
    5: WRITE PSRAM -> SD
    6: delete> WRITE PSRAM -> SD
    running variant 1
    reads succeeded 57671680 bytes in 2511907 us at 22.959322 MB/sec

  9. #34
    Senior Member
    Join Date
    Nov 2012
    Posts
    296
    Release of SdFat is not related to Teensy. I like playing with Teensy but the overwhelming number of users are on other boards. Most of the mods in 2.0.5 will be for other systems.

    I will be adding more support for STM32, STM32 is becoming more popular since ST now has an official Arduino board support package that supports many STM32 chips. I hate trying to find problems in STM32Cube it is the typical big company corporate army built software.

    I mainly use STM32 for my projects but using the native ChibiOS RTOS, not Arduino. ChibiOS has great STM32 driver support for the multi-threaded RTOS environment.

  10. #35
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,501
    Quote Originally Posted by Bill Greiman View Post
    Release of SdFat is not related to Teensy. ...
    Thought so - but had to ask if is was near done and might line up with TD 1.54 now it is incorporated for awesome improvement - those write rates in P#33 are better than the old SD read rates.

    I've had the SdFat Beta here and seeing it release to 2.0 and go into SD.h was a very nice change.

    Seems PJRC will need to fork a copy to make Teensy specific changes like the DSE(7)

  11. #36
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    @Bill Greiman Thank you!

  12. #37
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,501
    Quote Originally Posted by defragster View Post
    Thought so - but had to ask if is was near done and might line up with TD 1.54 now it is incorporated for awesome improvement - those write rates in P#33 are better than the old SD read rates.

    I've had the SdFat Beta here and seeing it release to 2.0 and go into SD.h was a very nice change.

    Seems PJRC will need to fork a copy to make Teensy specific changes like the DSE(7)
    @Paul - this is the PSRAM issue that exists in SdFat v2.0 that had a fix pushed into new SdFatBeta V2.0.5

    V2.0.5 :: github.com/greiman/SdFat-beta/blob/master/src/SdCard/SdioTeensy.cpp#L320

    versus:

    V2.0 :: github.com/greiman/SdFat/blob/master/src/SdCard/SdioTeensy.cpp#L287

  13. #38
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,785
    Ok, I'm pulling 2.0.5 into 1.54-beta6...

  14. #39
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,501
    Quote Originally Posted by PaulStoffregen View Post
    Ok, I'm pulling 2.0.5 into 1.54-beta6...
    Your call - wasn't sure if you'd fork the V_2.0 and do a PJRC edit for just that issue?

    No idea what changes from V_2.0 to Beta 2.0.5 so far other than that DSE() edit? But of course the Beta has this obligatory status note:
    "Warning: This version, 2.0.5-beta.1, has many internal changes so may be unstable."

  15. #40
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,501
    Tested this to work with TD 1.54 Beta 6.

    Using this updated code with more variants and 'a' 10X repeat:
    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
    
    #if defined(ARDUINO_TEENSY41)
    #define BUFSIZE (256*1024)
    #elif defined(ARDUINO_TEENSY40)
    #define BUFSIZE (200*1024)
    #endif
    #define FILENAME "TESTFILE.BIN"
    #define FILENAME2 "TESTFILE.BIN"
    
    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;
    	uint32_t rTime = micros();
    	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);
    			}
    		}
    	}
    	rTime = micros() - rTime;
    	Serial.printf("reads succeeded %lu bytes in %lu us at %f MB/sec\n", total_bytes_read, rTime, (float)total_bytes_read / rTime );
    	file.close();
    	return true;
    }
    
    bool writeTest(int variant) {
    	Serial.print("running Write variant ");
    	Serial.println(variant);
    	if (variant == 5) {
    		file = SD.open(FILENAME2, FILE_WRITE);
    	}
    	else {
    		if (SD.exists(FILENAME2))
    			SD.remove(FILENAME2);
    		file = SD.open(FILENAME2, FILE_WRITE);
    	}
    
    	if (!file) {
    		Serial.println("file open failed");
    		return false;
    	}
    	int total_bytes_written = 0;
    	int bytes2Write = 5 * 1024 * 1024;
    	uint32_t rTime = micros();
    	while (total_bytes_written < bytes2Write) {
    		int bytes_read;
    		if (variant == 5) {
    			bytes_read = file.write(psramBuf, BUFSIZE);
    		} else {
    			bytes_read = file.write(itcmBuf, BUFSIZE);
    		}
    
    		if (bytes_read < 0) {
    			Serial.print("write failed after ");
    			Serial.print(total_bytes_written);
    			Serial.println(" bytes");
    			file.close();
    			return false;
    		} else {
    			//Serial.println("read ok");
    			total_bytes_written += bytes_read;
    		}
    
    		if (variant == 3 || variant == 4) {
    			memcpy(psramBuf, itcmBuf, BUFSIZE);
    			if (variant == 4) {
    				arm_dcache_flush_delete(psramBuf, BUFSIZE);
    			}
    		}
    	}
    	rTime = micros() - rTime;
    	Serial.printf("write succeeded %lu bytes in %lu us at %f MB/sec\n", total_bytes_written, rTime, (float)total_bytes_written / rTime );
    	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
    #if 0
    	uint32_t lCnt = 0;
    	while (runTest(1)) {
    		lCnt++;
    		if ( !(lCnt % 10) ) Serial.printf("\t%lu\t", lCnt );
    	}
    #endif
    }
    
    void loop() {
    	int repeats = 1;
    	// put your main code here, to run repeatedly:
    	Serial.println("Select test variant ('a#' repeats 10 times)");
    	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");
    	Serial.println("5: WRITE PSRAM -> SD");
    	Serial.println("6: delete> WRITE PSRAM -> SD");
    	int variant = 0;
    	while (variant == 0) {
    		while (!Serial.available());
    		char c = Serial.read();
    		if (c == 'a') {
    			repeats = 10;
    		}
    		if (c >= '1' && c <= '6') {
    			variant = c - '0';
    		}
    	}
    	while ( repeats > 0 ) {
    		if ( variant <= 4 )
    			runTest(variant);
    		else
    			writeTest(variant);
    		repeats--;
    	}
    }

Posting Permissions

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