SPI SD card adapter and ESP32-S3 card mount failed

Greetings,

I have read a few similar topics but none of the solutions work for me. I only get "Card Mount Failed" or the equivalent. Please help!

I have an ESP32-S3 N16R8 dev board on a GPIO extension board connected to a micro SD card adapter. I cannot get the SD module to work using the SD_Test.ino straight from the SD library examples (or any other library).

I have literally hundreds of SD cards all formatted with FAT32 (tried FAT and NTFS) using SD card formatter and I can verify they all work and test fine on the PC.

I am using the latest ESP32 board package 3.1.3 but I have tried downgrading to 2.0.17 and no change.

I have confirmed the supply voltage is 3.3 on the money and all the pins on the ESP are working as outputs with blink test code.

I have tried using the two SPI interfaces HSPI and VSPI on the default pins.

int sck = 12;
int miso = 13;
int mosi = 11;
int cs = 10;

and

int sck = 36;
int miso = 37;
int mosi = 35;
int cs = 39;

This is the test code I am using. Please and thanks for any advice.

/*
 * pin 1 - not used          |  Micro SD card     |
 * pin 2 - CS (SS)           |                   /
 * pin 3 - DI (MOSI)         |                  |__
 * pin 4 - VDD (3.3V)        |                    |
 * pin 5 - SCK (SCLK)        | 8 7 6 5 4 3 2 1   /
 * pin 6 - VSS (GND)         | ▄ ▄ ▄ ▄ ▄ ▄ ▄ ▄  /
 * pin 7 - DO (MISO)         | ▀ ▀ █ ▀ █ ▀ ▀ ▀ |
 * pin 8 - not used          |_________________|
 *                             ║ ║ ║ ║ ║ ║ ║ ║
 *                     ╔═══════╝ ║ ║ ║ ║ ║ ║ ╚═════════╗
 *                     ║         ║ ║ ║ ║ ║ ╚══════╗    ║
 *                     ║   ╔═════╝ ║ ║ ║ ╚═════╗  ║    ║
 * Connections for     ║   ║   ╔═══╩═║═║═══╗   ║  ║    ║
 * full-sized          ║   ║   ║   ╔═╝ ║   ║   ║  ║    ║
 * SD card             ║   ║   ║   ║   ║   ║   ║  ║    ║
 * Pin name         |  -  DO  VSS SCK VDD VSS DI CS    -  |
 * SD pin number    |  8   7   6   5   4   3   2   1   9 /
 *                  |                                  █/
 *                  |__▍___▊___█___█___█___█___█___█___/
 *
 * Note:  The SPI pins can be manually configured by using `SPI.begin(sck, miso, mosi, cs).`
 *        Alternatively, you can change the CS pin and use the other default settings by using `SD.begin(cs)`.
 *
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | SPI Pin Name | ESP8266 | ESP32 | ESP32‑S2 | ESP32‑S3 | ESP32‑C3 | ESP32‑C6 | ESP32‑H2 |
 * +==============+=========+=======+==========+==========+==========+==========+==========+
 * | CS (SS)      | GPIO15  | GPIO5 | GPIO34   | GPIO10   | GPIO7    | GPIO18   | GPIO0    |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | DI (MOSI)    | GPIO13  | GPIO23| GPIO35   | GPIO11   | GPIO6    | GPIO19   | GPIO25   |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | DO (MISO)    | GPIO12  | GPIO19| GPIO37   | GPIO13   | GPIO5    | GPIO20   | GPIO11   |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | SCK (SCLK)   | GPIO14  | GPIO18| GPIO36   | GPIO12   | GPIO4    | GPIO21   | GPIO10   |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 *
 * For more info see file README.md in this library or on URL:
 * https://github.com/espressif/arduino-esp32/tree/master/libraries/SD
 */

#include "FS.h"
#include "SD.h"
#include "SPI.h"

/*
//Uncomment and set up if you want to use custom pins for the SPI communication
#define REASSIGN_PINS
int sck = 36;
int miso = 37;
int mosi = 35;
int cs = 39;
*/

