Using SD_MMC library on Seeed Xiao ESP32S3 Sense?

Hello all, I was able to run the demo successfully using the SD.h code to write to the SD card on the Xiao ESP32S3 Sense. However, some code that I would like to use uses the SD_MMC.h functions instead. When I try to even run the SD_MMCTest sketch in Arduino, is says SD card mount failed. Has anyone had any success running SD_MMC with the Sense? Thanks, Justin

To answer my question, I had to update the arduino-esp32 in boards manager and then I was able to get it to run.

Verify that the SD_MMC library is compatible with the Xiao ESP32S3 Sense and the ESP32-S3 platform. It’s possible that there could be compatibility issues or that specific configurations are needed for this particular hardware.

Hi @jlutzwpi , I’m facing the same issue, but my libraries are all up to date. Can you please share the arduino-esp32 version you are using?
Do you did any changes to the Code?
Also, do you did the jumper below the Expansion board as the Wiki says?

Hi there,
You may need to roll back the esp32 library, Look at some of the compiler outputs and see the versions etc.
https://forum.seeedstudio.com/t/xiao-esp32c3-with-round-display-and-sd-card-gif-viewer-example/272381?u=pj_glasso
What error are you getting.
HTH
GL :slight_smile: PJ

Hi!
I was using the library SD_MMC.h and was getting the error “SD card mount failed”.
So I switched to SD.h and it works (I do not tested the performance).
Just like the SD we have to make a change on the SD.begin(21), I think SD_MMC needs also some tuning on pins, but I tried many options and none work.

Looking for the same thing. Examples use the SD/SPI library, but was curious about using SD_MMC library. I found this reference in some sample code:

// non default pins configured for SD card on given camera board
#if defined(CAMERA_MODEL_ESP32S3_EYE) || defined(CAMERA_MODEL_FREENOVE_ESP32S3_CAM)
#define SD_MMC_CLK 39 
#define SD_MMC_CMD 38
#define SD_MMC_D0 40
#elif defined(CAMERA_MODEL_XIAO_ESP32S3)
#define SD_MMC_CLK 7 
#define SD_MMC_CMD 9
#define SD_MMC_D0 8
#elif defined(CAMERA_MODEL_TTGO_T_CAMERA_PLUS)
#define SD_MMC_CLK 21 // SCLK
#define SD_MMC_CMD 19 // MOSI
#define SD_MMC_D0 22  // MISO
#endif

LINK: https://github.com/limengdu/SeeedStudio-XIAO-ESP32S3-Sense-camera/blob/5598bc349ee456ba5589dd99a22a5d362d01f95f/record_video_decorder/ESP32-CAM_MJPEG2SD/appGlobals.h

But, I tried pins 7, 8 and 9 in the SDMMC_Test sketch with no luck. Anyone else have any luck?

Have you tried these?

/*
 * pin 1 - D2                |  Micro SD card     |
 * pin 2 - D3                |                   /
 * pin 3 - CMD               |                  |__
 * pin 4 - VDD (3.3V)        |                    |
 * pin 5 - CLK               | 8 7 6 5 4 3 2 1   /
 * pin 6 - VSS (GND)         | ▄ ▄ ▄ ▄ ▄ ▄ ▄ ▄  /
 * pin 7 - D0                | ▀ ▀ █ ▀ █ ▀ ▀ ▀ |
 * pin 8 - D1                |_________________|
 *                             ║ ║ ║ ║ ║ ║ ║ ║
 *                     ╔═══════╝ ║ ║ ║ ║ ║ ║ ╚═════════╗
 *                     ║         ║ ║ ║ ║ ║ ╚══════╗    ║
 *                     ║   ╔═════╝ ║ ║ ║ ╚═════╗  ║    ║
 * Connections for     ║   ║   ╔═══╩═║═║═══╗   ║  ║    ║
 * full-sized          ║   ║   ║   ╔═╝ ║   ║   ║  ║    ║
 * SD card             ║   ║   ║   ║   ║   ║   ║  ║    ║
 * ESP32-S3 DevKit  | 21  47  GND  39 3V3 GND  40 41  42  |
 * ESP32-S3-USB-OTG | 38  37  GND  36 3V3 GND  35 34  33  |
 * ESP32            |  4   2  GND  14 3V3 GND  15 13  12  |
 * Pin name         | D1  D0  VSS CLK VDD VSS CMD D3  D2  |
 * SD pin number    |  8   7   6   5   4   3   2   1   9 /
 *                  |                                  █/
 *                  |__▍___▊___█___█___█___█___█___█___/
 * WARNING: ALL data pins must be pulled up to 3.3V with an external 10k Ohm resistor!
 * Note to ESP32 pin 2 (D0): Add a 1K Ohm pull-up resistor to 3.3V after flashing
 *
 * SD Card | ESP32
 *    D2       12
 *    D3       13
 *    CMD      15
 *    VSS      GND
 *    VDD      3.3V
 *    CLK      14
 *    VSS      GND
 *    D0       2  (add 1K pull up after flashing)
 *    D1       4
 *
 *    For more info see file README.md in this library or on URL:
 *    https://github.com/espressif/arduino-esp32/tree/master/libraries/SD_MMC
 */

