typedef struct
{
uint8_t pdrv;
sdmmc_card_t card;
char* base;
} sd_data_t;
typedef struct
{
size_t unit_size;
} sd_format_data_t;
static bool sd_format(const sd_data_t* sd_data, const sd_format_data_t* format_data)
{
ESP_LOGI(log_tag, "Format SD card %u", sd_data->pdrv);
bool flag = false;
DWORD plist[] = {100, 0, 0, 0};
FRESULT res;
size_t buffer_size = FF_MAX_SS;
char* buffer = malloc(buffer_size);
if ((res = f_fdisk(sd_data->pdrv, plist, (void*)buffer)) == FR_OK)
{
char drv[3] = {(char)('0' + sd_data->pdrv), ':', '\0'};
// printf("Format SD card 2\n");
if ((res = f_mkfs(drv, FM_FAT32, esp_vfs_fat_get_allocation_unit_size(sd_data->card.csd.sector_size, format_data->unit_size), (void*)buffer, buffer_size)) == FR_OK)
flag = true;
else
{ESP_LOGE(log_tag, "f_mkfs failed with %d", res);}
}
else
{ESP_LOGE(log_tag, "f_fdisk failed with %d", res);}
free(buffer);
ESP_LOGI(log_tag, "Format of SD card %u finished", sd_data->pdrv);
return flag;
}
static bool do_sd_init(const char* base, const sdmmc_host_t* host, const sdspi_slot_config_t* slot, sd_data_t* sd_data, const sd_format_data_t* format_data)
{
bool flag = false;
sd_data->pdrv = 0xFF;
esp_err_t err;
bool host_init = false;
bool vfs_register = false;
bool diskio_register = false;
FATFS* fs = NULL;
char drv[3];
sd_data->base = strdup(base);
// connect SDMMC driver to FATFS
if ((err = ff_diskio_get_drive(&sd_data->pdrv)) == ESP_OK && sd_data->pdrv != 0xFF)
{
drv[0] = (char)('0' + sd_data->pdrv);
drv[1] = ':';
drv[2] = '\0';
if ((err = (*host->init)()) == ESP_OK)
{
host_init = true;
// configure SD slot
if ((err = sdspi_host_init_slot(host->slot, slot)) == ESP_OK)
{
// probe and initialize card
if ((err = sdmmc_card_init(host, &sd_data->card) == ESP_OK))
{
diskio_register = true;
ff_diskio_register_sdmmc(sd_data->pdrv, &sd_data->card);
// connect FATFS to VFS
if ((err = esp_vfs_fat_register(base, drv, 16, &fs)) == ESP_OK)
{
vfs_register = true;
if (!format_data || sd_format(sd_data, format_data))
{
FRESULT res;
if ((res = f_mount(fs, drv, 1)) == FR_OK)
{
flag = true;
ESP_LOGI(log_tag, "SD card %u mounted", sd_data->pdrv);
}
else
{ESP_LOGE(log_tag, "f_mount failed with %d", res);}
}
else
{ESP_LOGE(log_tag, "format_sd failed");}
}
else
{ESP_LOGE(log_tag, "esp_vfs_fat_register failed with '%s (%d)'", esp_err_to_name(err), err);}
}
else
ESP_LOGE(log_tag, "sdmmc_card_init failed with '%s (%d)'", esp_err_to_name(err), err);
}
else
{ESP_LOGE(log_tag, "sdspi_host_init_slot failed with '%s (%d)'", esp_err_to_name(err), err);}
}
else
{ESP_LOGE(log_tag, "host->init() failed with '%s (%d)'", esp_err_to_name(err), err);}
}
else
{ESP_LOGE(log_tag, "ff_diskio_get_drive failed with '%s (%d)'", esp_err_to_name(err), err);}
if (!flag)
{
if (host_init)
host->deinit();
if (fs)
f_mount(NULL, drv, 0);
if (vfs_register)
esp_vfs_fat_unregister_path(base);
if (diskio_register)
ff_diskio_unregister(sd_data->pdrv);
}
is_init = flag;
return flag;
}
bool sd_init(const char* base, const sdmmc_host_t* host, const sdspi_slot_config_t* slot, sd_data_t* sd_data)
{
return do_sd_init(base, host, slot, sd_data, NULL);
}
bool sd_init_and_format(const char* base, const sdmmc_host_t* host, const sdspi_slot_config_t* slot, sd_data_t* sd_data, const sd_format_data_t* format_data)
{
return do_sd_init(base, host, slot, sd_data, format_data);
}