void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
  Serial.printf("Listing directory: %s\n", dirname);

  File root = fs.open(dirname);
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }
  if (!root.isDirectory()) {
    Serial.println("Not a directory");
    return;
  }

  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.print("  DIR : ");
      Serial.println(file.name());
      if (levels) {
        listDir(fs, file.path(), levels - 1);
      }
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}

void createDir(fs::FS &fs, const char *path) {
  Serial.printf("Creating Dir: %s\n", path);
  if (fs.mkdir(path)) {
    Serial.println("Dir created");
  } else {
    Serial.println("mkdir failed");
  }
}

void removeDir(fs::FS &fs, const char *path) {
  Serial.printf("Removing Dir: %s\n", path);
  if (fs.rmdir(path)) {
    Serial.println("Dir removed");
  } else {
    Serial.println("rmdir failed");
  }
}

void readFile(fs::FS &fs, const char *path) {
  Serial.printf("Reading file: %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
}

void writeFile(fs::FS &fs, const char *path, const char *message) {
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

void appendFile(fs::FS &fs, const char *path, const char *message) {
  Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

void renameFile(fs::FS &fs, const char *path1, const char *path2) {
  Serial.printf("Renaming file %s to %s\n", path1, path2);
  if (fs.rename(path1, path2)) {
    Serial.println("File renamed");
  } else {
    Serial.println("Rename failed");
  }
}

void deleteFile(fs::FS &fs, const char *path) {
  Serial.printf("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

void testFileIO(fs::FS &fs, const char *path) {
  File file = fs.open(path);
  static uint8_t buf[512];
  size_t len = 0;
  uint32_t start = millis();
  uint32_t end = start;
  if (file) {
    len = file.size();
    size_t flen = len;
    start = millis();
    while (len) {
      size_t toRead = len;
      if (toRead > 512) {
        toRead = 512;
      }
      file.read(buf, toRead);
      len -= toRead;
    }
    end = millis() - start;
    Serial.printf("%u bytes read for %lu ms\n", flen, end);
    file.close();
  } else {
    Serial.println("Failed to open file for reading");
  }

  file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }

  size_t i;
  start = millis();
  for (i = 0; i < 2048; i++) {
    file.write(buf, 512);
  }
  end = millis() - start;
  Serial.printf("%u bytes written for %lu ms\n", 2048 * 512, end);
  file.close();
}

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

#ifdef REASSIGN_PINS
  SPI.begin(sck, miso, mosi, cs);
  if (!SD.begin(cs)) {
#else
  if (!SD.begin()) {
#endif
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  listDir(SD, "/", 0);
  createDir(SD, "/mydir");
  listDir(SD, "/", 0);
  removeDir(SD, "/mydir");
  listDir(SD, "/", 2);
  writeFile(SD, "/hello.txt", "Hello ");
  appendFile(SD, "/hello.txt", "World!\n");
  readFile(SD, "/hello.txt");
  deleteFile(SD, "/foo.txt");
  renameFile(SD, "/hello.txt", "/foo.txt");
  readFile(SD, "/foo.txt");
  testFileIO(SD, "/test.txt");
  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
}

void loop() {}

Did any of those solutions involve the GPIO expansion board?

Test the ESP32 and SD card together on a breadboard, without the GPIO extension board. This will tell you if the expansion board is part of the problem.

Please post a link to the specs of this adapter. Many are designed for use with 5V Arduino and this can cause problems, especially in circuits that use other SPI devices.

Also please post links to the ESP32 board and the GPIO expander, and post a schematic (hand drawn is ok so long as it is neat) so we can see how you have wired everything.

Those are the pins used by the PSRAM on an ESP32S3.

Thanks for the swift reply,

sorry I have just realized only half of my picture uploaded in my original post so the details are missing.

I have ruled out the expansion board as part of the issue. Connecting to the ESP32-S3 pins directly yields the same result.

This is it:

https://www.aliexpress.com/item/1005006833453685.html?spm=a2g0o.order_list.order_list_main.29.49601802LnTAJg

The SD card adapter is a generic adapter from AliExpress with the logic lever converter and 3.3V regulator onboard. I am powering it from the 5V header on the expansion board in the same way I do on a standard ESP32 + breakout board. This works fine on the regular ESP32 and I can use the same code to read SD cards without issue.

https://www.aliexpress.com/item/1865616455.html?spm=a2g0o.order_list.order_list_main.86.49601802LnTAJg

Thanks,

but I am actually focusing on HSPI connected to 10, 11, 12, 13 i only tried VSPI to see if something was wrong.

ESP32-S3 data sheet says the VSPI bus is on 35,37,36 and 39 and is accessible to use. Am I wrong?

This is not my dev board but the GPIO should be similar and the SPI pins too

Here is a picture of my setup while I draw the schematic. Please note I am using an external 9V supply (not plugged in on this pic) connected to the expansion board via the barrel connector so the 5V and 3.3V supply is stable and has 2A available.

int sck = 12;
int miso = 13;
int mosi = 11;
int cs = 10;

Pins 35,37,36 are "accessible" to the ESP32S3 chip and used for the PSRAM on Dev Kit boards.

What operating voltage are the PSRAM chips ?

It would be better to choose an SD adapter without those things to use with a 3.3V board like ESP32. Like this one:

That said, I can't see a reason why the adapter you have is not working.

1 Like

ive purchased a new SD card reader that doesn't have the level shifter. I have connected 3.3V which bypasses the 5V regulator.

it works on an ESp32 but I still cant get it to work on the ESP32-S3....

this is the new module.

I found this:

SD Pull-up Requirements(SD Pull-up Requirements - ESP32-S3 - — ESP-IDF Programming Guide v5.5.1 documentation)

Espressif hardware products are designed for multiple use cases which may require different pull states on pins. For this reason, the pull state of particular pins on certain products needs to be adjusted to provide the pull-ups required in the SD bus.

SD pull-up requirements apply to cases where ESP32-S3 uses the SPI or SDMMC controller to communicate with SD cards. When an SD card is operating in SPI mode or 1-bit SD mode, the CMD and DATA (DAT0 - DAT3) lines of the SD bus must be pulled up by 10 kOhm resistors. SD cards and SDIO devices should also have pull-ups on all above-mentioned lines (regardless of whether these lines are connected to the host) in order to prevent them from entering a wrong state.

But it looks like you have pullups on the SD module, so this requirement should be covered.

thanks,

I have always assumed this to be taken care of by the modules... but I will add some external 10K resistors for a sanity check and I will put a scope on the signals to see if I can see any deformities in the signal.

OK I think I have found the problem.

The Expansion board has a built in 3.3V regulator that connects to the 3.3V output on the ESP32-S3 pins. I have never noticed this until I was measuring the 5V rails on the expansion board without the ESP inserted. the 3.3V headers were hot too. I can only assume that two 3.3V regulators where fighting and causing grief because after cutting the 3.3V supply from the expansion board and powering the SD module only from the ESP 3.3V supply everything seems to be working with the New SD card module that has a 3.3V input.

p.s. will investigate with my first SD module shortly as it has built in 5V regulator...

I have used that type of SD card adapter quite a bit with ESP32 and ESP32S3, is SPI mode and MMX mode, never had a problem.

Trying to use an SD card adapter with regulator on an ESP32 or ESP32S3, is just asking for there to be problems.

SD cards are 3.3V devices,as are ESP32 and ESP32S3, so no regulators needed.

I understand that the signal level shifter circuit on the 5V SD card adapters can cause problems if you want to connect other devices to the SPI bus. I believe it is caused by the MOSI signal not going tri-state when the CS signal is high.

Yep, know about that issue with those boards that are designed for 5V logic level Arduinos.

Thats why I use the ones in the picture you posted.

Ah, sorry, I misunderstood. I thought you were saying you had used the type that @dannysprogis has with ESP32.

Or if doing a PCB, for 3.3v logic micros, I use one of these;

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.