Trouble initializing custom sdcard

bobpellegrino

Active member
I am using a NAND chip, XTSD01GLGEAG, as an sdcard on my custom 4.1 board. It is connected to SPI2 as follows:
MISO==>pin 42
MOSI==>pin 43
CS ==> pin 44
SCK ==> pin 45

In the SdFat_Usage example I changed chipselect to 44, and set the last parameter to "&SPI2" in
ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(16), &SPI2));

I also set:
SPI2.setMOSI(43);
SPI2.setSCK(45);
SPI2.setMISO(42);

Result is "Initializing SD card...initialization failed!"

I'm sure I am misunderstanding something simple. Maybe I cannot expect that chip to act like an sdcard?
 
Last edited:
The chip in question is only 125MB. I wonder if that is a problem? Here is the schematic:

1712069908829.png
 
Other people have used those SD-emulating chips successfully on the main SPI port, and SPI2 has been confirmed working with regular SD cards, so I'm pretty sure this can work. My guess is a wiring error. Those bottom side pads are tiny!

Can you show photos of your wiring? Maybe we can help notice any problem with the connection?
 
I doubt that this is helpful, because it is a custom board. The 4 data lines go directly to the referenced pins on the processor. Did we need pullups?

1712076224542.png


1712076108194.jpeg
 
This is the modified CardInfo I used:

C-like:
/*
  SD card test
  
 This example shows how use the utility libraries on which the'
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you're not sure whether its working or not.
    
 The circuit:
  * SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila, pin 7 on Teensy with audio board
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila, pin 14 on Teensy with audio board
 ** CS - depends on your SD card shield or module - pin 10 on Teensy with audio board
         Pin 4 used here for consistency with other Arduino examples

 
 created  28 Mar 2011
 by Limor Fried
 modified 9 Apr 2012
 by Tom Igoe
 */
 // include the SD library:
#include <SD.h>
#include <SPI.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Teensy 3.5 & 3.6 & 4.1 on-board: BUILTIN_SDCARD
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
const int chipSelect = 44;

void setup()
{
  //UNCOMMENT THESE TWO LINES FOR TEENSY AUDIO BOARD:
  SPI2.setMOSI(43);  // Audio shield has MOSI on pin 7
  SPI2.setSCK(45);  // Audio shield has SCK on pin 14
  SPI2.setMISO(42);
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect.
  }


  Serial.print("\nInitializing SD card...");


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
 
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  if (volumesize < 8388608ul) {
    Serial.print("Volume size (bytes): ");
    Serial.println(volumesize * 512);        // SD card blocks are always 512 bytes
  }
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 2;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);

 
  //Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  //root.openRoot(volume);
 
  // list all files in the card with date and size
  //root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {
 
}
 
This is the modified CardInfo I used:

This will not work.

The problem is here:

Code:
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {

This line will use SPI (pins 11,12,13) not SPI2.

Inside SD.h, you can see this init() function just calls SD.begin(pin).


To actually use SPI2, you need one of the special begin() functions which tells the SD / SdFat library to use SPI2. You configured the SPI2 pins early in the program, but that is not enough. It only tells the SPI2 instance in the SPI library which pins to use, when a library like SD tries to use SPI2. But if you do not also instruct SD to use SPI2, then the pin config has absolutely no effect because nothing ever tries to actually use SPI2. It will just default to regular SPI.
 
Last edited:
I am in the process of adding the R-pi Pico board that has two SPI ports to the GDSTx library for EVEx displays. On the Teensy 4.1 board it was enough to use the SDIO reader.

I have been able to access the second SPI port with these lines in the SdInfo example:

Code:
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = 13;
#else   // SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif  // SDCARD_SS_PIN

// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16), &SPI1)
#else  // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16), &SPI1)
#endif  // HAS_SDIO_CLASS

//------------------------------------------------------------------------------

No need to define SCK-MISO-MOSI pins
 
Darn! I thought I knew what to do...
I modified the SdFat_Usage example as shown in red:


Code:
#include <SD.h>

// On Teensy 2.0, SdFat's files are "File32" rather than "FsFat"
#ifdef __AVR__
#define FsFile File32
#endif

void setup()
{
 

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

  Serial.print("Initializing SD card...");
  bool ok;
  const int chipSelect = 44;
  SPI2.setMOSI(43);
  SPI2.setMISO(42);
  SPI2.setSCK(45);
ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(16), &SPI2));

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

 
  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();

 
  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((uint8_t)'\0'); // add a null byte to mark end of string
  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();

 
}

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


void printSpaces(int num) {
  for (int i = 0; i < num; i++) {
    Serial.print(" ");
  }
}

The first time it ran, I got:

Initializing SD card...initialization done.


Print directory using SD functions
datalog.bin 41943040


Print directory using SdFat ls() function
datalog.bin


Writing to datalog.bin using SdFat functions
datalog.bin started with 41943040 bytes
unable to preallocate this file
datalog.bin


Writing to datalog.bin using SdFat functions
datalog.bin started with 41943040 bytes
unable to preallocate this file
Reading to datalog.bin using SD functions
Read from file:



After that, each subsequent run failed with:
Initializing SD card...initialization failed!
even after power cycle.
 
Back
Top