BUILTIN_SDCARD not defined when switching from T3.5 to T4.1 compiles

royontog

Member
I have had SDFat running on Teensy 3.5 for a few years now. Switching to Teensy 4.1 I have a few conditionals for compiling out A21 and A22 to replace with I2S and PWM. The 3.5 version still compiles and runs perfectly. The 4.1 compile fails with BUILTIN_SDCARD undefined. I am using Arduino IDE 2.3.2 and TD 1.59.0. The undefined is in my file access library module that has no conditional compilation in it. That file includes SdFat.h. I only have the Teensy SD and SdFat libraries. No SDCard libraries in (Documents) and no libraries at all in (Arduino). (Unless those are somewhere other than
"C:\Program Files\Arduini IDE\"
then I'm looking in the wrong place.)
SdFat is version 2.1.2. I am using sdEx for faster parallel access to the card, so SPI is not needed (I think).

Since BUILTIN_SDCARD was undefined, the only value I found for it when grep'ing the libraries was 254, I first added the #define immediately in front of my method:
Code:
#define BUILTIN_SDCARD 254
int SnFileRW::SN_SD_setup() {
  // returns 0 if successful, else error code
  if (!sdEx.begin(BUILTIN_SDCARD)) {
    sdEx.initErrorHalt("SdEx.begin() failed");
    return( -1 );
  }
  // make sdEx the current volume.
  sdEx.chvol();
  return( 0 );
}
in my library module. It compiled but failed to initialize at run time with
22:39:39.315 -> SdEx.begin() failed
22:39:39.315 -> begin() failed
22:39:39.315 -> Do not reformat the SD.
22:39:39.315 -> No card, wrong chip select pin, or wiring error?
22:39:39.315 -> SdError: 0X1,0X0
So I guess 254 is not the right CS pin on T4.1.
After searching the forum, I removed the #define and switched from including SdFat.h to including SD.h for the T4.1 build, It compiles, but still fails to initialize with the above error.
The SDCard is a SanDisk Ultra 32GB that works fine in the T3.5 and on my PC.
I checked the T4.1 schematic to see if I could find the CS line but it looks like it is internal, and digging into the MXRT1062 code looks daunting.
It would be helpful as a workaround to know what the T4.1 SDCard CS pin number is.
Of course, I would much prefer to get my code to build properly. Is anyone else successfully using sdEx on T4.1? Any ideas on what I should check?
 
Last edited:
#define BUILTIN_SDCARD 254 is the same on T_3.5 and T_4.1. It is not a physical pin, but rather an indicator to use the SDIO interface where CS pin is not relevant.

Teensy uses an included version of SDFAT configured for use with SD.h and any other version of SDFat must not be used. The verbose console build output must show the PJRC Teensy folder version of SDFAT in use.

There are examples of use of the included SD.h that might help testing and resolving the usage as it can be used either as the prior SD.h methods or alternatively as SDFat interface and functions.
 
Thanks for the clarification on the CS pin. I am only using teensy libraries for SD, SPI, and SDFat. I fought that battle a couple years ago ;-)
Code:
C:\Users\Roy\AppData\Local\Arduino15\packages\teensy\tools\teensy-compile\11.3.1/arm/bin/arm-none-eabi-g++ -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++17 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=159 -DARDUINO=10607 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -IC:\Users\Roy\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\cores\teensy4 -Ic:\Users\Roy\Documents\Arduino\libraries\SNTimeCl -IC:\Users\Roy\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\EEPROM C:\Users\Roy\AppData\Local\Temp\arduino\sketches\52727AC3EC0A62F194516ABECA6826BD\sketch\sleepynest-v2-teensy35.ino.cpp -o nul
Alternatives for SD.h: [SD@2.0.0]
ResolveLibrary(SD.h)
  -> candidates: [SD@2.0.0]

Same for SPI and SD.
So is it wrong to use SdFat.h instead of SD.h?

I have a well tested class that uses SdFat.h on T3.5 and it has worked fine for a long time. I am very reluctant to make big changes to it as you can imagine. That said, I am exploring converting to using SdFat with SD.h, but I haven't found any examples yet. I am reading through SD.h and haven't found a clue yest, but early days and I'll keep looking.

My code for Teensy 3.5 is essentially
Code:
#include <SdFat.h>
...
class SNFileRW {
private:
    SdFat sdEx;
...
}

int SNFileRW::SN_SD_setup() {
  // returns 0 if successful, else error code
  #ifdef ARDUINO_TEENSY35
  if (!sdEx.begin(BUILTIN_SDCARD)) {
    sdEx.initErrorHalt("SdEx.begin() failed");
    return( -1 );
  }
  // make sdEx the current volume.
  sdEx.chvol();
  #endif
  return( 0 );
}

Why would that not work simply by changing to compiling for T4.1? [Fails in sdEx.begin(BUILTIN_SDCARD).]
 
Try putting
Code:
#define BUILTIN_SDCARD 254
before you #include SdFat.h. There is code inside that header that depends on it being defined, so if you put it after the file is included (like in your first post) it's not going to work.

