Cannot access SD card after upgrading to Teensyduino 1.55 or 1.54.

Status
Not open for further replies.

khtos

Active member
I was working under Teensyduino 1.53 and was writing a program for teensy 4.1 that stored data on an SD card. Since I met some bugs under TD 1.53, I had to update to TD 1.55. But after the updating, the program stopped detecting the SD card inserted into the built-in slot. In the process of my attempts to figure out what was going wrong, I got to the point that I tried to compile a sketch from the "SD" library examples (C: \ Program Files (x86) \ Arduino \ hardware \ teensy \ avr \ libraries \ SD \ examples \ listfiles). And it does not detect the SD card. I ran this example on two teensy 4.1 with two different SD cards and always got the same result:
Code:
Port open
Initializing SD card ... initialization failed!
OK. Then I roll back to the Teensyduino 1.53 version, and compile just the same sketch, and flashed it into the Teensy board. Both Teensy boards began to see the SD cards.
OK. Then I updated the TD to the 1.55 version, again the cards are not visible. I rolled back to 1.53 again - everything works again. Then I checked TD 1.54 - SD cards are also not visible by the program.
So, the question is: what could be the reason for this behavior and what should I do to get access to the SD card under Teensyduino 1.55?
Here is the full text of the sketch that I wrote to the board for each version of Teensyduino:
Code:
/*
  SD card basic directory list example
 ....
 This example code is in the public domain.
 */
#include <SD.h>

// change this to match your SD shield or module;
// Teensy 3.5 & 3.6 & 4.1 on-board: BUILTIN_SDCARD
const int chipSelect = BUILTIN_SDCARD;

void setup()
{

  // Open serial communications and wait for port to open:
    Serial.begin(9600);
    while (!Serial) {
        ; // wait for serial port to connect.
    }

    Serial.print("Initializing SD card...");

    if (!SD.begin(chipSelect)) {
        Serial.println("initialization failed!");
        return;
    }
    Serial.println("initialization done.");

    File root = SD.open("/");

    printDirectory(root, 0);

    Serial.println("done!");
}

void loop()
{
  // nothing happens after setup finishes.
}

void printDirectory(File dir, int numSpaces) {
    while (true) {
        File entry = dir.openNextFile();
        if (!entry) {
          //Serial.println("** no more files **");
            break;
        }
        printSpaces(numSpaces);
        Serial.print(entry.name());
        if (entry.isDirectory()) {
            Serial.println("/");
            printDirectory(entry, numSpaces + 2);
        }
        else {
       // files have sizes, directories do not
            printSpaces(48 - numSpaces - strlen(entry.name()));
            Serial.print("  ");
            Serial.println(entry.size(), DEC);
        }
        entry.close();
    }
}

void printSpaces(int num) {
    for (int i = 0; i < num; i++) {
        Serial.print(" ");
    }
}
 
Guessing - With the new Teensyduino, SD now goes to SDFat which is a much more capable SD...

It would help if you looked at bottom, of your build on new stuff, where it may say something like:
Using SDFat from ... And see if it is coming from your Teensy install or from your <Arduino sketches>/libraries folder...
If from outside of Teensyduino, try removing the version out of the sketches and see if it works better.
 
here are the lines from the compiler output that are related to the libraries used:

Code:
Building libraries ...

Using library SD version 2.0.0 in folder "file:///C:/Program%20Files%20(x86)/Arduino/hardware/teensy/avr/libraries/SD"
....
Using library SdFat version 2.0.5-beta.1 in folder "file:///C:/Program%20Files%20(x86)/Arduino/hardware/teensy/avr/libraries/SdFat"
....
Using library SPI version 1.0 in folder "file:///C:/Program%20Files%20(x86)/Arduino/hardware/teensy/avr/libraries/SPI"
....

unfortunately, as you can see, all the libraries are taken from the folder /Arduino/hardware/teensy/avr/libraries/
 
@KurtE - does the "Fail" come form a debug print I haven't gotten removed on my WIP edits?

