> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kode.diy/llms.txt
> Use this file to discover all available pages before exploring further.

# MicroSD

> Discover the use of the microSD, its programming and why it is so important.

# Features

The microSD card is one of the **essential parts for the operation of the Kode Dot.** In it the applications, configuration data and user files are stored.

In addition, for **projects and applications** that are developed in kodeOS, it is the **easiest way to save the data that is generated.**

## Connection diagram

The microSD is connected to the ESP32-S3 via **SDIO, in 1-bit mode.** Thus, the **SD/MMC Host** peripheral that has the ESP32-S3 dedicated to read and write on the microSD is used.

The connection between the microSD and the ESP32-S3 is as follows:

| MicroSD       | ESP32-S3 |
| ------------- | -------- |
| Command       | GPIO5    |
| Clock         | GPIO6    |
| Data          | GPIO7    |
| Card Detected | EXP14    |

<Note>The Card Detected pin is connected to EXP14 of the IO expander. See [IO expander](/en/kode-dot/io-expander) for more information.</Note>

## Recommended libraries

### Arduino

* [SD\_MMC](https://github.com/espressif/arduino-esp32/tree/master/libraries/SD_MMC)

### ESP-IDF

* No requires additional libraries.

## Example code

This code will make a **test of the microSD in this order:**

1. List directories
2. Create a directory
3. List directories
4. Delete a directory
5. List directories
6. Write a file
7. Add a message to the end of a file
8. Read a file
9. Delete a file
10. Rename a file
11. Read a file
12. Test of reading and writing performance

```cpp microsd_test.ino lines icon="microchip" theme={null}
/**
 * Manages an SD card in SD_MMC (1-bit) mode on ESP32-S3.
 * Performs file operations (list, create, read, write, rename, delete) and measures performance.
 * Uses custom pins and mounts the card at /sdcard.
*/
/* ───────── KODE | docs.kode.diy ───────── */

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

/* Custom pins for SD_MMC (SD in 1-bit mode) */
int clk = 6;    /* Clock pin (CLK) */
int cmd = 5;    /* Command pin (CMD) */
int d0  = 7;    /* Data0 pin (D0) */

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

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

  /* Iterate through files and subdirectories */
  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.print("  DIR : ");
      Serial.println(file.name());
      /* Recurse into subdirectories if levels > 0 */
      if (levels) {
        listDir(fs, file.path(), levels - 1);
      }
    } else {
      /* It's a file: print name and size */
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}

/* Function to create a directory */
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");
  }
}

/* Function to remove a directory */
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");
  }
}

/* Function to read and display file contents */
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: ");
  /* Read byte by byte and write to Serial */
  while (file.available()) {
    Serial.write(file.read());
  }
}

/* Function to write a message to a file (overwrite) */
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;
  }
  /* Write the message and check result */
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
}

/* Function to append a message to a file */
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");
  }
}

/* Function to rename a file */
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");
  }
}

/* Function to delete a file */
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");
  }
}

/* File I/O performance test on a large file */
void testFileIO(fs::FS &fs, const char *path) {
  File file = fs.open(path);
  static uint8_t buf[512];  /* 512-byte buffer */
  size_t len = 0;
  uint32_t start = millis();
  uint32_t elapsed;

  if (file) {
    /* Get file size */
    len = file.size();
    size_t originalLen = len;
    start = millis();
    /* Read file in chunks */
    while (len) {
      size_t toRead = (len > sizeof(buf)) ? sizeof(buf) : len;
      file.read(buf, toRead);
      len -= toRead;
    }
    elapsed = millis() - start;
    Serial.printf("%u bytes read in %lu ms\n", originalLen, elapsed);
    file.close();
  } else {
    Serial.println("Failed to open file for reading");
  }

  /* Write performance measurement */
  file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  start = millis();
  /* Write 2048 blocks of 512 bytes (1 MiB) */
  for (size_t i = 0; i < 2048; i++) {
    file.write(buf, sizeof(buf));
  }
  elapsed = millis() - start;
  Serial.printf("%u bytes written in %lu ms\n", 2048 * sizeof(buf), elapsed);
  file.close();
}

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

  /* Assign custom pins for SD_MMC in 1-bit mode */
  if (!SD_MMC.setPins(clk, cmd, d0)) {
    Serial.println("Pin change failed!");
    return;
  }

  /* Mount the SD card via SD_MMC (mount point and busWidth=1 for 1-bit) */
  if (!SD_MMC.begin("/sdcard", 1)) {
    Serial.println("Card Mount Failed");
    return;
  }

  /* Check card type */
  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");

  /* Print card size in MB */
  uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
  Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);

  /* Examples of file and directory operations */
  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");

  /* Print total and used space in MB */
  Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
}

void loop() {
  /* Nothing to do in the main loop; brief delay to yield CPU */
  delay(10);
}
```

## Download examples

You can test the example codes using the Arduino IDE or the ESP-IDF IDE or download the codes in our drive:

[MicroSD examples](https://drive.google.com/drive/folders/1fMG1BzAr6a9Gi88daPVNe0bdkRSY8TKe)