(The fact that it doesn't get defined by default for T4.1 may be a bug - SdFatConfig.h contains this:
Code:
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
// Pseudo pin select for SDIO.
#ifndef BUILTIN_SDCARD
#define BUILTIN_SDCARD 254
#endif  // BUILTIN_SDCARD
while SD.h contains this:
Code:
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
#define BUILTIN_SDCARD 254
#endif
So SdFat.h is skipping the definition for T4.1, making people rely on the SD library instead.)
 
With all that said you can actually mix and match SD and SDfat commands. Take a look at the SdFat_Usage example in the SD library. Note: SD is linked to the SDfat library that is installed with Teensyduino (either for 1.8.19 or 2.2.0 IDE's).

Typically to use SDfat you would preface the SDfat command with
Code:
SD.sdfs.xxxxxx
where xxxxxx is the sdfat command.
 
It really helps to see the actual code: If that file is actually like:
Code:
#include <SdFat.h>
...
class SNFileRW {
private:
    SdFat sdEx;
...
}

int SNFileRW::SN_SD_setup() {
  // returns 0 if successful, else error code
  #ifdef ARDUINO_TEENSY35
  if (!sdEx.begin(BUILTIN_SDCARD)) {
    sdEx.initErrorHalt("SdEx.begin() failed");
    return( -1 );
  }
  // make sdEx the current volume.
  sdEx.chvol();
  #endif
  return( 0 );
}
And did not include <SD.h>
And uses the SdFat sdEx class, you need to either instead
#include <SD.h>
and the SD object, which then if you pass in BUILTIN_SDCARD, it will then use 4 bit SDIO and not SPI

Or you need to use SDFat way, to do it.
Code:
#define SD_CONFIG SdioConfig(FIFO_SDIO)
...
  if (!sd.cardBegin(SD_CONFIG)) {

Cut and pasted from SdFat example:

Or you can do combination of the two, as @mjs513 mentioned, but again this depends on including SD.h

Edit: Should mention that in the above example for SDFat library that only started the card.... You probably would probably
use the combined begin like: sd.begin(SD_CONFIG);
 
I really appreciate the insights and suggestions.
FYI, I use sublime and GitHUb, so I can easily see everything I have changed in a build.
I have a lot to look at still, but one thing I did was to grep my sketch folder and the Arduino libraries folder for SD.h (not case-sensitive). It was found only in my header file, and in SDWaveFile.h (which I don't use at this time). SD.h is included in 3 header files in the teensy hardware libraries, I use non of those, but can't be certain they aren't included indirectly. I will put #warning in each to be sure.
That said, for my T3.5 build I only includes SdFat.h and it works fine.
So I removed SdFat.h and included SD.h, and it still works fine. ( SdFat object's begin(), chvol(), open(), read(), write(), ls() ).
The same code compiled for T4.1. It boots and begin() succeeds, but I am unable to access files in any way. Even open() fails.
So all I have done is switch the #include SdFat.h to #include SD.h.
My next thought is to get another T4.1 module, to make sure I don't have a bad SDCard socket or interface.

I will need to get the 4-bit SDIO interface working again. This exercise reminded me that back in the dim times I had to flip a bit in one of the SdFat .h files to use SDIO, and that was lost in later library updates.
I will be trying @KurtE 's suggestions, but changing my SdFat object to an SD object will take some time, I think.

If anyone still wants to see the complete code, I can provide it with a little sanitizing and testing. LMK.
And I will do the same if (when) I have any more questions.
Thanks, again!
 
Please understand this is guesswork since I can't see the files on your PC, but I'm pretty you have copies of SD and SdFat different than the ones published in Teensyduino 1.59.

Even if Arduino IDE is utterly unusable for you to go real programming, in situations like this it can really help as a quick double check to test compiling your program. The older Arduino IDE, version 1.8.19, is actually better to use. Especially on Windows, running Arduino's installer with default settings will delete any previously installed copy (found at the default location). For version 1.8.19, you need to download the Teensyduino installer (scroll down past the stuff for newer Arduino IDE to the stuff for 1.8.19) to get the installer. If using MacOS Mojave or later, the download is a complete copy of Arduino IDE, so nothing needed from Arduino's website.

Yeah, Arduino IDE 1.8.19 is clunky, but it's really easy to just copy and paste a program from another editor and click Verify to check if it compiles. You can also upload and check if it actually works. Please do this. It can save you a lot of time to at least see whether your program compiles and works with the set of libraries we publish for Teensy.

You could also give the published examples as try. Super easy in Arduino IDE, just make sure Teensy is selected in Tools > Boards (since the other menus update depending on the selected board), then click File > Examples > SdFat to open any of the examples that come with the copy of SdFat from Teensyduino 1.59. Just upload and see if they work with your board.

Even if you never want to use Arduino IDE to write actual code, having a known-good setup for comparison can really help.
 
@PaulStoffregen I don't believe that is the case in this situation. Observe what I mentioned in post #4:
SdFat does not define BUILTIN_SDCARD for Teensy 4.x. It's only available if SD.h is included, and that has to come before SdFat.h is included or else SdBase.begin() will fail due to the BUILTIN_SDCARD conditional compilation block being excluded.

So it is completely possible that code compiled for Teensy 3.x, using only SdFat.h, will not work cleanly / without modifications for Teensy 4.x.
 
Back
Top