Running that code here results in a FAIL - but printed directory:
Code:
Initializing SD card...    [B]Fail[/B]
initialization done.
System Volume Information/
  WPSettings.dat                                  12
  IndexerVolumeGuid                               76
YouAreHere3.txt                                   90
Logic+Setup+2.3.39-master.xxx                     488003064
sixaxispairtoolsetup-0.3.1.xxx                    80751504
done!

Look at this example sketch : {local install}\hardware\teensy\avr\libraries\SD\examples\SdFat_Usage\SdFat_Usage.ino

That example using :
Code:
   // Access the built in SD card on Teensy 3.5, 3.6, 4.1 using FIFO
  ok = SD.sdfs.begin(SdioConfig(FIFO_SDIO));

Works with TD 1.56 Beta 2 here.

As does this example : C:\T_Drive\Arduino_1.8.16_155\hardware\teensy\avr\libraries\SD\examples\listfiles\listfiles.ino
> when edited to use :: BUILTIN_SDCARD
 
@KurtE - does the "Fail" come form a debug print I haven't gotten removed on my WIP edits?

Running that code here results in a FAIL - but printed directory:
Does not look like it... As his output shows the output from having the begin fail...

unfortunately, as you can see, all the libraries are taken from the folder /Arduino/hardware/teensy/avr/libraries/

Sorry I am not an expert on SD, I have been using it for some testing and the like with trying to get things like MTP and MSC to work.

Usually when I run into issues like this, I try a couple of things like:

a) Reformat the SDCard... - Maybe something is corrupt and old library did not detect it... Usually for this I use the program SDFormatter which reformats the SD to be compatible with the SD standards for cards...

b) I look into the code, and do things like add debug outputs after each call, to see where the failure is happening.

Good Luck
 
