mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-03 02:20:57 +02:00
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:
@@ -13,6 +13,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "diskio_impl.h"
|
#include "diskio_impl.h"
|
||||||
|
#include "private_include/diskio_private.h"
|
||||||
#include "ffconf.h"
|
#include "ffconf.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
@@ -117,3 +118,16 @@ DWORD get_fattime(void)
|
|||||||
| (WORD)(tmr.tm_min << 5)
|
| (WORD)(tmr.tm_min << 5)
|
||||||
| (WORD)(tmr.tm_sec >> 1);
|
| (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);
|
||||||
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "diskio_impl.h"
|
#include "diskio_impl.h"
|
||||||
|
#include "private_include/diskio_sdmmc_private.h"
|
||||||
#include "ffconf.h"
|
#include "ffconf.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#include "sdmmc_cmd.h"
|
#include "sdmmc_cmd.h"
|
||||||
@@ -143,3 +144,14 @@ BYTE ff_diskio_get_pdrv_card(const sdmmc_card_t* card)
|
|||||||
}
|
}
|
||||||
return 0xff;
|
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;
|
||||||
|
}
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "sdmmc_cmd.h"
|
#include "sd_protocol_types.h"
|
||||||
#include "sd_protocol_defs.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
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);
|
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
|
* @return Driver number to the card
|
||||||
*/
|
*/
|
||||||
BYTE ff_diskio_get_pdrv_card(const sdmmc_card_t* card);
|
BYTE ff_diskio_get_pdrv_card(const sdmmc_card_t* card);
|
||||||
|
36
components/fatfs/diskio/private_include/diskio_private.h
Normal file
36
components/fatfs/diskio/private_include/diskio_private.h
Normal 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
|
@@ -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
|
@@ -16,6 +16,26 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
* @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
|
* For SDMMC peripheral, pass a pointer to sdmmc_slot_config_t
|
||||||
* structure initialized using SDMMC_SLOT_CONFIG_DEFAULT.
|
* structure initialized using SDMMC_SLOT_CONFIG_DEFAULT.
|
||||||
* @param mount_config pointer to structure with extra parameters for mounting FATFS
|
* @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
|
* @return
|
||||||
* - ESP_OK on success
|
* - 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_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
|
||||||
* - ESP_ERR_NO_MEM if memory can not be allocated
|
* - ESP_ERR_NO_MEM if memory can not be allocated
|
||||||
* - ESP_FAIL if partition can not be mounted
|
* - 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
|
* For SPI peripheral, pass a pointer to sdspi_device_config_t
|
||||||
* structure initialized using SDSPI_DEVICE_CONFIG_DEFAULT().
|
* structure initialized using SDSPI_DEVICE_CONFIG_DEFAULT().
|
||||||
* @param mount_config pointer to structure with extra parameters for mounting FATFS
|
* @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
|
* 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
|
* needed. Otherwise it's not suggested to use more than one card at the same time and unmount one
|
||||||
* of them in your application.
|
* of them in your application.
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK on success
|
* - 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_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
|
||||||
* - ESP_ERR_NO_MEM if memory can not be allocated
|
* - ESP_ERR_NO_MEM if memory can not be allocated
|
||||||
* - ESP_FAIL if partition can not be mounted
|
* - ESP_FAIL if partition can not be mounted
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -14,10 +14,12 @@
|
|||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include "esp_vfs_fat.h"
|
#include "esp_vfs_fat.h"
|
||||||
|
#include "vfs_fat_internal.h"
|
||||||
#include "esp_vfs.h"
|
#include "esp_vfs.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#include "diskio_impl.h"
|
#include "diskio_impl.h"
|
||||||
|
#include "private_include/diskio_private.h"
|
||||||
|
|
||||||
#define F_WRITE_MALLOC_ZEROING_BUF_SIZE_LIMIT 512
|
#define F_WRITE_MALLOC_ZEROING_BUF_SIZE_LIMIT 512
|
||||||
|
|
||||||
@@ -1530,3 +1532,63 @@ fail:
|
|||||||
errno = fresult_to_errno(res);
|
errno = fresult_to_errno(res);
|
||||||
return -1;
|
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, §or_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;
|
||||||
|
}
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -13,10 +13,6 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <stddef.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 {
|
typedef struct vfs_fat_spiflash_ctx_t {
|
||||||
const esp_partition_t *partition; //The partition where the FAT is located
|
const esp_partition_t *partition; //The partition where the FAT is located
|
||||||
bool by_label; //If the partition is mounted by label or not
|
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_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);
|
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);
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include "diskio_sdmmc.h"
|
#include "diskio_sdmmc.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "sd_protocol_defs.h"
|
#include "sd_protocol_defs.h"
|
||||||
|
#include "private_include/diskio_sdmmc_private.h"
|
||||||
|
|
||||||
#if SOC_SDMMC_HOST_SUPPORTED
|
#if SOC_SDMMC_HOST_SUPPORTED
|
||||||
#include "driver/sdmmc_host.h"
|
#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 vfs_fat_sd_ctx_t *s_ctx[FF_VOLUMES] = {};
|
||||||
|
|
||||||
static void call_host_deinit(const sdmmc_host_t *host_config);
|
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,
|
static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, BYTE pdrv);
|
||||||
const char *drv, sdmmc_card_t *card, BYTE pdrv);
|
|
||||||
|
|
||||||
static bool s_get_context_id_by_card(const sdmmc_card_t *card, uint32_t *out_id)
|
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,
|
static esp_err_t mount_prepare_mem(const char *base_path,
|
||||||
BYTE *out_pdrv,
|
BYTE *out_pdrv,
|
||||||
char **out_dup_path,
|
char **out_dup_path)
|
||||||
sdmmc_card_t** out_card)
|
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
char* dup_path = NULL;
|
char* dup_path = NULL;
|
||||||
sdmmc_card_t* card = NULL;
|
|
||||||
|
|
||||||
// connect SDMMC driver to FATFS
|
// connect SDMMC driver to FATFS
|
||||||
BYTE pdrv = FF_DRV_NOT_USED;
|
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;
|
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);
|
dup_path = strdup(base_path);
|
||||||
if(!dup_path){
|
if(!dup_path){
|
||||||
ESP_LOGD(TAG, "could not copy base_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;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_card = card;
|
|
||||||
*out_pdrv = pdrv;
|
*out_pdrv = pdrv;
|
||||||
*out_dup_path = dup_path;
|
*out_dup_path = dup_path;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
cleanup:
|
cleanup:
|
||||||
free(card);
|
|
||||||
free(dup_path);
|
free(dup_path);
|
||||||
return err;
|
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;
|
esp_err_t err = ESP_OK;
|
||||||
FRESULT res = f_mount(fs, drv, 1);
|
FRESULT res = f_mount(fs, drv, 1);
|
||||||
if (res != FR_OK) {
|
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;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = partition_card(mount_config, drv, card, pdrv);
|
err = partition_card(mount_config, card, pdrv);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
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;
|
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)
|
const char *base_path, FATFS **out_fs, vfs_fat_x_ctx_flags_t *out_flags)
|
||||||
{
|
{
|
||||||
FATFS *fs = NULL;
|
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
|
// 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) {
|
if (err != ESP_OK) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -191,44 +180,44 @@ fail:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config,
|
static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, BYTE pdrv)
|
||||||
const char *drv, sdmmc_card_t *card, BYTE pdrv)
|
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
esp_err_t err = ESP_OK;
|
||||||
esp_err_t err;
|
esp_vfs_fat_drive_divide_arr_t partitions = {100, 0, 0, 0};
|
||||||
const size_t workbuf_size = 4096;
|
err = esp_vfs_fat_partition_drive(pdrv, partitions);
|
||||||
void* workbuf = NULL;
|
if (err != ESP_OK) {
|
||||||
ESP_LOGW(TAG, "partitioning card");
|
return err;
|
||||||
|
}
|
||||||
|
err = esp_vfs_fat_format_drive(pdrv, mount_config);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
workbuf = ff_memalloc(workbuf_size);
|
static esp_err_t esp_vfs_fat_save_ctx(uint8_t drv_num,
|
||||||
if (workbuf == NULL) {
|
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;
|
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;
|
return ESP_OK;
|
||||||
fail:
|
|
||||||
free(workbuf);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOC_SDMMC_HOST_SUPPORTED
|
#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);
|
return sdmmc_host_init_slot(slot, (const sdmmc_slot_config_t*) slot_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_vfs_fat_sdmmc_sdcard_init(const sdmmc_host_t* host_config,
|
||||||
esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
|
const void* slot_config,
|
||||||
const sdmmc_host_t* host_config,
|
sdmmc_card_t* card,
|
||||||
const void* slot_config,
|
bool* out_host_inited)
|
||||||
const esp_vfs_fat_mount_config_t* mount_config,
|
|
||||||
sdmmc_card_t** out_card)
|
|
||||||
{
|
{
|
||||||
esp_err_t err;
|
if (host_config == NULL || slot_config == NULL || card == NULL) {
|
||||||
vfs_fat_sd_ctx_t *ctx = NULL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t err;
|
||||||
|
int card_handle = -1; //uninitialized
|
||||||
|
bool host_inited = false;
|
||||||
|
|
||||||
err = (*host_config->init)();
|
err = (*host_config->init)();
|
||||||
CHECK_EXECUTE_RESULT(err, "host init failed");
|
CHECK_EXECUTE_RESULT(err, "host init failed");
|
||||||
//deinit() needs to be called to revert the init
|
//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);
|
err = sdmmc_card_init(host_config, card);
|
||||||
CHECK_EXECUTE_RESULT(err, "sdmmc_card_init failed");
|
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");
|
|
||||||
|
|
||||||
if (out_card != NULL) {
|
|
||||||
*out_card = card;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(vfs_fat_sd_ctx_t));
|
return ESP_OK;
|
||||||
if (!ctx) {
|
cleanup:
|
||||||
CHECK_EXECUTE_RESULT(ESP_ERR_NO_MEM, "no mem");
|
if (host_inited) {
|
||||||
}
|
call_host_deinit(host_config);
|
||||||
ctx->pdrv = pdrv;
|
}
|
||||||
memcpy(&ctx->mount_config, mount_config, sizeof(esp_vfs_fat_mount_config_t));
|
return err;
|
||||||
ctx->card = card;
|
}
|
||||||
ctx->base_path = dup_path;
|
|
||||||
ctx->fs = fs;
|
esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
|
||||||
ctx->flags = flags;
|
const sdmmc_host_t* host_config,
|
||||||
ctx_id = s_get_unused_context_id();
|
const void* slot_config,
|
||||||
assert(ctx_id != FF_VOLUMES);
|
const esp_vfs_fat_mount_config_t* mount_config,
|
||||||
s_ctx[ctx_id] = ctx;
|
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;
|
return ESP_OK;
|
||||||
cleanup:
|
cleanup:
|
||||||
if (host_inited) {
|
if (host_inited) {
|
||||||
call_host_deinit(host_config);
|
call_host_deinit(host_config);
|
||||||
}
|
}
|
||||||
free(card);
|
free(card);
|
||||||
free(dup_path);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -320,34 +316,25 @@ bus first and check the device parameters."
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_vfs_fat_sdspi_mount(const char* base_path,
|
esp_err_t esp_vfs_fat_sdspi_sdcard_init(const sdmmc_host_t* host_config,
|
||||||
const sdmmc_host_t* host_config_input,
|
const void* slot_config,
|
||||||
const sdspi_device_config_t* slot_config,
|
sdmmc_card_t* card,
|
||||||
const esp_vfs_fat_mount_config_t* mount_config,
|
bool* out_host_inited)
|
||||||
sdmmc_card_t** out_card)
|
|
||||||
{
|
{
|
||||||
const sdmmc_host_t* host_config = host_config_input;
|
if (host_config == NULL || slot_config == NULL || card == NULL) {
|
||||||
esp_err_t err;
|
return ESP_ERR_INVALID_ARG;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
//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");
|
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");
|
CHECK_EXECUTE_RESULT(err, "slot init failed");
|
||||||
//Set `host_inited` to true to indicate that host_config->deinit() needs
|
//Set `host_inited` to true to indicate that host_config->deinit() needs
|
||||||
//to be called to revert `init_sdspi_host`
|
//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.
|
* above. But the input pointer is const, so create a new variable.
|
||||||
*/
|
*/
|
||||||
sdmmc_host_t new_config;
|
sdmmc_host_t new_config;
|
||||||
if (card_handle != host_config->slot) {
|
if (card_handle != host->slot) {
|
||||||
new_config = *host_config_input;
|
new_config = *host_config;
|
||||||
host_config = &new_config;
|
host = &new_config;
|
||||||
new_config.slot = card_handle;
|
new_config.slot = card_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// probe and initialize card
|
// 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");
|
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");
|
|
||||||
|
|
||||||
if (out_card != NULL) {
|
|
||||||
*out_card = card;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = calloc(1, sizeof(vfs_fat_sd_ctx_t));
|
return ESP_OK;
|
||||||
if (!ctx) {
|
cleanup:
|
||||||
CHECK_EXECUTE_RESULT(ESP_ERR_NO_MEM, "no mem");
|
if (host_inited) {
|
||||||
|
call_host_deinit(host);
|
||||||
}
|
}
|
||||||
ctx->pdrv = pdrv;
|
return err;
|
||||||
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;
|
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
*out_card = card;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -398,6 +405,39 @@ cleanup:
|
|||||||
call_host_deinit(host_config);
|
call_host_deinit(host_config);
|
||||||
}
|
}
|
||||||
free(card);
|
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);
|
free(dup_path);
|
||||||
return err;
|
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)
|
static esp_err_t unmount_card_core(const char *base_path, sdmmc_card_t *card)
|
||||||
{
|
{
|
||||||
BYTE pdrv = ff_diskio_get_pdrv_card(card);
|
BYTE pdrv_num = ff_diskio_get_pdrv_cnt_card(card);
|
||||||
if (pdrv == 0xff) {
|
if (pdrv_num == 0) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
BYTE pdrv = ff_diskio_get_pdrv_card(card);
|
||||||
|
|
||||||
// unmount
|
// unmount
|
||||||
char drv[3] = {(char)('0' + pdrv), ':', 0};
|
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
|
// release SD driver
|
||||||
ff_diskio_unregister(pdrv);
|
ff_diskio_unregister(pdrv);
|
||||||
|
|
||||||
call_host_deinit(&card->host);
|
if (pdrv_num == 1) {
|
||||||
free(card);
|
call_host_deinit(&card->host);
|
||||||
|
free(card);
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t err = esp_vfs_fat_unregister_path(base_path);
|
esp_err_t err = esp_vfs_fat_unregister_path(base_path);
|
||||||
return err;
|
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;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t workbuf_size = 4096;
|
|
||||||
void *workbuf = ff_memalloc(workbuf_size);
|
|
||||||
if (workbuf == NULL) {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
//format
|
//format
|
||||||
uint32_t id = FF_VOLUMES;
|
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;
|
s_ctx[id]->mount_config = *cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(
|
ret = esp_vfs_fat_format_drive(pdrv, &s_ctx[id]->mount_config);
|
||||||
card->csd.sector_size,
|
if (ret != ESP_OK) {
|
||||||
s_ctx[id]->mount_config.allocation_unit_size);
|
ESP_LOGE(TAG, "esp_vfs_fat_format_drive failed");
|
||||||
ESP_LOGI(TAG, "Formatting card, allocation unit size=%d", alloc_unit_size);
|
return ret;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mount back
|
//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) {
|
if (err != ESP_OK) {
|
||||||
unmount_card_core(base_path, card);
|
unmount_card_core(base_path, card);
|
||||||
ESP_LOGE(TAG, "failed to format, resources recycled, please mount again");
|
ESP_LOGE(TAG, "failed to format, resources recycled, please mount again");
|
||||||
|
@@ -148,6 +148,8 @@ static struct {
|
|||||||
struct arg_end *end;
|
struct arg_end *end;
|
||||||
} mount_args;
|
} mount_args;
|
||||||
|
|
||||||
|
static sdmmc_card_t *card = NULL;
|
||||||
|
|
||||||
/** 'mount' command */
|
/** 'mount' command */
|
||||||
static int mount(int argc, char **argv)
|
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.
|
// initialize SD card and mount FAT filesystem.
|
||||||
sdmmc_card_t *card;
|
|
||||||
|
|
||||||
#if CONFIG_SNIFFER_SD_SPI_MODE
|
#if CONFIG_SNIFFER_SD_SPI_MODE
|
||||||
ESP_LOGI(TAG, "Using SPI peripheral");
|
ESP_LOGI(TAG, "Using SPI peripheral");
|
||||||
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
||||||
@@ -249,10 +249,11 @@ static int unmount(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
/* unmount sd card */
|
/* unmount sd card */
|
||||||
if (!strncmp(mount_args.device->sval[0], "sd", 2)) {
|
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");
|
ESP_LOGE(TAG, "Card unmount failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
card = NULL;
|
||||||
ESP_LOGI(TAG, "Card unmounted");
|
ESP_LOGI(TAG, "Card unmounted");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user