Unable to initialize sd card with ESP32

Calling sd card getting failed i am using 16gb sd card with sd card module and source code is follows

        /*
  This example demonstrates how to read and write an SD card on an ESP32,
  using this library contributed by nliviu:

  https://github.com/nliviu/sdlib


   This example is adapted for ESP32 from this example:
   
   https://github.com/cesanta/esp-idf/blob/master/examples/storage/sd_card/main/sd_card_example_main.c
*/

#include "mgos.h"

#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_vfs_fat.h"
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "sdmmc_cmd.h"
#include "mgos_i2c.h"
#include "mgos_imu.h"
#include "mgos_sd.h"

#define PIN_NUM_MISO 19
#define PIN_NUM_MOSI 23
#define PIN_NUM_CLK  18
#define PIN_NUM_CS   5



static void imu_cb(void *user_data) 
{
  struct mgos_imu *imu = (struct mgos_imu *)user_data;
  float ax, ay, az;
  float gx, gy, gz;
  float mx, my, mz;

  if (!imu) return;

  if (mgos_imu_accelerometer_get(imu, &ax, &ay, &az))
    LOG(LL_INFO, ("type=%-10s Accel X=%.2f Y=%.2f Z=%.2f",
                  mgos_imu_accelerometer_get_name(imu), ax, ay, az));
  if (mgos_imu_gyroscope_get(imu, &gx, &gy, &gz))
    LOG(LL_INFO, ("type=%-10s Gyro  X=%.2f Y=%.2f Z=%.2f",
                  mgos_imu_gyroscope_get_name(imu), gx, gy, gz));
  if (mgos_imu_magnetometer_get(imu, &mx, &my, &mz))
    LOG(LL_INFO, ("type=%-10s Mag   X=%.2f Y=%.2f Z=%.2f",
                  mgos_imu_magnetometer_get_name(imu), mx, my, mz));
}



