Beginner's Guide to using the T3.6/T3.5 SD Card socket

Status
Not open for further replies.

TelephoneBill

Well-known member
The purpose of this post is to get a novice (like myself) quickly writing his/her own code using the T3.6/T3.5 built in SD Card peripheral, without having to read through a mountain of detail in various forum locations. (Note - There are lots of other forum posts to search on this topic if you want to dig deeper).

For maximum speed on read/writes, I illustrate use of the "SdFat" library created by Bill Greiman, rather than the traditional Arduino "SD" library. This requires a new library to be uploaded and included into the IDE, and this will be described further in this post. Inside this library, the author has provided a new "sd" class known as "SdFatSdioEX" - the class that is used in this example.

The SD Card socket on the Teensy 3.6 (and 3.5) is intended to work with a newer and faster "SDIO mode" of data transfer, rather than with the older/slower "SPI mode". It employs four parallel data lines, whereas the SPI mode used only one. It does NOT use any of the SPI interfaces shown on the pinout card, but relies on a direct SD I/O interface built into the K66 chip and directly wired to the socket. The T3.6 interface operates a little faster than the T3.5, but both are pretty rapid reaching speeds of the order of 20 MBytes/sec.

Below is a minimal code example for writing/reading data to/from a new file on an SD card. Ensure you have an SD card inserted before downloading the program. Open the "Serial Monitor" once loaded.

(Edit2 - see also post #5 for more features.)

Code:
//SD Card - Write/read/delete testing (v1.01)
//===========================================
//Date 08 OCT 2017
#include <SdFat.h>
#define USE_SDIO 1
const uint8_t SD_CHIP_SELECT = SS;

SdFatSdioEX sd;
SdFile myFile;
char fileName[] = "NoviceTest01.txt";
char KeyCode;
int FileData;

void setup() 
{
  Serial.begin(9600);
  while(!Serial);
  Serial.println("Enter 'w' key to write file data.");
  Serial.println("Enter 'r' key to read file content.");
  Serial.println("Enter 'd' key to delete file.");
}

void loop() 
{  
  if (Serial.available()>0) {
    KeyCode = Serial.read();
    sd.begin();
    if (KeyCode=='w') {
      if (!myFile.open(fileName, O_RDWR | O_CREAT | O_AT_END)) {
        Serial.println("Opening text file for write failed.");
      }
      else {
        myFile.println("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        myFile.close();
        Serial.println("...File written.");
      }
    } 
    if (KeyCode=='r') {
      if (!myFile.open(fileName, O_READ)) {
        Serial.println("Opening text file for read failed.");
      }
      else {
        while ((FileData = myFile.read()) >= 0) Serial.write(FileData);
        myFile.close();
      }
    } 
    if (KeyCode=='d') {
      if (!sd.remove(fileName)) {
        Serial.println("File delete failed.");
      }
      else {
        Serial.println("...File deleted.");  
      }
    } 
  } 
}

To install the "SdFat" Library...
1) In the IDE, select "Sketch" from the main menu.
2) Select "Include Library" and then "Manage Libraries...".
3) In the filter textbox (top right) of the Library Manager, type "SdFat".
4) Click on the entry for "SdFat" in the list box, Then click "Install".
5) Close the Library Manager once installed.

Edit1 - Removed the DISABLE_CHIP_SELECT line. Removed "sd.errorHalt" lines - stops sd working (replaced with Serial message). Included file "Delete".
Moved "sd.begin()" into main loop - allows card to be removed and re-inserted.
 
Last edited:
Frank - thanks for picking up what looks like a novice error. I commented out the DISABLE_CHIP_SELECT line and discovered the test program still works... but I'm unsure if that is what you were pointing out? Also discovered that by putting sd.begin() in the setup rather than the main loop that if the card is removed and then re-inserted it gives an error. Is it 'good practice' to repeatedly call sd.begin() in a loop? Or is there some "sd card removed" (or inserted) indicator to check for?

What I was trying to achieve was a simple 'intro' for novices (like myself) to be able to use the T3.6 socket without having to read a plethora of disjointed comments. I found it frustrating. Happy to edit if it can be improved?

Re. the SDIO interface - I found (as a novice) was very useful to know. I first wondered if SPI was involved (it seemed to be everywhere else I read).

Edit - Updated code now to v1.01.
 
Last edited:
I have problems always to use the Audio-Library together with Bill`s SdFat. So far I don't know a good way to use both libraries in a program.
The reason is, the Audio-Library #includes "SD.h" - and the waveplayer, for example, uses it.
But, maybe I'm missing something?

Edit: The only way I know is NOT to use Audio.h and to copy the needed Audio-Library-files to the project. There must be a better way ?
 
Last edited:
Some additional features of the SdFile object (called "myFile" in the above program) which may help novice users...

Note 1 - The list can be found here file:///C:/Users/YourName/Documents/Arduino/libraries/SdFat/extras/html/class_sd_file.html, however I found that not all the features listed were working. Those below have been tested.

Note 2 - When a file is opened there is an internal file pointer which points to the current position where data will be read from (or written to). This pointer can be manipluated in code. On opening a file, the pointer is reset to zero, so the first byte of data will be read from position 0.

myFile.seekSet(12) - this will place the pointer at position 12. Being a "zero based" pointer, it will point to the 13th data byte.
myFile.curPosition() - this will return an integer showing at which position the pointer is currently pointing.
myFile.rewind() - resets the pointer to the zero position.
myFile.seekCur(5) - this sets the pointer to 5 places further than the current position.
myFile.seekEnd(-4) - this sets the pointer to 4 places before the end of the file.
myFile.flush() - ensures any bytes in a buffer are written out to the file.
myFile.fileSize() - this returns the total number of bytes in the file.
myFile.printName() - this prints the file name to the Serial output device.
myFile.dirIndex() - this returns the index position of the file in its directory place. The first two places are ./ and ../ directories (in the root for example).
myFile.write(byte) - writes a single byte to the file.
myFile.write(stringPtr) - writes a string pointed at by stringPtr.
myFile.write(bufPtr, n) - writes n bytes from buffer pointed at by bufPtr.
myFile.read() - returns the next single byte to be read from file (current file pointer).
myFile.read(bufPtr, n) - returns n bytes into buffer pointed at by bufPtr.

also...

sd.ls() - lists the contents of the root directory to the Serial output device.
sd.ls(LS_R) - lists the contents, and all sub directories and files, to the Serial output device.
sd.ls("TestDir1") - lists the contents of the "TestDir1" directory to the Serial output device.
sd.mkdir("TestDir1") - creates a new directory called "TestDir1".
sd.rmdir("TestDir1") - removes a directory called "TestDir1", but only when empty.
 
I have problems always to use the Audio-Library together with Bill`s SdFat. So far I don't know a good way to use both libraries in a program.
The reason is, the Audio-Library #includes "SD.h" - and the waveplayer, for example, uses it.
But, maybe I'm missing something?

Edit: The only way I know is NOT to use Audio.h and to copy the needed Audio-Library-files to the project. There must be a better way ?

where I cannot control the buid (i.e. in Arduino), I do exactly that, Not using Audio.h and include the required files. Anyhow, I find Audio.h a terrible approach by including everything.
Also that Audio GUI includes files that are not used is annoying.
At a certain point one should know what one is doing, also in Arduino ecosystem.
But I accept that it is how it is.
 
Status
Not open for further replies.
Back
Top