Could you explain one more time what should I try to do!
Here is, what I have done:
- uninstalled Arduino and installed it again (version 1.8.16),
- downloaded Teensyduino 1.56_beta2 (here https://www.pjrc.com/teensy/td_156-beta2/TeensyduinoInstall.exe) and installed it over Arduino
- opened example C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD\examples\SdFat_Usage\SdFat_Usage.ino and made change change:
Code:
const int chipSelect = BUILTIN_SDCARD;
and uncomented
Code:
ok = SD.sdfs.begin(SdioConfig(FIFO_SDIO));
- I tried all variants of the "SD.sdfs.begin" from the example
and commented "return" here
Code:
    if (!ok) {
        Serial.println("initialization failed!");
        //return;
    }

and I always get this result in the terminal:
Code:
Port open
Initializing SD card...initialization failed!
initialization done.

Print directory using SD functions

Print directory using SdFat ls() function

Writing to datalog.bin using SdFat functions
datalog.bin started with 0 bytes
  unable to preallocate this file
Reading to datalog.bin using SD functions
unable to open datalog.bin :(
I can read the SD card on the computer, and there are about 50 files and a couple of folders on it.
So, the standard examples don`t work on my hardware :(
unfortunately, I can't format the card right now, I will try it tomorrow, but maybe someone can suggest another solution?

the full list of the program:
Code:
#include <SD.h>

void setup()
{
  //Uncomment these lines for Teensy 3.x Audio Shield (Rev C)
  //SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
  //SPI.setSCK(14);  // Audio shield has SCK on pin 14

    Serial.begin(9600);
    while (!Serial); // wait for Arduino Serial Monitor

    Serial.print("Initializing SD card...");
    bool ok;
    const int chipSelect = BUILTIN_SDCARD;

    // Instead of the usual SD.begin(pin), you can access the underlying
    // SdFat library for much more control over how the SD card is
    // accessed.  Uncomment one of these, or craft your own if you wish
    // to use SdFat's many special features.

    // Faster SPI frequency.  16 MHz is default for longer / messy wiring.
    //ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(24)));

    // Very slow SPI frequency.  May be useful for hardware with slow buffers.
    //ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(4)));

    // SdFat offers DEDICATED_SPI optimation when no other SPI chips are
    // connected.  More CPU time is used and results may vary depending on
    // interrupts, but for many cases speed is much faster.
    //ok = SD.sdfs.begin(SdSpiConfig(chipSelect, DEDICATED_SPI, SD_SCK_MHZ(16)));

    // Access the built in SD card on Teensy 3.5, 3.6, 4.1 using FIFO
    ok = SD.sdfs.begin(SdioConfig(FIFO_SDIO));

    // Access the built in SD card on Teensy 3.5, 3.6, 4.1 using DMA (maybe faster)
    //ok = SD.sdfs.begin(SdioConfig(DMA_SDIO));

    if (!ok) {
        Serial.println("initialization failed!");
        //return;
    }
    Serial.println("initialization done.");
    Serial.println();

    // After the SD card is initialized, you can access is using the ordinary
    // SD library functions, regardless of whether it was initialized by
    // SD library SD.begin() or SdFat library SD.sdfs.begin().
    //
    Serial.println("Print directory using SD functions");
    File root = SD.open("/");
    while (true) {
        File entry = root.openNextFile();
        if (!entry) break; // no more files
        Serial.print(entry.name());
        if (entry.isDirectory()) {
            Serial.println("/");
        }
        else {
            printSpaces(40 - strlen(entry.name()));
            Serial.print("  ");
            Serial.println(entry.size(), DEC);
        }
        entry.close();
    }

    // You can also access the SD card with SdFat's functions
    //
    Serial.println();
    Serial.println("Print directory using SdFat ls() function");
    SD.sdfs.ls();

    // You can access files using SdFat which uses "FsFile" for open files
    // FsFile offers more capability than regular SD "File".  As shown in this
    // example, you can truncate tiles.  You can also pre-allocate a file on
    // the SD card (if it does not yet have any data, the reason we truncate
    // first).  Pre-allocation impoves the speed of writes within the already
    // allocated space while data logging or performing other small writes.
    //
    Serial.println();
    Serial.println("Writing to datalog.bin using SdFat functions");
    FsFile myfile = SD.sdfs.open("datalog.bin", O_WRITE | O_CREAT);
    unsigned int len = myfile.fileSize();
    Serial.print("datalog.bin started with ");
    Serial.print(len);
    Serial.println(" bytes");
    if (len > 0) {
      // reduce the file to zero if it already had data
        myfile.truncate();
    }
    if (myfile.preAllocate(40 * 1024 * 1024)) {
        Serial.print("  Allocate 40 megabytes for datalog.bin");
    }
    else {
        Serial.print("  unable to preallocate this file");
    }
    myfile.print("Just some test data written to the file (by SdFat functions)");
    myfile.write(0);
    myfile.close();

    // You can also use regular SD functions, even to access the same file.  Just
    // remember to close the SdFat FsFile before opening as a regular SD File.
    //
    Serial.println();
    Serial.println("Reading to datalog.bin using SD functions");
    File f = SD.open("datalog.bin");
    if (f) {
        char mybuffer[100];
        int index = 0;
        while (f.available()) {
            char c = f.read();
            mybuffer[index] = c;
            if (c == 0) break;  // end of string
            index = index + 1;
            if (index == 99) break; // buffer full
        }
        mybuffer[index] = 0;
        Serial.print("  Read from file: ");
        Serial.println(mybuffer);
    }
    else {
        Serial.println("unable to open datalog.bin :(");
    }
    f.close();

    // When mixing SD and SdFat file access, remember for writing that
    // SD defaults to appending if you open with FILE_WRITE.  You must
    // use FILE_WRITE_BEGIN if you wish to overwrite the file from the
    // start.  With SdFat, O_WRITE or O_RDWR starts overwriting from the
    // beginning.  You must add O_AT_END if you wish to appead.
}

void loop()
{
  // nothing happens after setup finishes.
}


void printSpaces(int num) {
    for (int i = 0; i < num; i++) {
        Serial.print(" ");
    }
}
 
my part b) from above...

So we know SD.begin() fails...
If we look into SD.h (in the libraries\SD\src) directory we see:
Code:
	bool begin(uint8_t csPin = 10) {
		cspin = csPin;
#ifdef __arm__
		FsDateTime::setCallback(dateTime);
#endif
#ifdef BUILTIN_SDCARD
		if (csPin == BUILTIN_SDCARD) {
			bool ret = sdfs.begin(SdioConfig(FIFO_SDIO));
			cardPreviouslyPresent = ret;
			return ret;
		}
So as you are passing in BUILTIN_SDCARD we know: sdfs.begin(SdioConfig(FIFO_SDIO))

is failing...

If we then look into SDFat directory (SdFat\src\SdFat.h)
We see:
Code:
 bool begin(SdioConfig sdioConfig) {
    return cardBegin(sdioConfig) && Vol::begin(m_card);
  }
So we know either cardBegin or Vol::begin fails... Which one....

So I might hack up this code to something like:
Code:
  bool begin(SdioConfig sdioConfig) {    
    if (!cardBegin(sdioConfig)) {
        Serial.println("Card begin failed");
        return false;
    }
    if (!Vol::begin(m_card)) {
        Serial.println("Vol::begin failed");
        return false;
    }
    return true;
  }

Warning typed on fly. so probably issues.... But then you see which one of these fail... Then knowing that I would go to that function and again aid in prints, to see what it does not like...
 
Last edited:
Could you explain one more time what should I try to do!
Here is, what I have done:
- uninstalled Arduino and installed it again (version 1.8.16),
- downloaded Teensyduino 1.56_beta2 (here https://www.pjrc.com/teensy/td_156-beta2/TeensyduinoInstall.exe) and installed it over Arduino
- opened example C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD\examples\SdFat_Usage\SdFat_Usage.ino and made change change:
...

The second example "listfiles.ino" works with change of : chipSelect = BUILTIN_SDCARD
>> This is the better example to test for your case.

The first example 'SdFat_Usage.ino' take a different edit - as it is using new functionality:

Comment the first "ok=..." there:
Code:
  // Faster SPI frequency.  16 MHz is default for longer / messy wiring.
  [B]//ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(24)));[/B]

and uncomment the one indicated:
Code:
  // Access the built in SD card on Teensy 3.5, 3.6, 4.1 using FIFO
  ok = SD.sdfs.begin(SdioConfig(FIFO_SDIO));

If the first "ok" line isn't commented it may break the .begin().
 
Can you tell us about the SD card you're using?

I suspect the newer version of SdFat might have a bug where it can't detect older pre-SDHC (all 2GB and smaller, some 4GB) cards. To matters even more complicated, there are actually 2 different types of smaller cards, without any externally visible way to tell them apart. The card info program gives that info... but only if the library can detect the hardware. Works in SPI mode...

It definitely works very well with 32, 64, 128GB and larger cards.
 
Thank you so much, Paul!
I used one old 2GB card and the other one was 16GB, both didn't work. Now I took out a 32GB card from the old phone and it works with the "SdFat_Usage" example!
 
SDcard.jpg
this is a 16Gb card, which doesn't work, I will try to format it tomorrow, and check if it will work.
 
Just curious, did that 16GB card work after reformatting?

So far I've not seen any SDHC cards which are incompatible with SdFat's SDIO, only the older pre-SDHC ones (usually less than 4GB).
 
Hello! Right now, that card works.
It didn't work, after formatting with built-in windows formatter. I tried fast and full formatting in FAT32 and exFAT and it give no result. The card was readable and writable in windows, but teensy didn't see it. But, after formatting the card into FAT32 with SDFormatter, advised by KurtE, it started to work. And after the SD card started to work I tried to reformat it with windows formatter and it still works with teensy without any noticeable problem.
Thank you for the help once more!
 
Status
Not open for further replies.
Back
Top