SdFat SDIO for Teensy 4.0

do you mean CPU clock at 150MHz?

Yes. Set in the IDE - edited to show F_CPU_ACTUAL in setup {also print __FILE__ so I know what the sketch will do when I type 'Any' char}:
Code:
Use a freshly formatted SD for best performance.
Sketch is :T:\TEMP\arduino_modified_sketch_197682\bench.ino
	 [COLOR="#FF0000"][B]F_CPU=151200000[/B][/COLOR]
Type any character to start
FreeStack: 441608
Type is FAT32
Card size: 31.91 GB (GB = 1E9 bytes)

Manufacturer ID: 0X3
OEM ID: SD
Product: SU32G
Version: 8.0
Serial number: 0XAC3E2E1C
Manufacturing date: 9/2012

[B][COLOR="#FF0000"]error: open failed
SdError: 0X23,0X1[/COLOR][/B]

Should have presented that as the SdError may be useful - though should repro. Wondering if a CLOCK isn't set right?

Also fails at 24 MHz - a bit earlier on begin():
Code:
Sketch is :T:\TEMP\arduino_modified_sketch_69952\bench.ino
	 F_CPU=24000000
Type any character to start
FreeStack: 441608
begin() failed
Do not reformat the SD.
SdError: 0X17,0X1
 
Yes. Set in the IDE - edited to show F_CPU_ACTUAL in setup {also print __FILE__ so I know what the sketch will do when I type 'Any' char}:
I ask as I run T4 +AudioCard-uSD (spi) + sdfat-beta at 24 MHz CPU clock without problems (I think)
so issue may be with SDIO clock generation
 
Greiman, with the SdFat-beta library: Is it possible to generate in the serial monitor a list of the files contained in a folder inside any microSD card installed in the Teensy 4?.

Will you have an example?

Thank you for making the SdFat library compatible with teensy 4. We have been able to use your library for handling .avi, .jpg, .jpeg files stored on a microSD card connected in SDIO; by a profound modification in the gameduino library 23x.
 
Will you have an example?
Here is what I have you can probably modify it to suit your needs.

Code:
#include <SdFat.h> // SdFat V "2.0.0"

SdFat SD;
File m_pSource;

const int DIR_max = 250; // [# of Directory - max]
const int max_DIR_name_lenght = 255;
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];

//============================================================================
//------------                    setup()                        -------------
//============================================================================
void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  while (!Serial && millis() < 15000) {}  // wait for Serial Monitor with 15sec. timeout.

#if defined(SdFat_h)
  Serial.print( "SdFat version "), Serial.println( SD_FAT_VERSION ), Serial.println("");
#elif defined(__SD_H__)
  Serial.println( "SD - a slightly more friendly wrapper for sdfatlib"), Serial.println("");
#endif

  if (!SD.begin(SdioConfig(FIFO_SDIO))) { // SdFat.h Ver 2.0.0 Beta only...
    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();
}
//----------------------------------------------------------------------------

