De-Initialize SD Card with Teensy 4.1 SD library?

Svarun123

Member
I'm using a Teensy 4.1 microcontroller for a project that involves saving some data to a series of SD cards.
I'm programming my Teensy 4.1 with the Arduino IDE v2.3.8 and Teensyduino v1.60.

While I am able to use the basic "SD.h" Teensyduino library in order to open & save data to an SD card in the in-built SD card reader onboard the Teensy 4.1, I am curious whether it is possible to de-initialize an SD card once it's been initialized with "SD.begin". I'm looking specifically for something that would disable the SPI bus the SD card uses.

It appears to me that Teensyduino's SD library is a wrapper for SdFat. In that library, there is an end function, which should effectively de-initialize a previously-initialized SD card.

However, it appears that using the lower-level classes that the Teensyduino SD library implements from SdFat doesn't quite work with a Teensy 4.1.
For instance, attempting to run the following basic example code that uses the `SdFat` and `FsFile` classes:

C++:
#include <SD.h>

SdFat sd;
FsFile file;

void setup()
{
  Serial.begin(9600);

  while (!sd.begin(BUILTIN_SDCARD))
  {
    Serial.println("unable to find SD card!");
    delay(500);
  }
}

void loop()
{
  file = sd.open("test.txt", FILE_WRITE);
  file.println("test");
  file.flush();
  file.close();
  sd.end();

  while (true)
  {
    delay(500);
    Serial.println("done");
  }
}

Just fails to initialize any SD card I put in the in-built SD card slot. If I try to use the SdFat library from the Arduino library manager, I get errors stating that I should only be using the Teensyduino SD library exclusively. I've tried formatting my SD cards to the "Fat32" and "ExFat" formats, to no avail.

Is there a way to programatically de-initialize an SD card on a Teensy 4.1 microcontroller, with the Teensyduino SD library? Has this ever been attempted before? Assuming it's possible, is it also possible to subsequently re-initialize the same or a different SD card with the same SD class?

If not, is there a way I could use the base SdFat class on a Teensy 4.1 instead of the Teensyduino SD library?

Thanks for your time, any guidance is appreciated.
 
Last edited:
Use the SD.sdfs object to access the underlying SdFat class. Use the end() method on that class to close the volume.

Thank you for your reply;

I changed my test code as such:

C++:
#include <SD.h>
FsFile file;

void setup()
{
  Serial.begin(9600);

  while (!SD.sdfs.begin(BUILTIN_SDCARD))
  {
    Serial.println("unable to find SD card!");
    delay(500);
  }
}

void loop()
{
  file = SD.sdfs.open("test.txt", FILE_WRITE);
  file.println("test");
  file.flush();
  file.close();
  SD.sdfs.end();

  while (true)
  {
    delay(500);
    Serial.println("done");
  }
}

Unfortunately, it still appears that I cannot initialize any SD cards with the "SD.sfds" class.

Another thing I noticed is that, if I plug my SD card in after I start the Teensy & while the initialization loop in "begin" is running, my Teensy resets...

Anything else I could try? Should I be supplying some additional parameters to the "begin" function here, or should I be formatting my SD cards in a specific manner? I'm only using 32GB micro SD cards here.
 
This can't possibly work!

Code:
  while (!SD.sdfs.begin(BUILTIN_SDCARD))

You can only use BUILTIN_SDCARD with the SD.begin() function.

If you want to use SdFat's begin(), you must use the more complex syntax SdFat provides. In Arduino IDE, click File > Examples > SD > SdFat_Usage for examples of the valid syntax usable with SD.sdfs.begin().
 
Last edited:
While this doesn't give you the SD.end() function you wanted, Teensy's SD library does have a SD.mediaPresent() function which is meant to detect the removal of a card and perform re-initialization upon insertion of a new card.

Here's a quick example to show how it works.

Code:
#include <SD.h>

unsigned int count = 0;

void setup() {
  Serial.begin(9600);
  if (SD.begin(BUILTIN_SDCARD)) {
    Serial.println("SD card present at begin");
  } else {
    Serial.println("no SD card found at begin");
  }
}

