Merge branch 'refactor/fatfs_vfs_functions' into 'master'

fix(storage): Refactor FATFS VFS functions to be easier to understand

Closes IDF-14044

See merge request espressif/esp-idf!41679
This commit is contained in:
Adam Múdry
2025-09-28 22:54:49 +02:00
10 changed files with 460 additions and 175 deletions

View File

@@ -13,6 +13,7 @@
#include <stdlib.h>
#include <sys/time.h>
#include "diskio_impl.h"
#include "private_include/diskio_private.h"
#include "ffconf.h"
#include "ff.h"
@@ -117,3 +118,16 @@ DWORD get_fattime(void)
| (WORD)(tmr.tm_min << 5)
| (WORD)(tmr.tm_sec >> 1);
}
bool ff_diskio_is_registered(BYTE ldrv)
{
if (ldrv < FF_VOLUMES && s_impls[ldrv]) {
return true;
}
return false;
}
inline DRESULT ff_diskio_get_sector_size(BYTE ldrv, UINT* out_bytes_per_sector)
{
return ff_disk_ioctl(ldrv, GET_SECTOR_SIZE, (void*) out_bytes_per_sector);
}

View File

@@ -5,6 +5,7 @@
*/
#include "diskio_impl.h"
#include "private_include/diskio_sdmmc_private.h"
#include "ffconf.h"
#include "ff.h"
#include "sdmmc_cmd.h"
@@ -143,3 +144,14 @@ BYTE ff_diskio_get_pdrv_card(const sdmmc_card_t* card)
}
return 0xff;
}
BYTE ff_diskio_get_pdrv_cnt_card(const sdmmc_card_t* card)
{
BYTE num = 0;
for (int i = 0; i < FF_VOLUMES; i++) {
if (card == s_cards[i]) {
num += 1;
}
}
return num;
}

View File

@@ -1,13 +1,12 @@
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdmmc_cmd.h"
#include "sd_protocol_defs.h"
#include "sd_protocol_types.h"
#ifdef __cplusplus
extern "C" {
@@ -30,9 +29,9 @@ void ff_sdmmc_set_disk_status_check(BYTE pdrv, bool enable);
void ff_diskio_register_sdmmc(unsigned char pdrv, sdmmc_card_t* card);
/**
* @brief Get the driver number corresponding to a card
* @brief Get the first registered drive number corresponding to a card
*
* @param card The card to get its driver
* @param card The card to get its drive number
* @return Driver number to the card
*/
BYTE ff_diskio_get_pdrv_card(const sdmmc_card_t* card);

View File

@@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "diskio.h"
/**
* @brief Check if a drive number is registered
*
* @param ldrv logical or physical drive number
*
* @return true if the drive number is registered, false otherwise
*/
bool ff_diskio_is_registered(BYTE ldrv);
/**
* @brief Get sector size of a drive
*
* @param ldrv logical or physical drive number
* @param out_bytes_per_sector output parameter to receive the sector size in bytes
*
* @return DRESULT indicating success or failure
*/
DRESULT ff_diskio_get_sector_size(BYTE ldrv, UINT* out_bytes_per_sector);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "sd_protocol_types.h"
typedef unsigned char BYTE;
/**
* @brief Get count of all registered drives corresponding to a card
*
* @param card The card to get its drive number
* @return Number of registered drives to the card
*/
BYTE ff_diskio_get_pdrv_cnt_card(const sdmmc_card_t* card);
#ifdef __cplusplus
}
#endif

View File