//============================================================================
//------------                    loop()                        -------------
//============================================================================
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
  while (true) {

    File entry = dir.openNextFile();
    if (! entry) {
      // no more files
      Serial.println("\t **no more files**"), Serial.println();
      break;
    }
    entry.getName(filename, sizeof(filename));

    if (entry.isDirectory()) {
      //Serial.println(" / ");
      //printDirectory(entry, numTabs + 1);
    } else {
      Serial.print(filename); // SDFAT LIB
      // files have sizes, directories do not
      Serial.print("       \t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}
//----------------------------------------------------------------------------
 
Thanks so much to Bill Greiman for this library - SDIO on T3 amazing - before I found it 20Mb/sec read from SD was the stuff of mad man's dreams!

Do anyone know for sure if this uses SPI when it in SDIO mode or it all handled with bit banging across the four data lines?
I need to use the SPI bus for shift register filling and need to change speed and data direction (to LSB first).
I know changing settings may conflict if SPI already in use.

Thanks

Dave
 
Thanks so much to Bill Greiman for this library - SDIO on T3 amazing - before I found it 20Mb/sec read from SD was the stuff of mad man's dreams!

Do anyone know for sure if this uses SPI when it in SDIO mode or it all handled with bit banging across the four data lines?
I need to use the SPI bus for shift register filling and need to change speed and data direction (to LSB first).
I know changing settings may conflict if SPI already in use.

Thanks

Dave

It uses native SDIO driver of T3.5/6, T4.0 (no SPI or bitbanging)
 
Hi Bill
In the old SDFat library there was a class called FatFileSystem. In trying to convert some old sketches what would the equivalent be or is there one? Example of challenge:
Code:
typedef FatFileSystem vfs_t;

any pointers would help. Thanks in advance.
 
Finally got a T4 to run the bench.ino and TeensySdioDemo.ino using SdFat v2 on a breadboard! Thought I'd post how, for anyone struggling to do the same:

I used blackketter's board from OSH:

https://oshpark.com/shared_projects/tZbsjC0v

The soldering is very delicate and requires preparation of the breakout board to carefully remove all foil flaps around the castellated copper using fine tweesers. This needs to be done with a microscope to ensure that there are no fine fragments shorting to an adjacent hole. It is well worth checking that there is no conductivity between any of the SDIO pins before proceeding any further.
castellation.jpg

I used solder flux for my first board, but this ran between the breakout and the Teensy boards and increased the conductivity between adjacent pins. This board never worked that well. I could get it to run SD.h examples but none of the SdFat examples.

For my second attempt, I prepared the surfaces carefully using a flux pen, taking care not use excess. I directly soldered each pin carefully and then checked the resistance between the 3v3 and the pins of interest. They should all be above 1M Ohm.

I tried connecting to different boards. The Adafruit SD Board worked great with Arduino Uno and Seeeduino Xiao. I see the Xiao being used as a serial data logger in combo with one of the SD breakout boards.

For the Teensy 4.0, I used the Pololu microSD Breakout and the Waveshare Micro SD Board.
Pololu_Micro_SD_T.pngPololu_Micro_SD.jpgWaveshare_Micro_SD.jpg

For breadboard use, I favoured the Waveshare board with its single row of pins and visible labels (always nice to sanity check you wiring on the board itself). Although, the Pololu board may stack nicely (above the T4) into the female headers of the T4 breakout board.
Sdio_Breadboard.jpgsdio_board.jpg

Next, with the SdFat lib (v2) in the <arduino>/libraries folder, I ran the bench and TeensySdioDemo examples (without modification).

Code:
FILE_SIZE_MB = 5
BUF_SIZE = 512 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
10309.28,9846,22,49
10266.94,9300,22,49

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
22522.52,480,22,22
22522.52,480,22,22

The next step will be to build the stackable version...
 
Last edited:
I used the Pololu to build the stackable SD module, placing a 0.1µF cap between GND and 3v3.

sd_stack.jpg

The example TeensySdioDemo.ino works for both SDIO options 1 and 2, but the SPI options 3 and 4 fail:

Code:
Type '1' for FIFO SDIO
     '2' for DMA SDIO
     '3' for Dedicated SPI
     '4' for Shared SPI
Error: begin failed
SD_CARD_ERROR_CMD0, ErrorData: 0XFF

I presume the error is because SdFat isn't configured to use SPI over the SDIO pins AND the SD module (Pololu) isn't built to read SPI data.
 
I presume the error is because SdFat isn't configured to use SPI over the SDIO pins AND the SD module (Pololu) isn't built to read SPI data.
The adapter is capable of both protocols and SdFat uses SPI library, so you have to configure SPI library first before initiating SdFat.
You are using T4 and I'm not sure if there is a SPI overlaid to SDIO (as it is with T3.6), but reading the PinMux table in the IMXRT1062 documentation you may figure out and adapt SPI to these pins or adapt code.
 
Is there a recommended approach to use SdFat along with existing newlib stdio functions? I was able to get SdFat to work by renaming all of the classes and members to something other than the stdio equivalents, but this creates other problems for classes using stdio types...
 
Because I didn't know any better, I have also done the hack of renaming all the classes. What a pain! There has to be a smarter way!

I'm very interested to hear how other people have dealt with this problem.

Chip
 
Hello all! I am trying to rid my system of clicks and pops when loading multiple WAVs, several people have mentioned the issues with SD.h so I am trying sdfat on T4. SdFormatter, SdInfo and TeensySdioDemo are all working well! I can even get one wav playing using my own code and its seems the dropouts when a single wav is triggered repeatedly are much improved. Sadly when I try and trigger 4 wavs at the same time, although they play I loose control of the system at the serial window until they have finished playing. If I trigger two wavs at the same time, I can retrigger a couple of times and then I loose control. I also have the cash register sound that I can trigger as it is handy for debug.

Here is the code... (super lean to keep it simple)

Code:
#define USE_SdFat_ // uncomment for SdFat.h, comment for SD.h lib.
#include "SdFat.h"
SdFat sd;

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioPlayMemory          sound0;         //xy=257,200
AudioPlaySdWav           playSdWav2;     //xy=296,375
AudioPlaySdWav           playSdWav3;     //xy=313,439
AudioPlaySdWav           playSdWav1;     //xy=324,292
AudioPlaySdWav           playSdWav4;     //xy=345,516
AudioMixer4              mixer1;         //xy=802,203
AudioMixer4              mixer2;         //xy=851,322
AudioOutputI2S           i2s1;           //xy=1069,248
AudioConnection          patchCord1(sound0, 0, mixer1, 1);
AudioConnection          patchCord2(sound0, 0, mixer2, 2);
AudioConnection          patchCord3(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord4(playSdWav1, 1, mixer2, 1);
AudioConnection          patchCord5(mixer1, 0, i2s1, 0);
AudioConnection          patchCord6(mixer2, 0, i2s1, 1);
// GUItool: end automatically generated code





// Use these with the Teensy Audio Shield
//#define SDCARD_CS_PIN    10
//#define SDCARD_MOSI_PIN  7
//#define SDCARD_SCK_PIN   14

// 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

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13
int inByte = 0;
byte  newDATAin = 1;

#include "AudioSampleCashregister.h" // http://www.freesound.org/people/kiddpark/sounds/201159/



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

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(100);


  //SPI.setMOSI(SDCARD_MOSI_PIN);
  ///SPI.setSCK(SDCARD_SCK_PIN);
  if (!sd.begin(SdioConfig(FIFO_SDIO))) {
    // stop here, but print a message repetitively
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }   
}

void loop() {
   
  
   
switch (Serial.read()) {

            
      
   case 's': {
    Serial.println("s");
   // envelope1.noteOff();
   // envelope2.noteOff();tttttttttttt
   playSdWav1.stop();
   playSdWav2.stop();
   playSdWav3.stop();
   playSdWav4.stop();
   //playSdWav5.stop();
   //playSdWav6.stop();
   //playSdWav7.stop();
   //playSdWav8.stop();
   sound0.play(AudioSampleCashregister);

 
   
 }
 break;

 case 't': {

  sound0.stop();

  playSdWav1.play("10BAB1.WAV");

  playSdWav2.play("10BAB2.WAV");
  
  playSdWav3.play("10BAB3.WAV");
  playSdWav4.play("10BAB4.WAV"); 

 }
 break;

 case 'y': {

  sound0.stop();

  playSdWav1.play("10BAB2.WAV");

 delay(5);

  //playSdWav2.play("10BAB2.WAV");
  
  //playSdWav3.play("10BAB3.WAV");
  //playSdWav4.play("10BAB4.WAV"); 

 }
 break;

   
}
}

Here is the audio used in the above example: http://donjohnstonmusic.co.uk/tr/sinewavs.zip

I am aware three of the wav players are not connected to any outputs, they still play and cause the issue and its the same when they are connected. is there something in the SDfat settings I can tweak to prevent this hang?

all help very gratefully received, I am properly stuck
 
Last edited:
A couple of functional tests with teensy 4.1 and the SdFat 2.2.2 library

MicroSD: Canvas GoPlus 256 Gb

SdFat222_bench256Gb.jpg

GDSTx with Teensy 4.1, FT813 7" TFT and SdFat 2.2.2

SdFat222_SdInfoFT813_256Gb.jpg
 
Back
Top