void playWithSd()
{
	
	 LOG(LL_INFO, ( "%s", "Initializing SD card"));



#ifndef USE_SPI_MODE

    LOG(LL_INFO, ( "%s", "Using SDMMC peripheral"));

    sdmmc_host_t host = SDMMC_HOST_DEFAULT();





    gpio_set_pull_mode(15, GPIO_PULLUP_ONLY);   // CMD, needed in 4- and 1- line modes

    gpio_set_pull_mode(2, GPIO_PULLUP_ONLY);    // D0, needed in 4- and 1-line modes

    gpio_set_pull_mode(4, GPIO_PULLUP_ONLY);    // D1, needed in 4-line mode only

    gpio_set_pull_mode(12, GPIO_PULLUP_ONLY);   // D2, needed in 4-line mode only

    gpio_set_pull_mode(13, GPIO_PULLUP_ONLY);   // D3, needed in 4- and 1-line modes



#endif //USE_SPI_MODE





  LOG(LL_INFO, ("%s", "**************************************"));
  LOG(LL_INFO, ("%s", "**************************************"));
  LOG(LL_INFO, ("%s", "Using SPI peripheral"));
  LOG(LL_INFO, ("%s", "Playing with SD!!!!!"));

  //sdmmc_host_t host = SDSPI_HOST_DEFAULT();
  sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
  slot_config.gpio_miso = PIN_NUM_MISO;
  slot_config.gpio_mosi = PIN_NUM_MOSI;
  slot_config.gpio_sck  = PIN_NUM_CLK;
  slot_config.gpio_cs   = PIN_NUM_CS;

  // Options for mounting the filesystem.
  // If format_if_mount_failed is set to true, SD card will be partitioned and
  // formatted in case when mounting fails.
  esp_vfs_fat_sdmmc_mount_config_t mount_config = 
  {
    .format_if_mount_failed = false,
    .max_files = 5,
    .allocation_unit_size = 16 * 1024
  };


  // Use settings defined above to initialize SD card and mount FAT filesystem.
  // Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
  // Please check its source code and implement error recovery when developing
  // production applications.
  sdmmc_card_t* card;
  esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);

  if (ret != ESP_OK)
  {
    if (ret == ESP_FAIL)
    {
      LOG(LL_INFO, ("%s", "Failed to mount filesystem.  If you want the card to be formatted, set format_if_mount_failed = true."));
    }
    else
    { LOG(LL_INFO, ("%s", "**************************************"));
      LOG(LL_INFO, ("Failed to initialize the card (%s). ", esp_err_to_name(ret)));
       LOG(LL_INFO, ("%s", "**************************************"));
    }
    return;
  }

  // Card has been initialized, print its properties
  sdmmc_card_print_info(stdout, card);


  // Use POSIX and C standard library functions to work with files.
  // First create a file.
  LOG(LL_INFO, ("%s", "Opening file"));
  FILE* f = fopen("/sdcard/hello.txt", "w");
  if (f == NULL)
  {
    LOG(LL_INFO, ("%s","Failed to open file for writing"));
    return;
  }
  fprintf(f, "Hello %s!\n", card->cid.name);
  fclose(f);
  LOG(LL_INFO, ("%s","File written"));


  // Check if destination file exists before renaming
  struct stat st;
  if (stat("/sdcard/foo.txt", &st) == 0)
  {
    // Delete it if it exists
    unlink("/sdcard/foo.txt");
  }

  // Rename original file
  LOG(LL_INFO, ("%s","Renaming file"));
  if (rename("/sdcard/hello.txt", "/sdcard/foo.txt") != 0)
  {
    LOG(LL_INFO, ("%s","Rename failed"));
    return;
  }

  // Open renamed file for reading
  LOG(LL_INFO, ("%s","Reading file"));
  f = fopen("/sdcard/foo.txt", "r");
  if (f == NULL)
  {
    LOG(LL_INFO, ("%s","Failed to open file for reading"));
    return;
  }
  char line[64];
  fgets(line, sizeof(line), f);
  fclose(f);
  // strip newline
  char* pos = strchr(line, '\n');
  if (pos)
  {
    *pos = '\0';
  }
  LOG(LL_INFO, ("Read from file: %s", line));

  // All done, unmount partition and disable SDMMC or SPI peripheral
  esp_vfs_fat_sdmmc_unmount();
  LOG(LL_INFO, ("%s", "Card unmounted"));


  LOG(LL_INFO, ("%s", "**************************************"));
  LOG(LL_INFO, ("%s", "**************************************"));
}


enum mgos_app_init_result mgos_app_init(void)
{ 
   
    playWithSd();

  struct mgos_i2c *i2c = mgos_i2c_get_global();
  struct mgos_imu *imu = mgos_imu_create();
  struct mgos_imu_acc_opts acc_opts;
  struct mgos_imu_gyro_opts gyro_opts;
  struct mgos_imu_mag_opts mag_opts;

  if (!i2c) {
    LOG(LL_ERROR, ("I2C bus missing, set i2c.enable=true in mos.yml"));
    return false;
  }

  if (!imu) {
    LOG(LL_ERROR, ("*******************************Cannot create IMU***************\n\n\n"));
    return false;
  }

  acc_opts.type = ACC_MPU9250;
  acc_opts.scale = 16.0; // G
  acc_opts.odr = 100;    // Hz
  if (!mgos_imu_accelerometer_create_i2c(imu, i2c, 0x68, &acc_opts))
    LOG(LL_ERROR, ("Cannot create accelerometer on IMU"));

  gyro_opts.type = GYRO_MPU9250;
  gyro_opts.scale = 2000; // deg/sec
  gyro_opts.odr = 100;    // Hz
  if (!mgos_imu_gyroscope_create_i2c(imu, i2c, 0x68, &gyro_opts))
    LOG(LL_ERROR, ("Cannot create gyroscope on IMU"));

  mag_opts.type = MAG_AK8963;
  mag_opts.scale = 12.0; // Gauss
  mag_opts.odr = 10;     // Hz
  if (!mgos_imu_magnetometer_create_i2c(imu, i2c, 0x0C, &mag_opts))
    LOG(LL_ERROR, ("Cannot create magnetometer on IMU"));