@@ -16,6 +16,26 @@
extern "C" {
#endif
typedef enum {
FORMATTED_DURING_LAST_MOUNT = 1 << 0, // The FATFS partition was formatted during the last mount
} vfs_fat_x_ctx_flags_t;
typedef PARTITION esp_vfs_fat_pdrv_part_t;
/**
* @note When the value of item is less than or equal to 100, it specifies the partition size in percentage of the entire drive space.
* When it is larger than 100, it specifies number of sectors. The partition map table is terminated by a zero,
* 4th partition in MBR format or no remaining space for next allocation. If the specified size is larger than remaining space on the drive,
* the partition is truncated at end of the drive.
*
* For example:
*
* `{100, 0, 0, 0}` will create a single partition with 100% of the drive space.
* `{50, 50, 0, 0}` will create two partitions, first with 50% of the drive space and second with the remaining 50%.
* `{0x10000000, 0x10000000, 0x10000000, 0}` will create three partitions, each with a size of 256 MiB, leaving remaining space non-allocated.
*/
typedef LBA_t esp_vfs_fat_drive_divide_arr_t[4];
/**
* @brief Configuration structure for esp_vfs_fat_register
*/
@@ -152,9 +172,10 @@ typedef esp_vfs_fat_mount_config_t esp_vfs_fat_sdmmc_mount_config_t;
* For SDMMC peripheral, pass a pointer to sdmmc_slot_config_t
* structure initialized using SDMMC_SLOT_CONFIG_DEFAULT.
* @param mount_config pointer to structure with extra parameters for mounting FATFS
* @param[out] out_card if not NULL, pointer to the card information structure will be returned via this argument
* @param[out] out_card pointer to the card information structure will be returned via this argument
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if any of the arguments is NULL
* - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
* - ESP_ERR_NO_MEM if memory can not be allocated
* - ESP_FAIL if partition can not be mounted
@@ -192,12 +213,13 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
* For SPI peripheral, pass a pointer to sdspi_device_config_t
* structure initialized using SDSPI_DEVICE_CONFIG_DEFAULT().
* @param mount_config pointer to structure with extra parameters for mounting FATFS
* @param[out] out_card If not NULL, pointer to the card information structure will be returned via
* @param[out] out_card Pointer to the card information structure will be returned via
* this argument. It is suggested to hold this handle and use it to unmount the card later if
* needed. Otherwise it's not suggested to use more than one card at the same time and unmount one
* of them in your application.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if any of the arguments is NULL
* - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
* - ESP_ERR_NO_MEM if memory can not be allocated
* - ESP_FAIL if partition can not be mounted

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,10 +14,12 @@
#include <sys/fcntl.h>
#include <sys/lock.h>
#include "esp_vfs_fat.h"
#include "vfs_fat_internal.h"
#include "esp_vfs.h"
#include "esp_log.h"
#include "ff.h"
#include "diskio_impl.h"
#include "private_include/diskio_private.h"
#define F_WRITE_MALLOC_ZEROING_BUF_SIZE_LIMIT 512
@@ -1530,3 +1532,63 @@ fail:
errno = fresult_to_errno(res);
return -1;
}
esp_err_t esp_vfs_fat_format_drive(uint8_t ldrv, const esp_vfs_fat_mount_config_t* mount_config)
{
if (mount_config == NULL || !ff_diskio_is_registered(ldrv)) {
return ESP_ERR_INVALID_ARG;
}
FRESULT res = FR_OK;
esp_err_t err = ESP_OK;
const size_t workbuf_size = 4096;
void* workbuf = NULL;
workbuf = ff_memalloc(workbuf_size);
if (workbuf == NULL) {
return ESP_ERR_NO_MEM;
}
size_t sector_size = 512; // default value
ff_diskio_get_sector_size(ldrv, &sector_size);
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(sector_size, mount_config->allocation_unit_size);
ESP_LOGW(TAG, "formatting drive, allocation unit size=%d", alloc_unit_size);
const MKFS_PARM opt = {(BYTE)FM_ANY, (mount_config->use_one_fat ? 1 : 2), 0, 0, alloc_unit_size};
char drv[3] = {(char)('0' + ldrv), ':', 0};
res = f_mkfs(drv, &opt, workbuf, workbuf_size);
if (res != FR_OK) {
err = ESP_FAIL;
ESP_LOGE(TAG, "f_mkfs failed (%d)", res);
}
free(workbuf);
return err;
}
esp_err_t esp_vfs_fat_partition_drive(uint8_t pdrv, const esp_vfs_fat_drive_divide_arr_t drive_divide)
{
if (!ff_diskio_is_registered(pdrv)) {
return ESP_ERR_INVALID_ARG;
}
FRESULT res = FR_OK;
esp_err_t err = ESP_OK;
const size_t workbuf_size = 4096;
void* workbuf = NULL;
ESP_LOGD(TAG, "partitioning drive");
workbuf = ff_memalloc(workbuf_size);
if (workbuf == NULL) {
return ESP_ERR_NO_MEM;
}
LBA_t ptbl[4] = {drive_divide[0], drive_divide[1], drive_divide[2], drive_divide[3]};
res = f_fdisk(pdrv, ptbl, workbuf);
if (res != FR_OK) {
err = ESP_FAIL;
ESP_LOGE(TAG, "f_fdisk failed (%d)", res);
}
free(workbuf);
return err;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,10 +13,6 @@
#include <sys/param.h>
#include <stddef.h>
typedef enum {
FORMATTED_DURING_LAST_MOUNT = 1 << 0, // The FATFS partition was formatted during the last mount
} vfs_fat_x_ctx_flags_t;
typedef struct vfs_fat_spiflash_ctx_t {
const esp_partition_t *partition; //The partition where the FAT is located
bool by_label; //If the partition is mounted by label or not
@@ -49,3 +45,88 @@ static inline size_t esp_vfs_fat_get_allocation_unit_size(
vfs_fat_spiflash_ctx_t* get_vfs_fat_spiflash_ctx(wl_handle_t wlhandle);
vfs_fat_sd_ctx_t* get_vfs_fat_get_sd_ctx(const sdmmc_card_t *card);
/**
* @brief Helper function to initialize SD card using SDMMC peripheral
*
* @param host_config pointer to structure describing SDMMC host
* @param slot_config pointer to structure with slot configuration
* @param card pointer to structure with card information
* @param[out] out_host_inited if not NULL, pointer to boolean variable will be set to true if host was initialized
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if any of the arguments other than `out_host_inited` is NULL
* - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
*/
esp_err_t esp_vfs_fat_sdmmc_sdcard_init(const sdmmc_host_t* host_config, const void* slot_config, sdmmc_card_t* card, bool* out_host_inited);
/**
* @brief Helper function to initialize SD card using SDSPI peripheral
*
* @param host_config pointer to structure describing SDSPI host
* @param slot_config pointer to structure with slot configuration
* @param card pointer to structure with card information
* @param[out] out_host_inited if not NULL, pointer to boolean variable will be set to true if host was initialized
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if any of the arguments other than `out_host_inited` is NULL
* - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
*/
esp_err_t esp_vfs_fat_sdspi_sdcard_init(const sdmmc_host_t* host_config, const void* slot_config, sdmmc_card_t* card, bool* out_host_inited);
/**
* @brief Convenience function to get FAT filesystem registered and mounted in VFS with an initialized card handle
*
* @note This function is intended to be used when the card is already initialized and the user wants to mount the FAT filesystem on it.
* Can be used to mount multiple partitions on a single card.
*
* @param card pointer to the card handle, which should be initialised by calling `esp_vfs_fat_sdmmc_sdcard_init` or `esp_vfs_fat_sdspi_sdcard_init` first
* @param base_path path where partition should be registered (e.g. "/sdcard" or "/part1", etc.)
* @param mount_config pointer to structure with extra parameters for mounting FATFS
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if any of the arguments is NULL
* - ESP_ERR_NO_MEM if memory can not be allocated
* - ESP_FAIL if partition can not be mounted
* - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
*/
esp_err_t esp_vfs_fat_mount_initialized(sdmmc_card_t* card,
const char* base_path,
const esp_vfs_fat_mount_config_t* mount_config);
/**
* @brief Format FATFS partition on a drive to FAT filesystem
*
* @param ldrv logical or physical drive number
* @param mount_config pointer to structure with extra parameters for mounting FATFS
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if mount_config is NULL or ldrv is not valid
* - ESP_ERR_NO_MEM if memory allocation failed
* - ESP_FAIL if f_mkfs failed
*/
esp_err_t esp_vfs_fat_format_drive(uint8_t ldrv, const esp_vfs_fat_mount_config_t* mount_config);
/**
* @brief Partition the drive to multiple FATFS partitions
*
* @param pdrv physical drive number
* @param drive_divide array of 4 LBA_t values, specifying the size of each partition
*
* @note `esp_vfs_fat_drive_divide_arr_t drive_divide`
* - When the value of item is less than or equal to 100, it specifies the partition size in percentage of the entire drive space.
* When it is larger than 100, it specifies number of sectors. The partition map table is terminated by a zero,
* 4th partition in MBR format or no remaining space for next allocation. If the specified size is larger than remaining space on the drive,
* the partition is truncated at end of the drive.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if pdrv is not valid
* - ESP_ERR_NO_MEM if memory allocation failed
* - ESP_FAIL if f_fdisk failed
*/
esp_err_t esp_vfs_fat_partition_drive(uint8_t pdrv, const esp_vfs_fat_drive_divide_arr_t drive_divide);

View File

@@ -17,6 +17,7 @@
#include "diskio_sdmmc.h"
#include "soc/soc_caps.h"
#include "sd_protocol_defs.h"
#include "private_include/diskio_sdmmc_private.h"
#if SOC_SDMMC_HOST_SUPPORTED
#include "driver/sdmmc_host.h"
@@ -34,8 +35,7 @@ static const char* TAG = "vfs_fat_sdmmc";
static vfs_fat_sd_ctx_t *s_ctx[FF_VOLUMES] = {};
static void call_host_deinit(const sdmmc_host_t *host_config);
static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config,
const char *drv, sdmmc_card_t *card, BYTE pdrv);
static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, BYTE pdrv);
static bool s_get_context_id_by_card(const sdmmc_card_t *card, uint32_t *out_id)
{
@@ -73,12 +73,10 @@ vfs_fat_sd_ctx_t* get_vfs_fat_get_sd_ctx(const sdmmc_card_t *card)
static esp_err_t mount_prepare_mem(const char *base_path,
BYTE *out_pdrv,
char **out_dup_path,
sdmmc_card_t** out_card)
char **out_dup_path)
{
esp_err_t err = ESP_OK;
char* dup_path = NULL;
sdmmc_card_t* card = NULL;
// connect SDMMC driver to FATFS
BYTE pdrv = FF_DRV_NOT_USED;
@@ -87,14 +85,6 @@ static esp_err_t mount_prepare_mem(const char *base_path,
return ESP_ERR_NO_MEM;
}
// not using ff_memalloc here, as allocation in internal RAM is preferred
card = (sdmmc_card_t*)malloc(sizeof(sdmmc_card_t));
if (card == NULL) {
ESP_LOGD(TAG, "could not locate new sdmmc_card_t");
err = ESP_ERR_NO_MEM;
goto cleanup;
}
dup_path = strdup(base_path);
if(!dup_path){
ESP_LOGD(TAG, "could not copy base_path");
@@ -102,18 +92,17 @@ static esp_err_t mount_prepare_mem(const char *base_path,
goto cleanup;
}
*out_card = card;
*out_pdrv = pdrv;
*out_dup_path = dup_path;
return ESP_OK;
cleanup:
free(card);
free(dup_path);
return err;
}
static esp_err_t s_f_mount(sdmmc_card_t *card, FATFS *fs, const char *drv, uint8_t pdrv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags)
static esp_err_t s_f_mount(sdmmc_card_t *card, FATFS *fs, uint8_t pdrv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags)
{
char drv[3] = {(char)('0' + pdrv), ':', 0};
esp_err_t err = ESP_OK;
FRESULT res = f_mount(fs, drv, 1);
if (res != FR_OK) {
@@ -125,7 +114,7 @@ static esp_err_t s_f_mount(sdmmc_card_t *card, FATFS *fs, const char *drv, uint8
return ESP_FAIL;
}
err = partition_card(mount_config, drv, card, pdrv);
err = partition_card(mount_config, card, pdrv);
if (err != ESP_OK) {
return err;
}
@@ -150,7 +139,7 @@ static esp_err_t s_f_mount(sdmmc_card_t *card, FATFS *fs, const char *drv, uint8
return ESP_OK;
}
static esp_err_t mount_to_vfs_fat(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, uint8_t pdrv,
static esp_err_t esp_vfs_fat_mount_internal(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, uint8_t pdrv,
const char *base_path, FATFS **out_fs, vfs_fat_x_ctx_flags_t *out_flags)
{
FATFS *fs = NULL;
@@ -176,7 +165,7 @@ static esp_err_t mount_to_vfs_fat(const esp_vfs_fat_mount_config_t *mount_config
}
// Try to mount partition
err = s_f_mount(card, fs, drv, pdrv, mount_config, out_flags);
err = s_f_mount(card, fs, pdrv, mount_config, out_flags);
if (err != ESP_OK) {
goto fail;
}
@@ -191,44 +180,44 @@ fail:
return err;
}
static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config,
const char *drv, sdmmc_card_t *card, BYTE pdrv)
static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, BYTE pdrv)
{
FRESULT res = FR_OK;
esp_err_t err;
const size_t workbuf_size = 4096;
void* workbuf = NULL;
ESP_LOGW(TAG, "partitioning card");
esp_err_t err = ESP_OK;
esp_vfs_fat_drive_divide_arr_t partitions = {100, 0, 0, 0};
err = esp_vfs_fat_partition_drive(pdrv, partitions);
if (err != ESP_OK) {
return err;
}
err = esp_vfs_fat_format_drive(pdrv, mount_config);
return err;
}
workbuf = ff_memalloc(workbuf_size);
if (workbuf == NULL) {
static esp_err_t esp_vfs_fat_save_ctx(uint8_t drv_num,
const esp_vfs_fat_mount_config_t* mount_config,
sdmmc_card_t* card,
char* base_path,
FATFS* fs,
vfs_fat_x_ctx_flags_t flags)
{
vfs_fat_sd_ctx_t *ctx = NULL;
uint32_t ctx_id = FF_VOLUMES;
ctx = calloc(1, sizeof(vfs_fat_sd_ctx_t));
if (!ctx) {
ESP_LOGE(TAG, "mount_prepare failed");
return ESP_ERR_NO_MEM;
}
ctx->pdrv = drv_num;
memcpy(&ctx->mount_config, mount_config, sizeof(esp_vfs_fat_mount_config_t));
ctx->card = card;
ctx->base_path = base_path;
ctx->fs = fs;
ctx->flags = flags;
ctx_id = s_get_unused_context_id();
assert(ctx_id != FF_VOLUMES);
s_ctx[ctx_id] = ctx;
LBA_t plist[] = {100, 0, 0, 0};
res = f_fdisk(pdrv, plist, workbuf);
if (res != FR_OK) {
err = ESP_FAIL;
ESP_LOGD(TAG, "f_fdisk failed (%d)", res);
goto fail;
}
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(
card->csd.sector_size,
mount_config->allocation_unit_size);
ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size);
const MKFS_PARM opt = {(BYTE)FM_ANY, (mount_config->use_one_fat ? 1 : 2), 0, 0, alloc_unit_size};
res = f_mkfs(drv, &opt, workbuf, workbuf_size);
if (res != FR_OK) {
err = ESP_FAIL;
ESP_LOGD(TAG, "f_mkfs failed (%d)", res);
goto fail;
}
free(workbuf);
return ESP_OK;
fail:
free(workbuf);
return err;
}
#if SOC_SDMMC_HOST_SUPPORTED
@@ -238,29 +227,19 @@ static esp_err_t init_sdmmc_host(int slot, const void *slot_config, int *out_slo
return sdmmc_host_init_slot(slot, (const sdmmc_slot_config_t*) slot_config);
}
esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
const sdmmc_host_t* host_config,
esp_err_t esp_vfs_fat_sdmmc_sdcard_init(const sdmmc_host_t* host_config,
const void* slot_config,
const esp_vfs_fat_mount_config_t* mount_config,
sdmmc_card_t** out_card)
sdmmc_card_t* card,
bool* out_host_inited)
{
esp_err_t err;
vfs_fat_sd_ctx_t *ctx = NULL;
uint32_t ctx_id = FF_VOLUMES;
FATFS *fs = NULL;
int card_handle = -1; //uninitialized
sdmmc_card_t* card = NULL;
BYTE pdrv = FF_DRV_NOT_USED;
char* dup_path = NULL;
bool host_inited = false;
err = mount_prepare_mem(base_path, &pdrv, &dup_path, &card);
if (err != ESP_OK) {
ESP_LOGE(TAG, "mount_prepare failed");
return err;
if (host_config == NULL || slot_config == NULL || card == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err;
int card_handle = -1; //uninitialized
bool host_inited = false;
err = (*host_config->init)();
CHECK_EXECUTE_RESULT(err, "host init failed");
//deinit() needs to be called to revert the init
@@ -274,36 +253,53 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
err = sdmmc_card_init(host_config, card);
CHECK_EXECUTE_RESULT(err, "sdmmc_card_init failed");
vfs_fat_x_ctx_flags_t flags = 0;
err = mount_to_vfs_fat(mount_config, card, pdrv, dup_path, &fs, &flags);
CHECK_EXECUTE_RESULT(err, "mount_to_vfs failed");
if (out_card != NULL) {
*out_card = card;
if (out_host_inited != NULL) {
*out_host_inited = host_inited;
}
ctx = calloc(1, sizeof(vfs_fat_sd_ctx_t));
if (!ctx) {
CHECK_EXECUTE_RESULT(ESP_ERR_NO_MEM, "no mem");
}
ctx->pdrv = pdrv;
memcpy(&ctx->mount_config, mount_config, sizeof(esp_vfs_fat_mount_config_t));
ctx->card = card;
ctx->base_path = dup_path;
ctx->fs = fs;
ctx->flags = flags;
ctx_id = s_get_unused_context_id();
assert(ctx_id != FF_VOLUMES);
s_ctx[ctx_id] = ctx;
return ESP_OK;
cleanup:
if (host_inited) {
call_host_deinit(host_config);
}
return err;
}
esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
const sdmmc_host_t* host_config,
const void* slot_config,
const esp_vfs_fat_mount_config_t* mount_config,
sdmmc_card_t** out_card)
{
if (base_path == NULL || host_config == NULL || slot_config == NULL || mount_config == NULL || out_card == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err;
sdmmc_card_t* card = NULL;
bool host_inited = false;
// not using ff_memalloc here, as allocation in internal RAM is preferred
card = (sdmmc_card_t*) malloc(sizeof(sdmmc_card_t));
if (card == NULL) {
ESP_LOGD(TAG, "could not locate new sdmmc_card_t");
err = ESP_ERR_NO_MEM;
goto cleanup;
}
err = esp_vfs_fat_sdmmc_sdcard_init(host_config, slot_config, card, &host_inited);
CHECK_EXECUTE_RESULT(err, "esp_vfs_fat_sdmmc_sdcard_init failed");
err = esp_vfs_fat_mount_initialized(card, base_path, mount_config);
CHECK_EXECUTE_RESULT(err, "esp_vfs_fat_mount_initialized failed");
*out_card = card;
return ESP_OK;
cleanup:
if (host_inited) {
call_host_deinit(host_config);
}
free(card);
free(dup_path);
return err;
}
#endif
@@ -320,34 +316,25 @@ bus first and check the device parameters."
return err;
}
esp_err_t esp_vfs_fat_sdspi_mount(const char* base_path,
const sdmmc_host_t* host_config_input,
const sdspi_device_config_t* slot_config,
const esp_vfs_fat_mount_config_t* mount_config,
sdmmc_card_t** out_card)
esp_err_t esp_vfs_fat_sdspi_sdcard_init(const sdmmc_host_t* host_config,
const void* slot_config,
sdmmc_card_t* card,
bool* out_host_inited)
{
const sdmmc_host_t* host_config = host_config_input;
esp_err_t err;
vfs_fat_sd_ctx_t *ctx = NULL;
uint32_t ctx_id = FF_VOLUMES;
FATFS *fs = NULL;
int card_handle = -1; //uninitialized
bool host_inited = false;
BYTE pdrv = FF_DRV_NOT_USED;
sdmmc_card_t* card = NULL;
char* dup_path = NULL;
err = mount_prepare_mem(base_path, &pdrv, &dup_path, &card);
if (err != ESP_OK) {
ESP_LOGE(TAG, "mount_prepare failed");
return err;
if (host_config == NULL || slot_config == NULL || card == NULL) {
return ESP_ERR_INVALID_ARG;
}
const sdmmc_host_t* host = host_config;
esp_err_t err;
int card_handle = -1; //uninitialized
bool host_inited = false;
//the init() function is usually empty, doesn't require any deinit to revert it
err = (*host_config->init)();
err = (*host->init)();
CHECK_EXECUTE_RESULT(err, "host init failed");
err = init_sdspi_host(host_config->slot, slot_config, &card_handle);
err = init_sdspi_host(host->slot, slot_config, &card_handle);
CHECK_EXECUTE_RESULT(err, "slot init failed");
//Set `host_inited` to true to indicate that host_config->deinit() needs
//to be called to revert `init_sdspi_host`
@@ -358,39 +345,59 @@ esp_err_t esp_vfs_fat_sdspi_mount(const char* base_path,
* above. But the input pointer is const, so create a new variable.
*/
sdmmc_host_t new_config;
if (card_handle != host_config->slot) {
new_config = *host_config_input;
host_config = &new_config;
if (card_handle != host->slot) {
new_config = *host_config;
host = &new_config;
new_config.slot = card_handle;
}
// probe and initialize card
err = sdmmc_card_init(host_config, card);
err = sdmmc_card_init(host, card);
CHECK_EXECUTE_RESULT(err, "sdmmc_card_init failed");
vfs_fat_x_ctx_flags_t flags = 0;
if (out_host_inited != NULL) {
*out_host_inited = host_inited;
}
err = mount_to_vfs_fat(mount_config, card, pdrv, dup_path, &fs, &flags);
CHECK_EXECUTE_RESULT(err, "mount_to_vfs failed");
return ESP_OK;
cleanup:
if (host_inited) {
call_host_deinit(host);
}
return err;
}
esp_err_t esp_vfs_fat_sdspi_mount(const char* base_path,
const sdmmc_host_t* host_config_input,
const sdspi_device_config_t* slot_config,
const esp_vfs_fat_mount_config_t* mount_config,
sdmmc_card_t** out_card)
{
if (base_path == NULL || host_config_input == NULL || slot_config == NULL || mount_config == NULL || out_card == NULL) {
return ESP_ERR_INVALID_ARG;
}
const sdmmc_host_t* host_config = host_config_input;
esp_err_t err;
bool host_inited = false;
sdmmc_card_t* card = NULL;
// not using ff_memalloc here, as allocation in internal RAM is preferred
card = (sdmmc_card_t*) malloc(sizeof(sdmmc_card_t));
if (card == NULL) {
ESP_LOGD(TAG, "could not locate new sdmmc_card_t");
err = ESP_ERR_NO_MEM;
goto cleanup;
}
err = esp_vfs_fat_sdspi_sdcard_init(host_config_input, slot_config, card, &host_inited);
CHECK_EXECUTE_RESULT(err, "esp_vfs_fat_sdspi_sdcard_init failed");
err = esp_vfs_fat_mount_initialized(card, base_path, mount_config);
CHECK_EXECUTE_RESULT(err, "esp_vfs_fat_mount_initialized failed");
if (out_card != NULL) {
*out_card = card;
}
ctx = calloc(1, sizeof(vfs_fat_sd_ctx_t));
if (!ctx) {
CHECK_EXECUTE_RESULT(ESP_ERR_NO_MEM, "no mem");
}
ctx->pdrv = pdrv;
memcpy(&ctx->mount_config, mount_config, sizeof(esp_vfs_fat_mount_config_t));
ctx->card = card;
ctx->base_path = dup_path;
ctx->fs = fs;
ctx->flags = flags;
ctx_id = s_get_unused_context_id();
assert(ctx_id != FF_VOLUMES);
s_ctx[ctx_id] = ctx;
return ESP_OK;
cleanup:
@@ -398,6 +405,39 @@ cleanup:
call_host_deinit(host_config);
}
free(card);
return err;
}
esp_err_t esp_vfs_fat_mount_initialized(sdmmc_card_t* card,
const char* base_path,
const esp_vfs_fat_mount_config_t* mount_config)
{
if (card == NULL || base_path == NULL || mount_config == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err;
FATFS *fs = NULL;
BYTE ldrv = FF_DRV_NOT_USED;
char* dup_path = NULL;
err = mount_prepare_mem(base_path, &ldrv, &dup_path);
if (err != ESP_OK) {
ESP_LOGE(TAG, "mount_prepare failed");
return err;
}
vfs_fat_x_ctx_flags_t flags = 0;
err = esp_vfs_fat_mount_internal(mount_config, card, ldrv, dup_path, &fs, &flags);
CHECK_EXECUTE_RESULT(err, "esp_vfs_fat_mount_internal failed");
err = esp_vfs_fat_save_ctx(ldrv, mount_config, card, dup_path, fs, flags);
CHECK_EXECUTE_RESULT(err, "esp_vfs_fat_save_ctx failed");
return ESP_OK;
cleanup:
free(dup_path);
return err;
}
@@ -413,10 +453,11 @@ static void call_host_deinit(const sdmmc_host_t *host_config)
static esp_err_t unmount_card_core(const char *base_path, sdmmc_card_t *card)
{
BYTE pdrv = ff_diskio_get_pdrv_card(card);
if (pdrv == 0xff) {
BYTE pdrv_num = ff_diskio_get_pdrv_cnt_card(card);
if (pdrv_num == 0) {
return ESP_ERR_INVALID_ARG;
}
BYTE pdrv = ff_diskio_get_pdrv_card(card);
// unmount
char drv[3] = {(char)('0' + pdrv), ':', 0};
@@ -424,8 +465,10 @@ static esp_err_t unmount_card_core(const char *base_path, sdmmc_card_t *card)
// release SD driver
ff_diskio_unregister(pdrv);
if (pdrv_num == 1) {
call_host_deinit(&card->host);
free(card);
}
esp_err_t err = esp_vfs_fat_unregister_path(base_path);
return err;
@@ -470,12 +513,6 @@ esp_err_t esp_vfs_fat_sdcard_format_cfg(const char *base_path, sdmmc_card_t *car
return ESP_FAIL;
}
const size_t workbuf_size = 4096;
void *workbuf = ff_memalloc(workbuf_size);
if (workbuf == NULL) {
return ESP_ERR_NO_MEM;
}
//format
uint32_t id = FF_VOLUMES;
@@ -489,20 +526,14 @@ esp_err_t esp_vfs_fat_sdcard_format_cfg(const char *base_path, sdmmc_card_t *car
s_ctx[id]->mount_config = *cfg;
}
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(
card->csd.sector_size,
s_ctx[id]->mount_config.allocation_unit_size);
ESP_LOGI(TAG, "Formatting card, allocation unit size=%d", alloc_unit_size);
const MKFS_PARM opt = {(BYTE)FM_ANY, (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, 0, alloc_unit_size};
res = f_mkfs(drv, &opt, workbuf, workbuf_size);
free(workbuf);
if (res != FR_OK) {
ret = ESP_FAIL;
ESP_LOGD(TAG, "f_mkfs failed (%d)", res);
ret = esp_vfs_fat_format_drive(pdrv, &s_ctx[id]->mount_config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "esp_vfs_fat_format_drive failed");
return ret;
}
//mount back
esp_err_t err = s_f_mount(card, s_ctx[id]->fs, drv, pdrv, &s_ctx[id]->mount_config, NULL);
esp_err_t err = s_f_mount(card, s_ctx[id]->fs, pdrv, &s_ctx[id]->mount_config, NULL);
if (err != ESP_OK) {
unmount_card_core(base_path, card);
ESP_LOGE(TAG, "failed to format, resources recycled, please mount again");

View File

@@ -148,6 +148,8 @@ static struct {
struct arg_end *end;
} mount_args;
static sdmmc_card_t *card = NULL;
/** 'mount' command */
static int mount(int argc, char **argv)
{
@@ -168,8 +170,6 @@ static int mount(int argc, char **argv)
};
// initialize SD card and mount FAT filesystem.
sdmmc_card_t *card;
#if CONFIG_SNIFFER_SD_SPI_MODE
ESP_LOGI(TAG, "Using SPI peripheral");
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
@@ -249,10 +249,11 @@ static int unmount(int argc, char **argv)
}
/* unmount sd card */
if (!strncmp(mount_args.device->sval[0], "sd", 2)) {
if (esp_vfs_fat_sdmmc_unmount() != ESP_OK) {
if (esp_vfs_fat_sdcard_unmount(CONFIG_SNIFFER_MOUNT_POINT, card) != ESP_OK) {
ESP_LOGE(TAG, "Card unmount failed");
return -1;
}
card = NULL;
ESP_LOGI(TAG, "Card unmounted");
}
return 0;