void loop() {
  count = count + 1;
  Serial.print("count = ");
  Serial.print(count);
  Serial.print(":  ");
  if (SD.mediaPresent()) {
    Serial.println("SD card is present");
    File f = SD.open("test.txt", FILE_WRITE); // appends unless FILE_WRITE_BEGIN
    if (f) {
      f.print("test ");
      f.println(count);
      f.flush();
      f.close();
    } else {
      Serial.println(" error appendint to test.txt");
    }
  } else {
    Serial.println("SD card absent");
  }
  delay(2500);
}
 
You can only use BUILTIN_SDCARD with the SD.begin() function.
It works with Teensy 3, so I have sent a PR to fix it for T4.
It does appear that it's intended to work:
Code:
template <class Vol, class Fmt>
class SdBase : public Vol {
 public:
  //----------------------------------------------------------------------------
  /** Initialize SD card and file system.
   *
   * \param[in] csPin SD card chip select pin.
   * \return true for success or false for failure.
   */
  bool begin(SdCsPin_t csPin = SS) {
#ifdef BUILTIN_SDCARD
    if (csPin == BUILTIN_SDCARD) {
      return begin(SdioConfig(FIFO_SDIO));
    }
#endif  // BUILTIN_SDCARD
    return begin(SdSpiConfig(csPin, SHARED_SPI));
  }
otherwise there is no point for the BUILTIN_SDCARD case to be there.
 
Thank you for all your guys' replies, I really appreciate all the support.

After tinkering around on my own for a while, I managed to get the following setup to work for me:

C++:
#include <SD.h>

#define SD_CONFIG SdioConfig(FIFO_SDIO)

FsFile file;

void setup()
{
  Serial.begin(9600);

  while (!SD.sdfs.begin(SD_CONFIG))
  {
    Serial.println("unable to find SD card!");
    delay(500);
  }
}

void loop()
{
  file = SD.sdfs.open("test.txt", O_WRITE | O_CREAT | O_TRUNC);
  file.println("test");
  file.flush();
  file.close();
  SD.sdfs.end();

  while (true)
  {
    delay(500);
    Serial.println("done");
  }
}

With the basic test setup above verifying the basics, I was able to use SdFat with the "SD.sdfs" class to programatically initializie & de-initialize my SD cards. I'm even able to re-initialize the same SD card multiple times and write to it.

Albeit, I'm still not entirely 100% sure whether "SD.sdfs.end" actually disables the internal SPI mechanics, I'll investigate some more at a later time.
 
Last edited:
The following may (or may not) be related:
while a SPI interface has the possibility to 'shut-down' the microSD card (I needed this to save power) unfortunately the sdio interface to the microSD card (Teensy4.1) has no possibility (at least I could not find one) to tell the microSD card that it not used anymore ( that is, to end all operations)
 
All SD cards support 2 completely different communication protocols.

SPI uses 4 signals and supports 1 data pin at a maximum of 25 MHz. Most microcontrollers use SPI mode, and Teensy can if you connect a SD card to any of its SPI ports. The SPI mode is relatively simple.

SDIO (or just SD) uses 6 signals and supports 4 data pins at a maximum of 50 MHz (with 3.3V signals). The built in SD socket on Teensy 4.1, and also Teensy 3.5 and Teensy 3.6, uses 6-signal SDIO protocol. SDIO mode is quite a complex protocol with many features meant for higher performance.

When you view SD card pinout info, 2 sets of signal names are given because the card can operate in 2 completely different communication protocols where the pins have different functionality.

1772453146888.png

In these pinouts, you'll notice 4 of the signals are DAT0, DAT1, DAT2, DAT3 because it really does transfer 4 bits in parallel. This most is not SPI.
 
Got it, thank you for describing this in detail.

Do you know whether the "SD.sdfs.end" function stops the SDIO protocol once called on a Teensy 4.1, including ceasing all involved clocks?
The project I'm working on requires a lot of very sensitive analog circuitry, and I'm trying to remove as many sources of noise within my system as possible.
 
including ceasing all involved clocks?

Well that's pretty easy to answer: no, or probably not.

Quick search for "CCM_CCGR6" in all the SdFat files finds only 1 place, in src/SdCard/SdioTeensy.cpp at line 362.

Code:
  /* Enable USDHC clock. */
  CCM_CCGR6 |= CCM_CCGR6_USDHC1(CCM_CCGR_ON);

Unless I've missed something done in a very tricky way (this was just a quick text search for only "CCM_CCGR6"), no other code seems to ever turn off the CCM_CCGR6_USDHC1 clock enable bits.
 
Back
Top