  LOG(LL_INFO, ("%s", "We are in the Entry point!!!!!"));
 

  mgos_set_timer(1000, true, imu_cb, imu);


  return MGOS_APP_INIT_SUCCESS;
}

error as follows

Annotation%202019-12-21%20121927
and error is

You are mixing SPI mode with SDMMC mode, that’s why the initialization fails.

/*
This example demonstrates how to read and write an SD card on an ESP32,
using this library contributed by nliviu:

https://github.com/nliviu/sdlib

This example is adapted for ESP32 from this example:

https://github.com/cesanta/esp-idf/blob/master/examples/storage/sd_card/main/sd_card_example_main.c
*/

#include “mgos.h”

#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include “esp_err.h”
#include “esp_log.h”
#include “esp_vfs_fat.h”
#include “driver/sdmmc_host.h”
#include “driver/sdspi_host.h”
#include “sdmmc_cmd.h”
#include “mgos_i2c.h”
#include “mgos_imu.h”
#include “mgos_sd.h”

#define PIN_NUM_MISO 19
#define PIN_NUM_MOSI 23
#define PIN_NUM_CLK 18
#define PIN_NUM_CS 5

void playWithSd()
{
LOG(LL_INFO, ("%s", “"));
LOG(LL_INFO, ("%s", "
”));

LOG(LL_INFO, ("%s", “Playing with SD!!!”));

sdmmc_host_t host = SDSPI_HOST_DEFAULT();
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
slot_config.gpio_miso = PIN_NUM_MISO;
slot_config.gpio_mosi = PIN_NUM_MOSI;
slot_config.gpio_sck = PIN_NUM_CLK;
slot_config.gpio_cs = PIN_NUM_CS;

// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.
esp_vfs_fat_sdmmc_mount_config_t mount_config =
{
.format_if_mount_failed = false,
.max_files = 5,
.allocation_unit_size = 16 * 1024
};

// Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
// Please check its source code and implement error recovery when developing
// production applications.
sdmmc_card_t* card;
esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);

if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
LOG(LL_INFO, ("%s", “Failed to mount filesystem. If you want the card to be formatted, set format_if_mount_failed = true.”));
}
else
{
LOG(LL_INFO, ("%s", “**************************************”));

  LOG(LL_INFO, ("Failed to initialize the card (%s). ", esp_err_to_name(ret)));
   LOG(LL_INFO, ("%s", "**************************************"));
}
return;

}

// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);

// Use POSIX and C standard library functions to work with files.
// First create a file.
LOG(LL_INFO, ("%s", “Opening file”));
FILE* f = fopen("/sdcard/hello.txt", “w”);
if (f == NULL)
{
LOG(LL_INFO, ("%s",“Failed to open file for writing”));
return;
}
fprintf(f, “Hello %s!\n”, card->cid.name);
fclose(f);
LOG(LL_INFO, ("%s",“File written”));

// Check if destination file exists before renaming
struct stat st;
if (stat("/sdcard/foo.txt", &st) == 0)
{
// Delete it if it exists
unlink("/sdcard/foo.txt");
}

// Rename original file
LOG(LL_INFO, ("%s",“Renaming file”));
if (rename("/sdcard/hello.txt", “/sdcard/foo.txt”) != 0)
{
LOG(LL_INFO, ("%s",“Rename failed”));
return;
}

// Open renamed file for reading
LOG(LL_INFO, ("%s",“Reading file”));
f = fopen("/sdcard/foo.txt", “r”);
if (f == NULL)
{
LOG(LL_INFO, ("%s",“Failed to open file for reading”));
return;
}
char line[64];
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
char* pos = strchr(line, ‘\n’);
if (pos)
{
*pos = ‘\0’;
}
LOG(LL_INFO, (“Read from file: %s”, line));

// All done, unmount partition and disable SDMMC or SPI peripheral
esp_vfs_fat_sdmmc_unmount();
LOG(LL_INFO, ("%s", “Card unmounted”));

