Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 20 of 20

Thread: Question on the correct usage of the SD Card on Teensy 4.1

  1. #1

    Question on the correct usage of the SD Card on Teensy 4.1

    Hi All,

    I have this RunCPM project which I build on the Teensy 3.5 and 3.6 using the SdFatSdio.
    This is what I done and worked since the beginning when I got the 3.5 and never changed it.
    However it doesn't seem to be working for the 4.1.
    On the 4.0 I used SdFat only, as I had the SD connected to the "Audio Shield Rev.D".
    I am using Greinman's SdFat library.
    Is the 4.1 not supported on Greinman's lib? Should I use SdFat for the 4.1 as well? Maybe change something in SdFat lib?
    Thanks in advance for any clue here.

    Thanks,
    Marcelo.

  2. #2

  3. #3
    Quote Originally Posted by manitou View Post
    Thank you.

    After reading more on the subject I found that the SdFat-beta seems to work for the 4.1 but break the 3.5 and 3.6.
    I might be wrong, but this is what I understood, and indeed using the beta hell broke loose here.
    So I will just wait for some time until a new version of SdFat comes out, before I provide 4.1 support on RunCPM.

    Thanks a lot,
    Marcelo.

  4. #4
    Senior Member
    Join Date
    Oct 2015
    Location
    Roma (IT, EU)
    Posts
    339
    Yes, this is very unfortunate.
    I have a lot of code, developed for T3.6, which uses "regular" SdFat with SdFatSdioEX objects.
    Now I can't use it with T4.1, because SdFat Beta does not provide SdFatSdioEX objects and "regular" SdFat does not support T4.1.

  5. #5
    Quote Originally Posted by XFer View Post
    Yes, this is very unfortunate.
    I have a lot of code, developed for T3.6, which uses "regular" SdFat with SdFatSdioEX objects.
    Now I can't use it with T4.1, because SdFat Beta does not provide SdFatSdioEX objects and "regular" SdFat does not support T4.1.
    Yes. I understand Greiman is overwhelmed, so I hope we do get a solution for this.

  6. #6
    Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    71
    The solution I've come up with is to rename the SdFat-beta library from SdFat to SdFat-beta: in library.properties change name=SdFat to name=SdFat-beta, rename src/SdFat.h to src/SdFat-beta.h, and change the library directory name to SdFat-beta. That way, I have both old SdFat library and the new SdFat-beta library available. Then you can do something like this:
    Code:
    #ifdef ARDUINO_TEENSY41
    #include <SdFat-beta.h>
    #else
    #include <StFat.h>
    #endif
    RunCPM with a Teensy 4.1 and working SDIO is... verrrry nice indeed.

  7. #7
    Quote Originally Posted by Silverlock View Post
    The solution I've come up with is to rename the SdFat-beta library from SdFat to SdFat-beta: in library.properties change name=SdFat to name=SdFat-beta, rename src/SdFat.h to src/SdFat-beta.h, and change the library directory name to SdFat-beta. That way, I have both old SdFat library and the new SdFat-beta library available. Then you can do something like this:
    Code:
    #ifdef ARDUINO_TEENSY41
    #include <SdFat-beta.h>
    #else
    #include <StFat.h>
    #endif
    RunCPM with a Teensy 4.1 and working SDIO is... verrrry nice indeed.
    Thanks .. this is what I thought about doing ... and I will probably do, but this adds some complication to newcomers, like having to download a lib, rename things, etc.
    How did you initialize the SD card? I do not use SdFatSdioEx.
    For the 3.5 and 3.6 I use SdFatSdio (is there an advantage on using SdFatSdioEx?)
    For the 3.5 and 3.6 I use simply sd.begin(), but for the 4.1 I am not sure what to use.

    Thanks,
    Marcelo.

  8. #8
    Senior Member
    Join Date
    Dec 2013
    Location
    East Stroudsburg PA.
    Posts
    285
    How did you initialize the SD card? I do not use SdFatSdioEx.
    in void setup() { }
    Code:
      if (!sd.begin(SdioConfig(FIFO_SDIO))) { // SdFat.h Ver 2.0.0 Beta
        Serial.println("m.SD initialization failed!");
      } else {
        Serial.println("m.SD initialization OK");
      }

  9. #9
    Cool, thanks.

    Also ... I am using this "dir_t" for reading directories. That seems to "not name a type" on the beta.
    No idea what it was replaced with.

  10. #10
    Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    71
    Quote Originally Posted by marcelodantas View Post
    Thanks .. this is what I thought about doing ... and I will probably do, but this adds some complication to newcomers, like having to download a lib, rename things, etc.
    How did you initialize the SD card? I do not use SdFatSdioEx.
    For the 3.5 and 3.6 I use SdFatSdio (is there an advantage on using SdFatSdioEx?)
    For the 3.5 and 3.6 I use simply sd.begin(), but for the 4.1 I am not sure what to use.
    For both the T4.0 and the T4.1, I used SdFat SD;. It worked on the T4.0 and I really never thought of playing with it when I switched over to the 4.1.

    In the SD.begin, I used SD.begin(SdioConfig(FIFO_SDIO)).

  11. #11
    Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    71
    Quote Originally Posted by marcelodantas View Post
    Cool, thanks.

    Also ... I am using this "dir_t" for reading directories. That seems to "not name a type" on the beta.
    No idea what it was replaced with.
    Oh right, forgot about all those internal renaming bits... One sec... dir_t became DirFat_t.

    There was also a function that went private (SD.vwd()) that was used in _sys_renamefile in abstraction_arduino.h. That had me going for a bit until I figured out that if (f.rename(SD.vwd(), (char*)newname)) { became if (f.rename((char*)newname)) {.

  12. #12
    Awesome!!! ... I will try all this tonight.
    I really hope 4.1 support gets migrated onto the standard SdFat. Would make things much easier.

  13. #13
    If you don't mind, can you zip the changes and send over? I did the changes above and am still getting some errors when compiling.
    I think I must not create SD as :
    SdFat SD;
    When using the 4.1?

  14. #14
    Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    71
    Awesome!!! ... I will try all this tonight.
    I think it took me about an hour of skullwork to get things migrated over to SdFat-beta before I got my T4.1 and plugged it in. The increase in speed is very, very noticeable.

    On the T4.0 with the uSD hooked up to SPI, it took 4m10s to assemble and link SYSLIB4.5.

    On the T4.1 with the onboard SDIO uSD, that dropped to 1m40s.

    And that's just using the SdFat class. Now that you've nudged my elbow, I may just have to look into SdFatSdio...

    I really hope 4.1 support gets migrated onto the standard SdFat. Would make things much easier.
    It would make things easier, but I'm not holding my breath. I don't see it happening; but I'd love to be proved wrong!

  15. #15
    Senior Member
    Join Date
    Dec 2013
    Location
    East Stroudsburg PA.
    Posts
    285
    Try this for a quick test:
    Code:
    //============================================================================
    // SdFat version 2.0.0 BETA ONLY
    //============================================================================
    #include <SdFat.h> // SdFat V "2.0.0"
    const char *SDFAT_ver = SD_FAT_VERSION;
    
    // Use built-in SD for SPI modes on Teensy 3.5/3.6.
    // Teensy 4.0 use first SPI port.
    // SDCARD_SS_PIN is defined for the built-in SD on some boards.
    #ifndef SDCARD_SS_PIN
    const uint8_t SD_CS_PIN = SS;
    #else  // SDCARD_SS_PIN
    // Assume built-in SD is used.
    const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
    #endif  // SDCARD_SS_PIN
    
    // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
    // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
    #define SD_FAT_TYPE 3
    
    SdFat sd; // SD
    // SdFat SD;
    
    // The file to be parsed.
    File m_pSource;
    
    const int DIR_max = 150; // [# of Directory - max]
    const int max_DIR_name_lenght = 100;
    char CURDIRname[max_DIR_name_lenght] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Elements with missing values will be initialized to 0;
    uint32_t DIRcount = 1; // COUNT of all DIRs on SD CARD
    char DIR_list_array[DIR_max][max_DIR_name_lenght]; // [# of DIRs max][max DIR name lenght];
    
    // uint32_t TOTAL_PMF_FILE_counter = 0;
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(38400); // Teensy ignores this and use full USB speed:  T3.x USB 1.1/Full-Speed: 12 Mbps, T4.x Hi-Speed: 480 Mbps.
      byte i = 0;
      while (!Serial && millis() < 5000) { // wait for Arduino Serial Monitor
      }
      if (!sd.begin(SdioConfig(FIFO_SDIO))) { // SdFat.h Ver 2.0.0 Beta
        Serial.println("m.SD initialization failed!");
      } else {
        Serial.println("m.SD initialization OK");
        LISTDIRs();
        m_pSource = sd.open("/"); // ROOT
        PrintFiles(m_pSource);
        m_pSource.close();
      }
    
    #if defined(SdFat_h)
      if (!strcmp("2.0.0", SDFAT_ver)) { // ver 2.0.0
        Serial.print( "SdFat version "), Serial.println( SD_FAT_VERSION );
      } else if ((SDFAT_ver[0] == '2') && (SDFAT_ver[1] == '.')) { // ver 2.
        Serial.println("Warning: MTP Library was only tested on SdFat Version 2.0.0 beta");
        Serial.print("SdFat Version currently installed "), Serial.println( SD_FAT_VERSION );
      } else { // ver 1
        Serial.print("Wrong SdFat Version "), Serial.println( SD_FAT_VERSION );
      }
    #endif
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    
    // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    //============================================================================
    //------------ LIST ALL DIRs ON SD CARD & SAVE IN DIR_list_array -------------
    //============================================================================
    void LISTDIRs() {
      Serial.println("\t**List Directories**");
      m_pSource = sd.open("/"); // ROOT
      char dirname[max_DIR_name_lenght]; // SDFAT // max_DIR_name_lenght
      if (m_pSource.isDirectory()) {
        strcpy(DIR_list_array[DIRcount], "/"); // array
    
        Serial.print("ROOT# ");
        Serial.print(DIRcount);
        Serial.print("\t");
        Serial.println(DIR_list_array[DIRcount]); // SDFAT LIB
        DIRcount++;
      }
      while (true) {
        File DIR = m_pSource.openNextFile();
    
        if (! DIR) {
          // no more files
          Serial.println("\t **no more Directories** ");
          DIR.close();
          break;
        }
        DIR.getName(dirname, sizeof(dirname));
        if (DIR.isDirectory()) {
          //DIRcount++;
          strcpy(DIR_list_array[DIRcount], dirname); // array
          strcat(DIR_list_array[DIRcount], "/");
          Serial.print("DIR# ");
          Serial.print(DIRcount);
          Serial.print("\t");
          Serial.println(DIR_list_array[DIRcount]); // SDFAT LIB
          DIRcount++;
        }
        DIR.close();
      }
      DIRcount --;
      Serial.print("\t **Directory count ");
      Serial.print(DIRcount), Serial.println(" **"), Serial.println();
      m_pSource.close();
    }
    //----------------------------------------------------------------------------
    
    //============================================================================
    // Print Files in Cur. Directory
    //============================================================================
    void PrintFiles(File dir) {
      Serial.println("\t**List Files in Cur. Directory**");
      char filename[max_DIR_name_lenght]; // SDFAT
    
      int len = strlen(filename);
      char *extension = filename + len - 4;
    
      while (true) {
    
        File entry = dir.openNextFile();
        if (! entry) {
          // no more files
          Serial.println("\t **no more files**");
          entry.close();
    
          // Serial.print("\t TOTAL PMF_FILE_counter: "), Serial.println(TOTAL_PMF_FILE_counter), Serial.println();
          break;
        }
        entry.getName(filename, sizeof(filename));
    
        if (entry.isDirectory()) {
          // skip
        } else {
          Serial.print(filename); // SDFAT LIB
          // files have sizes, directories do not
          Serial.print("       \t");
          Serial.print(entry.size(), DEC);
    
          Serial.print("\t dirIndex  "), Serial.println(entry.dirIndex());
    
          // PMF File Format counter
          /*
            len = strlen(filename);
            extension = filename + len - 4;
            if (!strcmp(".pmf", extension) || !strcmp(".PMF", extension)) {
            TOTAL_PMF_FILE_counter++;
            }
          */
        }
        entry.close();
      }
    }
    //----------------------------------------------------------------------------

  16. #16
    Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    71
    Quote Originally Posted by marcelodantas View Post
    If you don't mind, can you zip the changes and send over? I did the changes above and am still getting some errors when compiling.
    I think I must not create SD as :
    SdFat SD;
    When using the 4.1?
    Unfortunately, it's not that easy... I've done all this on my own "gone way out in left field" fork of RunCPM. ZCPR3.3, ZSDOS, serial and parallel port (yeah, it's me, mecparts).

    Let me start over with a current mainline copy and I'll get back to you. As I said, it only took me an hour to figure out the first time (and that included getting my SdFat extensions for setting file attributes and timestamps migrated to SdFat-beta), so it shouldn't take me too long.

  17. #17
    Quote Originally Posted by Silverlock View Post
    Unfortunately, it's not that easy... I've done all this on my own "gone way out in left field" fork of RunCPM. ZCPR3.3, ZSDOS, serial and parallel port (yeah, it's me, mecparts).

    Let me start over with a current mainline copy and I'll get back to you. As I said, it only took me an hour to figure out the first time (and that included getting my SdFat extensions for setting file attributes and timestamps migrated to SdFat-beta), so it shouldn't take me too long.
    Cool, thanks.
    I feel that I am really close. But it has been a long day so it is hard for me to concentrate.

  18. #18
    Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    71
    Quote Originally Posted by marcelodantas View Post
    Cool, thanks.
    I feel that I am really close. But it has been a long day so it is hard for me to concentrate.
    No trouble at all. I'd just finished a 22km bike ride before sitting down at the computer so my mind is fresh even if my knees are complaining.

    And right now, grabbing a couple extra 4.1s as soon as DigiKey had them in stock is about to pay off. I don't even need to disturb the "TeensyBoard/Z80".

  19. #19
    I got it to work.

    Looks like I will have to do a major cleanup, but I will probably upload a new version to GitHub soon.

    Thanks a lot for the tips.

  20. #20
    Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    71
    And I got my changes to work on the mainline code as well. If you want to check anything, I've pushed my changes to https://github.com/mecparts/RunCPM. It's up and running on one of the spare T4.1s. I'm just going to double check again a "clean but renamed" copy of SdFat-beta (i.e. without my file set attribute additions) but I don't expect any trouble.

    Edit: checked out okay with a "clean but renamed" copy of SdFat-beta.
    Last edited by Silverlock; 06-09-2020 at 01:58 AM.

Posting Permissions

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