#include "FS.h"
#include "SD_MMC.h"

// Default pins for ESP-S3
// Warning: ESP32-S3-WROOM-2 is using most of the default GPIOs (33-37) to interface with on-board OPI flash.
//   If the SD_MMC is initialized with default pins it will result in rebooting loop - please
//   reassign the pins elsewhere using the mentioned command `setPins`.
// Note: ESP32-S3-WROOM-1 does not have GPIO 33 and 34 broken out.
// Note: if it's ok to use default pins, you do not need to call the setPins
int clk = 36;
int cmd = 35;
int d0  = 37;
int d1  = 38;
int d2  = 33;
int d3  = 39; // GPIO 34 is not broken-out on ESP32-S3-DevKitC-1 v1.1

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

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");
    }
}

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");
    }
}

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);
    /*
    // If you want to change the pin assigment on ESP32-S3 uncomment this block and the appropriate
    // line depending if you want to use 1-bit or 4-bit line.
    // Please note that ESP32 does not allow pin change and will always fail.
    //if(! setPins(clk, cmd, d0)){
    //if(! setPins(clk, cmd, d0, d1, d2, d3)){
        Serial.println("Pin change failed!");
        return;
    }
    */

    if(!SD_MMC.begin()){
        Serial.println("Card Mount Failed");
        return;
    }
    uint8_t cardType = SD_MMC.cardType();

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

    Serial.print("SD_MMC 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_MMC.cardSize() / (1024 * 1024);
    Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);

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

void loop(){

}

from the espressif Git,

I’m sure if you make the neccesary edits , it will work.
HTH
GL :slight_smile: PJ :v:

What are you saying to try?

Hi there,
Well , If you read the fine print it says the following " This library provides the integration of ESP32 and ESP32-S3 with SD (Secure Digital) and MMC (Multi Media Card) cards using a built-in SDMMC module. Please note that SD_MMC is only available for ESP32 and ESP32-S3. For other SoCs please use the SD library based on SPI.
change the pins used in the example and see if it compiles and runs.
That would be my first guess. :face_with_peeking_eye:
based on

Pin assignments for ESP32-S3

On ESP32-S3, SDMMC peripheral is connected to GPIO pins using GPIO matrix. This allows arbitrary GPIOs to be used to connect an SD card or MMC. The GPIOs can be configured with the following commands:

  setPins(int clk, int cmd, int d0))
  setPins(int clk, int cmd, int d0, int d1, int d2, int d3))

I feel like if it was
#define SD_MMC_CLK 7
#define SD_MMC_CMD 9
#define SD_MMC_D0 8
& setPins(int clk, int cmd, int d0))
or setPins(7,9,8)) maybe ? 1,4 or 8 data pins is possible with MMC
But READ the FAQ: ymmv
HTH
GL :slight_smile: PJ :v:

If you read my original post, I mentioned that I tried that.

Hi there,
Yes, In the wrong order though?
I think you may need the other pins defined as well, for a 1 Bit SD_MMC, did you try that?
also you don’t say what type or size it is? (32G-FAT32)
Can you add some code to print out what it thinks the pins are?
ie,

 Serial.println("--------------");
  Serial.print(CS);Serial.println("    CS");
  Serial.print(SS);Serial.println("    SS");
  Serial.print(MOSI);Serial.println("   MOSI"); // master out, slave in
  Serial.print(MISO);Serial.println("    MISO");  // master in, slave out
  Serial.print(SCK);Serial.println("    SCK"); // clock
  Serial.println("--------------");

use the names in the lib, see what comes out
So did you try the SD_MMC begin with pin (21) ?
I’m just tossing stuff at you I would try.
HTH
GL :slight_smile: PJ