LOG(LL_INFO, ("%s", “"));
LOG(LL_INFO, ("%s", "
”));
}

enum mgos_app_init_result mgos_app_init(void)
{

LOG(LL_INFO, ("%s", “We are in the Entry point!!!”));
playWithSd();

return MGOS_APP_INIT_SUCCESS;
}

i used this code and this error shown up now

Annotation%202019-12-21%20155157

Is anybody getting what is the reason for this error?

Check the wiring and add pullup resistors as stated in the README.

Make sure you don’t use another SPI device on the same bus. ESP-IDF does not support sharing the SD SPI bus with other devices.

Hi nliviu. I have tried you SD library on ESP32 but it does not seem to work. I have tried your recent test-sdlib from here https://github.com/nliviu/test-sdlib but it does not seem to work. I am constantly getting: SD init ERROR! I am using ESP32-Wroom-32 devkit C. So I have changed the SPI pins accordingly by adding these lines in mos.yml

config_schema:
- [“sd_spi.pin_miso”, “i”, 19, {title: “SD SPI miso”}]
- [“sd_spi.pin_mosi”, “i”, 23, {title: “SD SPI mosi”}]
- [“sd_spi.pin_clk”, “i”, 18, {title: “SD SPI clk”}]
- [“sd_spi.pin_cs”, “i”, 5, {title: “SD SPI cs”}]

  1. I have used the pullup resistors.
  2. I also do not have any other module connected.

Please let me know if you have solved the problem.

Hi, I have solved the problem. I was using the SD card module that is commonly found with arduino boards. The problem seems to be a builtin pullup/pulldown resistor network. So I had to connect microSD card manually and boom! problem solved. I did not even need to use the pullup resistors as suggested in README because the builtin pullup resistors are being used. Sorry Noob error :grin:

Updated the library to work with esp-idf-4.2 and the test application with write/read file test.

I just picked up a project after a few months away, and I find that the SD card code that had been working no longer does. I’ll paste it below, along with the debug output. Could this latest change have broken it? It used to work fine…

LOG(LL_DEBUG, ("-->> Mounting SD card"));

// Add this code for ESP32 under Mongoose
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
slot_config.gpio_miso = (gpio_num_t) PIN_NUM_MISO;
slot_config.gpio_mosi = (gpio_num_t) PIN_NUM_MOSI;
slot_config.gpio_sck  = (gpio_num_t) PIN_NUM_CLK;
slot_config.gpio_cs   = (gpio_num_t) PIN_NUM_CS;

// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.

LOG(LL_DEBUG, ("-->> A"));

esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  .format_if_mount_failed = false,
  .max_files = 5,
  .allocation_unit_size = 16 * 1024
};

// Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
// Please check its source code and implement error recovery when developing
// production applications.

LOG(LL_DEBUG, ("-->> B"));

sdmmc_card_t* card;
esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);

if (ret != ESP_OK)
{
  if (ret == ESP_FAIL)
  {
    LOG(LL_INFO, ("%s", "Failed to mount filesystem."));
  }
  else
  {
    LOG(LL_INFO, ("Failed to initialize the card (%s). ", esp_err_to_name(ret)));
  }
  return;
}

The output:

[Jan 21 00:54:32.471] polar1.cpp:75           -->> In constructor
[Jan 21 00:54:32.476] polar1.cpp:76           -->> fileName: polar.tsv
[Jan 21 00:54:32.482] polar1.cpp:77           -->> vol: SD
[Jan 21 00:54:32.488] polar1.cpp:93           -->> Mounting SD card
[Jan 21 00:54:32.488] polar1.cpp:107          -->> A
[Jan 21 00:54:32.495] polar1.cpp:120          -->> B
[Jan 21 00:54:32.495] e[0;31mE (6705) vfs_fat_sdmmc: slot init failed (0x103).e[0m
[Jan 21 00:54:32.499] polar1.cpp:133          Failed to initialize the card (ESP_ERR_INVALID_STATE).

You can use my library, it has been updated to work with the new esp-idf.

That code is using your library. I changed it to use mgos_sd_open() instead and that got it working, in one spot, but not in another. I’m using it in two different source modules, would that be a problem? I’ll post some ore info later this evening.