From 15435bc21e98e34aa71e33aff59040dc9037c059 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Tue, 9 Jan 2024 16:37:47 +1100 Subject: [PATCH 01/13] Initial implmentation for SD card support --- CMakeLists.txt | 6 +- include/esp_littlefs.h | 2 + src/esp_littlefs.c | 90 ++++++++++++++++++--- src/littlefs_api.h | 56 +++++++++++-- src/{littlefs_api.c => littlefs_esp_part.c} | 12 +-- src/littlefs_sdmmc.c | 54 +++++++++++++ 6 files changed, 195 insertions(+), 25 deletions(-) rename src/{littlefs_api.c => littlefs_esp_part.c} (77%) create mode 100644 src/littlefs_sdmmc.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d3dd96..7c103a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,14 @@ cmake_minimum_required(VERSION 3.10) file(GLOB SOURCES src/littlefs/*.c) -list(APPEND SOURCES src/esp_littlefs.c src/littlefs_api.c src/lfs_config.c) +list(APPEND SOURCES src/esp_littlefs.c src/littlefs_esp_part.c src/littlefs_sdmmc.c src/lfs_config.c) if(IDF_VERSION_MAJOR GREATER_EQUAL 5) - list(APPEND pub_requires esp_partition) + list(APPEND pub_requires esp_partition sdmmc) else() list(APPEND pub_requires spi_flash) endif() -list(APPEND priv_requires esptool_py spi_flash vfs) +list(APPEND priv_requires esptool_py spi_flash vfs sdmmc) idf_component_register( SRCS ${SOURCES} diff --git a/include/esp_littlefs.h b/include/esp_littlefs.h index cf70959..ec4edc6 100644 --- a/include/esp_littlefs.h +++ b/include/esp_littlefs.h @@ -4,6 +4,7 @@ #include "esp_err.h" #include "esp_idf_version.h" #include +#include #include "esp_partition.h" #ifdef __cplusplus @@ -26,6 +27,7 @@ typedef struct { const char *base_path; /**< Mounting point. */ const char *partition_label; /**< Label of partition to use. */ const esp_partition_t* partition; /**< partition to use if partition_label is NULL */ + sdmmc_card_t *sdcard; /**< SD card handle to use if both esp_partition handle & partition label is NULL */ uint8_t format_if_mount_failed:1; /**< Format the file system if it fails to mount. */ uint8_t read_only : 1; /**< Mount the partition as read-only. */ uint8_t dont_mount:1; /**< Don't attempt to mount.*/ diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index a226682..251fdc8 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -23,6 +23,7 @@ #include #include #include +#include #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) #include "spi_flash_mmap.h" @@ -693,6 +694,62 @@ static void esp_littlefs_take_efs_lock(void) { xSemaphoreTake(_efs_lock, portMAX_DELAY); } +static esp_err_t esp_littlefs_init_sdcard(esp_littlefs_t** efs, sdmmc_card_t* sdcard, bool read_only) +{ + /* Allocate Context */ + *efs = esp_littlefs_calloc(1, sizeof(esp_littlefs_t)); + if (*efs == NULL) { + ESP_LOGE(ESP_LITTLEFS_TAG, "esp_littlefs could not be malloced"); + return ESP_ERR_NO_MEM; + } + (*efs)->sdcard = sdcard; + + { /* LittleFS Configuration */ + (*efs)->cfg.context = *efs; + (*efs)->read_only = read_only; + + // block device operations + (*efs)->cfg.read = littlefs_sdmmc_read; + (*efs)->cfg.prog = littlefs_sdmmc_write; + (*efs)->cfg.erase = littlefs_sdmmc_erase; + (*efs)->cfg.sync = littlefs_sdmmc_sync; + + // block device configuration + (*efs)->cfg.read_size = sdcard->csd.sector_size; + (*efs)->cfg.prog_size = sdcard->csd.sector_size; + (*efs)->cfg.block_size = sdcard->csd.sector_size; + (*efs)->cfg.block_count = sdcard->csd.capacity; + (*efs)->cfg.cache_size = CONFIG_LITTLEFS_CACHE_SIZE; + (*efs)->cfg.lookahead_size = CONFIG_LITTLEFS_LOOKAHEAD_SIZE; + (*efs)->cfg.block_cycles = CONFIG_LITTLEFS_BLOCK_CYCLES; +#if CONFIG_LITTLEFS_MULTIVERSION + #if CONFIG_LITTLEFS_DISK_VERSION_MOST_RECENT + (*efs)->cfg.disk_version = 0; +#elif CONFIG_LITTLEFS_DISK_VERSION_2_1 + (*efs)->cfg.disk_version = 0x00020001; +#elif CONFIG_LITTLEFS_DISK_VERSION_2_0 + (*efs)->cfg.disk_version = 0x00020000; +#else +#error "CONFIG_LITTLEFS_MULTIVERSION enabled but no or unknown disk version selected!" +#endif +#endif + } + + (*efs)->lock = xSemaphoreCreateRecursiveMutex(); + if ((*efs)->lock == NULL) { + ESP_LOGE(ESP_LITTLEFS_TAG, "mutex lock could not be created"); + return ESP_ERR_NO_MEM; + } + + (*efs)->fs = esp_littlefs_calloc(1, sizeof(lfs_t)); + if ((*efs)->fs == NULL) { + ESP_LOGE(ESP_LITTLEFS_TAG, "littlefs could not be malloced"); + return ESP_ERR_NO_MEM; + } + + return ESP_OK; +} + static esp_err_t esp_littlefs_init_efs(esp_littlefs_t** efs, const esp_partition_t* partition, bool read_only) { /* Allocate Context */ @@ -708,10 +765,10 @@ static esp_err_t esp_littlefs_init_efs(esp_littlefs_t** efs, const esp_partition (*efs)->read_only = read_only; // block device operations - (*efs)->cfg.read = littlefs_api_read; - (*efs)->cfg.prog = littlefs_api_prog; - (*efs)->cfg.erase = littlefs_api_erase; - (*efs)->cfg.sync = littlefs_api_sync; + (*efs)->cfg.read = littlefs_esp_part_read; + (*efs)->cfg.prog = littlefs_esp_part_write; + (*efs)->cfg.erase = littlefs_esp_part_erase; + (*efs)->cfg.sync = littlefs_esp_part_sync; // block device configuration (*efs)->cfg.read_size = CONFIG_LITTLEFS_READ_SIZE; @@ -793,12 +850,20 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) goto exit; } partition = conf->partition; + } else if (conf->sdcard) { + ESP_LOGI(ESP_LITTLEFS_TAG, "Using SD card handle %p for LittleFS mount", conf->sdcard); + err = sdmmc_get_status(conf->sdcard); + if (err != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Failed when checking SD card status: 0x%x", err); + goto exit; + } } else { ESP_LOGE(ESP_LITTLEFS_TAG, "No partition specified in configuration"); err = ESP_ERR_INVALID_ARG; goto exit; } - { + + if (!conf->sdcard) { uint32_t flash_page_size = g_rom_flashchip.page_size; uint32_t log_page_size = CONFIG_LITTLEFS_PAGE_SIZE; if (log_page_size % flash_page_size != 0) { @@ -807,11 +872,17 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) err = ESP_ERR_INVALID_ARG; goto exit; } - } - err = esp_littlefs_init_efs(&efs, partition, conf->read_only); - if(err != ESP_OK) { - goto exit; + err = esp_littlefs_init_efs(&efs, partition, conf->read_only); + + if(err != ESP_OK) { + goto exit; + } + } else { + err = esp_littlefs_init_sdcard(&efs, conf->sdcard, conf->read_only); + if(err != ESP_OK) { + goto exit; + } } // Mount and Error Check @@ -822,7 +893,6 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) res = lfs_mount(efs->fs, &efs->cfg); if (conf->format_if_mount_failed && res != LFS_ERR_OK) { - esp_err_t err; ESP_LOGW(ESP_LITTLEFS_TAG, "mount failed, %s (%i). formatting...", esp_littlefs_errno(res), res); err = esp_littlefs_format_partition(efs->partition); diff --git a/src/littlefs_api.h b/src/littlefs_api.h index 8dabe6c..1914cb7 100644 --- a/src/littlefs_api.h +++ b/src/littlefs_api.h @@ -9,6 +9,7 @@ #include "esp_vfs.h" #include "esp_partition.h" #include "littlefs/lfs.h" +#include #ifdef __cplusplus extern "C" { @@ -45,6 +46,7 @@ typedef struct _vfs_littlefs_file_t { typedef struct { lfs_t *fs; /*!< Handle to the underlying littlefs */ SemaphoreHandle_t lock; /*!< FS lock */ + sdmmc_card_t *sdcard; /*!< The SD card driver handle on which littlefs is located */ const esp_partition_t* partition; /*!< The partition on which littlefs is located */ char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */ @@ -65,8 +67,8 @@ typedef struct { * * @return errorcode. 0 on success. */ -int littlefs_api_read(const struct lfs_config *c, lfs_block_t block, - lfs_off_t off, void *buffer, lfs_size_t size); +int littlefs_esp_part_read(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size); /** * @brief Program a region in a block. @@ -77,8 +79,8 @@ int littlefs_api_read(const struct lfs_config *c, lfs_block_t block, * * @return errorcode. 0 on success. */ -int littlefs_api_prog(const struct lfs_config *c, lfs_block_t block, - lfs_off_t off, const void *buffer, lfs_size_t size); +int littlefs_esp_part_write(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size); /** * @brief Erase a block. @@ -89,7 +91,7 @@ int littlefs_api_prog(const struct lfs_config *c, lfs_block_t block, * May return LFS_ERR_CORRUPT if the block should be considered bad. * @return errorcode. 0 on success. */ -int littlefs_api_erase(const struct lfs_config *c, lfs_block_t block); +int littlefs_esp_part_erase(const struct lfs_config *c, lfs_block_t block); /** * @brief Sync the state of the underlying block device. @@ -98,7 +100,49 @@ int littlefs_api_erase(const struct lfs_config *c, lfs_block_t block); * * @return errorcode. 0 on success. */ -int littlefs_api_sync(const struct lfs_config *c); +int littlefs_esp_part_sync(const struct lfs_config *c); + +/** + * @brief Read a region in a block on SD card + * + * Negative error codes are propogated to the user. + * + * @return errorcode. 0 on success. + */ +int littlefs_sdmmc_read(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size); + +/** + * @brief Program a region in a block on SD card. + * + * The block must have previously been erased. + * Negative error codes are propogated to the user. + * May return LFS_ERR_CORRUPT if the block should be considered bad. + * + * @return errorcode. 0 on success. + */ +int littlefs_sdmmc_write(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size); + +/** + * @brief Erase a block on SD card. + * + * A block must be erased before being programmed. + * The state of an erased block is undefined. + * Negative error codes are propogated to the user. + * May return LFS_ERR_CORRUPT if the block should be considered bad. + * @return errorcode. 0 on success. + */ +int littlefs_sdmmc_erase(const struct lfs_config *c, lfs_block_t block); + +/** + * @brief Sync the state of the underlying SD card. + * + * Negative error codes are propogated to the user. + * + * @return errorcode. 0 on success. + */ +int littlefs_sdmmc_sync(const struct lfs_config *c); #ifdef __cplusplus } diff --git a/src/littlefs_api.c b/src/littlefs_esp_part.c similarity index 77% rename from src/littlefs_api.c rename to src/littlefs_esp_part.c index b4a1ab9..1cbbcca 100644 --- a/src/littlefs_api.c +++ b/src/littlefs_esp_part.c @@ -14,8 +14,8 @@ #include "littlefs_api.h" -int littlefs_api_read(const struct lfs_config *c, lfs_block_t block, - lfs_off_t off, void *buffer, lfs_size_t size) { +int littlefs_esp_part_read(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size) { esp_littlefs_t * efs = c->context; size_t part_off = (block * c->block_size) + off; esp_err_t err = esp_partition_read(efs->partition, part_off, buffer, size); @@ -26,8 +26,8 @@ int littlefs_api_read(const struct lfs_config *c, lfs_block_t block, return 0; } -int littlefs_api_prog(const struct lfs_config *c, lfs_block_t block, - lfs_off_t off, const void *buffer, lfs_size_t size) { +int littlefs_esp_part_write(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { esp_littlefs_t * efs = c->context; size_t part_off = (block * c->block_size) + off; esp_err_t err = esp_partition_write(efs->partition, part_off, buffer, size); @@ -38,7 +38,7 @@ int littlefs_api_prog(const struct lfs_config *c, lfs_block_t block, return 0; } -int littlefs_api_erase(const struct lfs_config *c, lfs_block_t block) { +int littlefs_esp_part_erase(const struct lfs_config *c, lfs_block_t block) { esp_littlefs_t * efs = c->context; size_t part_off = block * c->block_size; esp_err_t err = esp_partition_erase_range(efs->partition, part_off, c->block_size); @@ -50,7 +50,7 @@ int littlefs_api_erase(const struct lfs_config *c, lfs_block_t block) { } -int littlefs_api_sync(const struct lfs_config *c) { +int littlefs_esp_part_sync(const struct lfs_config *c) { /* Unnecessary for esp-idf */ return 0; } diff --git a/src/littlefs_sdmmc.c b/src/littlefs_sdmmc.c new file mode 100644 index 0000000..28a0648 --- /dev/null +++ b/src/littlefs_sdmmc.c @@ -0,0 +1,54 @@ +/** + * @file littlefs_sdmmc.c + * @brief Maps the HAL of sdmmc driver <-> littlefs + * @author Jackson Ming Hu + */ + +#include +#include +#include "littlefs_api.h" + +int littlefs_sdmmc_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) +{ + esp_littlefs_t * efs = c->context; + size_t part_off = (block * c->block_size) + off; + + esp_err_t ret = sdmmc_read_sectors(efs->sdcard, buffer, block, MIN(size / efs->cfg.read_size, 1)); + if (ret != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "failed to read addr %08x, size %08x, err=0x%x", (unsigned int) part_off, (unsigned int) size, ret); + return LFS_ERR_IO; + } + + return LFS_ERR_OK; +} + +int littlefs_sdmmc_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) +{ + esp_littlefs_t * efs = c->context; + size_t part_off = (block * c->block_size) + off; + + esp_err_t ret = sdmmc_write_sectors(efs->sdcard, buffer, block, MIN(size / efs->cfg.prog_size, 1)); + if (ret != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "failed to write addr %08x, size %08x, err=0x%x", (unsigned int) part_off, (unsigned int) size, ret); + return LFS_ERR_IO; + } + + return LFS_ERR_OK; +} + +int littlefs_sdmmc_erase(const struct lfs_config *c, lfs_block_t block) +{ + esp_littlefs_t * efs = c->context; + esp_err_t ret = sdmmc_erase_sectors(efs->sdcard, block, 1, SDMMC_ERASE_ARG); + if (ret != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Failed to erase block %lu: ret=0x%x %s", block, ret, esp_err_to_name(ret)); + return LFS_ERR_IO; + } + + return LFS_ERR_OK; +} + +int littlefs_sdmmc_sync(const struct lfs_config *c) +{ + return LFS_ERR_OK; // Doesn't require & doesn't support sync +} \ No newline at end of file From 430b1754993457281841d8f979250c124316f172 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Tue, 9 Jan 2024 17:13:33 +1100 Subject: [PATCH 02/13] Make sure cache size is sufficient for SD card --- src/esp_littlefs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index 251fdc8..d3da311 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -719,7 +719,7 @@ static esp_err_t esp_littlefs_init_sdcard(esp_littlefs_t** efs, sdmmc_card_t* sd (*efs)->cfg.prog_size = sdcard->csd.sector_size; (*efs)->cfg.block_size = sdcard->csd.sector_size; (*efs)->cfg.block_count = sdcard->csd.capacity; - (*efs)->cfg.cache_size = CONFIG_LITTLEFS_CACHE_SIZE; + (*efs)->cfg.cache_size = MAX(CONFIG_LITTLEFS_CACHE_SIZE, sdcard->csd.sector_size); // Must not be smaller than SD sector size (*efs)->cfg.lookahead_size = CONFIG_LITTLEFS_LOOKAHEAD_SIZE; (*efs)->cfg.block_cycles = CONFIG_LITTLEFS_BLOCK_CYCLES; #if CONFIG_LITTLEFS_MULTIVERSION From bc1f1ed61598a4fd70856426806b949191a11f56 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Tue, 9 Jan 2024 17:18:31 +1100 Subject: [PATCH 03/13] Try fixing build for mainline ESP-IDF --- include/esp_littlefs.h | 2 +- src/littlefs_api.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/esp_littlefs.h b/include/esp_littlefs.h index ec4edc6..2aacdd3 100644 --- a/include/esp_littlefs.h +++ b/include/esp_littlefs.h @@ -4,7 +4,7 @@ #include "esp_err.h" #include "esp_idf_version.h" #include -#include +#include #include "esp_partition.h" #ifdef __cplusplus diff --git a/src/littlefs_api.h b/src/littlefs_api.h index 1914cb7..43bece7 100644 --- a/src/littlefs_api.h +++ b/src/littlefs_api.h @@ -9,7 +9,7 @@ #include "esp_vfs.h" #include "esp_partition.h" #include "littlefs/lfs.h" -#include +#include #ifdef __cplusplus extern "C" { From aa45b7010b0158c12da07b3af9da846289e6970c Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 10:32:37 +1100 Subject: [PATCH 04/13] sdmmc: allow toggling the SDMMC support --- CMakeLists.txt | 14 +++++++++++--- Kconfig | 7 +++++++ include/esp_littlefs.h | 9 ++++++++- src/esp_littlefs.c | 27 ++++++++++++++++++++------- src/littlefs_api.h | 12 ++++++++++++ src/littlefs_sdmmc.c | 12 ++++++++---- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c103a0..539f1f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,22 @@ cmake_minimum_required(VERSION 3.10) file(GLOB SOURCES src/littlefs/*.c) -list(APPEND SOURCES src/esp_littlefs.c src/littlefs_esp_part.c src/littlefs_sdmmc.c src/lfs_config.c) +list(APPEND SOURCES src/esp_littlefs.c src/littlefs_esp_part.c src/lfs_config.c) + +if(CONFIG_LITTLEFS_SDMMC_SUPPORT) + list(APPEND SOURCES src/littlefs_sdmmc.c) +endif() if(IDF_VERSION_MAJOR GREATER_EQUAL 5) - list(APPEND pub_requires esp_partition sdmmc) + if (CONFIG_LITTLEFS_SDMMC_SUPPORT) + list(APPEND pub_requires esp_partition sdmmc) + else() + list(APPEND pub_requires esp_partition sdmmc) + endif() else() list(APPEND pub_requires spi_flash) endif() -list(APPEND priv_requires esptool_py spi_flash vfs sdmmc) +list(APPEND priv_requires esptool_py spi_flash vfs) idf_component_register( SRCS ${SOURCES} diff --git a/Kconfig b/Kconfig index 2cdce46..2048a8c 100644 --- a/Kconfig +++ b/Kconfig @@ -1,5 +1,12 @@ menu "LittleFS" + config LITTLEFS_SDMMC_SUPPORT + bool "SDMMC support (requires ESP-IDF v5+)" + default n + help + Toggle SD card support + This requires IDF v5+ as older ESP-IDF do not support SD card erase. + config LITTLEFS_MAX_PARTITIONS int "Maximum Number of Partitions" default 3 diff --git a/include/esp_littlefs.h b/include/esp_littlefs.h index 2aacdd3..5cc9880 100644 --- a/include/esp_littlefs.h +++ b/include/esp_littlefs.h @@ -4,9 +4,12 @@ #include "esp_err.h" #include "esp_idf_version.h" #include -#include #include "esp_partition.h" +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -27,7 +30,11 @@ typedef struct { const char *base_path; /**< Mounting point. */ const char *partition_label; /**< Label of partition to use. */ const esp_partition_t* partition; /**< partition to use if partition_label is NULL */ + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT sdmmc_card_t *sdcard; /**< SD card handle to use if both esp_partition handle & partition label is NULL */ +#endif + uint8_t format_if_mount_failed:1; /**< Format the file system if it fails to mount. */ uint8_t read_only : 1; /**< Mount the partition as read-only. */ uint8_t dont_mount:1; /**< Don't attempt to mount.*/ diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index d3da311..8a1e250 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -23,7 +23,10 @@ #include #include #include + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT #include +#endif #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) #include "spi_flash_mmap.h" @@ -694,6 +697,8 @@ static void esp_littlefs_take_efs_lock(void) { xSemaphoreTake(_efs_lock, portMAX_DELAY); } + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT static esp_err_t esp_littlefs_init_sdcard(esp_littlefs_t** efs, sdmmc_card_t* sdcard, bool read_only) { /* Allocate Context */ @@ -749,6 +754,7 @@ static esp_err_t esp_littlefs_init_sdcard(esp_littlefs_t** efs, sdmmc_card_t* sd return ESP_OK; } +#endif // CONFIG_LITTLEFS_SDMMC_SUPPORT static esp_err_t esp_littlefs_init_efs(esp_littlefs_t** efs, const esp_partition_t* partition, bool read_only) { @@ -850,6 +856,7 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) goto exit; } partition = conf->partition; +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT } else if (conf->sdcard) { ESP_LOGI(ESP_LITTLEFS_TAG, "Using SD card handle %p for LittleFS mount", conf->sdcard); err = sdmmc_get_status(conf->sdcard); @@ -857,18 +864,26 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) ESP_LOGE(ESP_LITTLEFS_TAG, "Failed when checking SD card status: 0x%x", err); goto exit; } +#endif } else { ESP_LOGE(ESP_LITTLEFS_TAG, "No partition specified in configuration"); err = ESP_ERR_INVALID_ARG; goto exit; } - if (!conf->sdcard) { +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT + if (conf->sdcard) { + err = esp_littlefs_init_sdcard(&efs, conf->sdcard, conf->read_only); + if(err != ESP_OK) { + goto exit; + } + } else { +#endif uint32_t flash_page_size = g_rom_flashchip.page_size; uint32_t log_page_size = CONFIG_LITTLEFS_PAGE_SIZE; if (log_page_size % flash_page_size != 0) { ESP_LOGE(ESP_LITTLEFS_TAG, "LITTLEFS_PAGE_SIZE is not multiple of flash chip page size (%u)", - (unsigned int) flash_page_size); + (unsigned int) flash_page_size); err = ESP_ERR_INVALID_ARG; goto exit; } @@ -878,12 +893,10 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) if(err != ESP_OK) { goto exit; } - } else { - err = esp_littlefs_init_sdcard(&efs, conf->sdcard, conf->read_only); - if(err != ESP_OK) { - goto exit; - } + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT } +#endif // Mount and Error Check _efs[index] = efs; diff --git a/src/littlefs_api.h b/src/littlefs_api.h index 43bece7..a449d20 100644 --- a/src/littlefs_api.h +++ b/src/littlefs_api.h @@ -9,7 +9,11 @@ #include "esp_vfs.h" #include "esp_partition.h" #include "littlefs/lfs.h" +#include + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT #include +#endif #ifdef __cplusplus extern "C" { @@ -46,7 +50,11 @@ typedef struct _vfs_littlefs_file_t { typedef struct { lfs_t *fs; /*!< Handle to the underlying littlefs */ SemaphoreHandle_t lock; /*!< FS lock */ + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT sdmmc_card_t *sdcard; /*!< The SD card driver handle on which littlefs is located */ +#endif + const esp_partition_t* partition; /*!< The partition on which littlefs is located */ char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */ @@ -102,6 +110,8 @@ int littlefs_esp_part_erase(const struct lfs_config *c, lfs_block_t block); */ int littlefs_esp_part_sync(const struct lfs_config *c); +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT + /** * @brief Read a region in a block on SD card * @@ -144,6 +154,8 @@ int littlefs_sdmmc_erase(const struct lfs_config *c, lfs_block_t block); */ int littlefs_sdmmc_sync(const struct lfs_config *c); +#endif // CONFIG_LITTLEFS_SDMMC_SUPPORT + #ifdef __cplusplus } #endif diff --git a/src/littlefs_sdmmc.c b/src/littlefs_sdmmc.c index 28a0648..88732fa 100644 --- a/src/littlefs_sdmmc.c +++ b/src/littlefs_sdmmc.c @@ -8,14 +8,18 @@ #include #include "littlefs_api.h" +#if CONFIG_LITTLEFS_SDMMC_SUPPORT && ESP_IDF_VERSION_MAJOR < 5 +#error "SDMMC feature is only supported in ESP-IDF v5+, see: https://github.com/joltwallet/esp_littlefs/pull/170#issuecomment-1882484668" +#endif + int littlefs_sdmmc_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) { esp_littlefs_t * efs = c->context; - size_t part_off = (block * c->block_size) + off; + uint32_t part_off = (block * c->block_size) + off; esp_err_t ret = sdmmc_read_sectors(efs->sdcard, buffer, block, MIN(size / efs->cfg.read_size, 1)); if (ret != ESP_OK) { - ESP_LOGE(ESP_LITTLEFS_TAG, "failed to read addr %08x, size %08x, err=0x%x", (unsigned int) part_off, (unsigned int) size, ret); + ESP_LOGE(ESP_LITTLEFS_TAG, "Failed to read addr 0x%08lx: off 0x%08lx, block 0x%08lx, size %lu, err=0x%x", part_off, off, block, size, ret); return LFS_ERR_IO; } @@ -25,11 +29,11 @@ int littlefs_sdmmc_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t int littlefs_sdmmc_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) { esp_littlefs_t * efs = c->context; - size_t part_off = (block * c->block_size) + off; + uint32_t part_off = (block * c->block_size) + off; esp_err_t ret = sdmmc_write_sectors(efs->sdcard, buffer, block, MIN(size / efs->cfg.prog_size, 1)); if (ret != ESP_OK) { - ESP_LOGE(ESP_LITTLEFS_TAG, "failed to write addr %08x, size %08x, err=0x%x", (unsigned int) part_off, (unsigned int) size, ret); + ESP_LOGE(ESP_LITTLEFS_TAG, "Failed to write addr 0x%08lx: off 0x%08lx, block 0x%08lx, size %lu, err=0x%x", part_off, off, block, size, ret); return LFS_ERR_IO; } From 1190584e828a7bd5cd9e7f6531d79b2995df4844 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 11:32:52 +1100 Subject: [PATCH 05/13] Do a full erase when formatting SD card --- src/esp_littlefs.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index 8a1e250..d719f66 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -226,6 +226,19 @@ esp_err_t format_from_efs(esp_littlefs_t *efs) esp_littlefs_free_fds(efs); } +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT + /* Format the SD card too */ + if (efs->sdcard) { + esp_err_t ret = sdmmc_full_erase(efs->sdcard); + if (ret != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Failed to format SD card: 0x%x %s", ret, esp_err_to_name(ret)); + return ret; + } + + ESP_LOGI(ESP_LITTLEFS_TAG, "SD card formatted!"); + } +#endif + /* Format */ { int res; From f2dbd2d7edbd90948a3e061cbb322c8a5b1972d6 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 12:13:49 +1100 Subject: [PATCH 06/13] sdmmc: implement format, VFS register & deregister --- include/esp_littlefs.h | 25 ++++++++ src/esp_littlefs.c | 141 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 161 insertions(+), 5 deletions(-) diff --git a/include/esp_littlefs.h b/include/esp_littlefs.h index 5cc9880..596ec1a 100644 --- a/include/esp_littlefs.h +++ b/include/esp_littlefs.h @@ -66,6 +66,19 @@ esp_err_t esp_vfs_littlefs_register(const esp_vfs_littlefs_conf_t * conf); */ esp_err_t esp_vfs_littlefs_unregister(const char* partition_label); +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +/** + * Unregister and unmount LittleFS from VFS for SD card + * + * @param partition_label Label of the partition to unregister. + * + * @return + * - ESP_OK if successful + * - ESP_ERR_INVALID_STATE already unregistered + */ +esp_err_t esp_vfs_littlefs_unregister_sdmmc(sdmmc_card_t *sdcard); +#endif + /** * Unregister and unmount littlefs from VFS * @@ -119,6 +132,18 @@ esp_err_t esp_littlefs_format(const char* partition_label); */ esp_err_t esp_littlefs_format_partition(const esp_partition_t* partition); +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +/** + * Format the LittleFS on a SD card + * + * @param partition partition to format. + * @return + * - ESP_OK if successful + * - ESP_FAIL on error + */ +esp_err_t esp_littlefs_format_sdmmc(sdmmc_card_t *sdcard); +#endif + /** * Get information for littlefs * diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index d719f66..c4a7233 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -118,6 +118,7 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf); static esp_err_t esp_littlefs_by_label(const char* label, int * index); static esp_err_t esp_littlefs_by_partition(const esp_partition_t* part, int*index); +static esp_err_t esp_littlefs_by_sdmmc_handle(sdmmc_card_t *handle, int *index); static esp_err_t esp_littlefs_get_empty(int *index); static void esp_littlefs_free(esp_littlefs_t ** efs); @@ -241,13 +242,23 @@ esp_err_t format_from_efs(esp_littlefs_t *efs) /* Format */ { - int res; + esp_err_t res = ESP_OK; ESP_LOGV(ESP_LITTLEFS_TAG, "Formatting filesystem"); - /* Need to write explicit block_count to cfg */ + /* Need to write explicit block_count to cfg; but skip if it's the SD card */ +#ifndef CONFIG_LITTLEFS_SDMMC_SUPPORT efs->cfg.block_count = efs->partition->size / efs->cfg.block_size; res = lfs_format(efs->fs, &efs->cfg); efs->cfg.block_count = 0; +#else + if (efs->sdcard) { + res = lfs_format(efs->fs, &efs->cfg); + } else { + efs->cfg.block_count = efs->partition->size / efs->cfg.block_size; + res = lfs_format(efs->fs, &efs->cfg); + efs->cfg.block_count = 0; + } +#endif if( res != LFS_ERR_OK ) { ESP_LOGE(ESP_LITTLEFS_TAG, "Failed to format filesystem"); @@ -340,8 +351,17 @@ esp_err_t esp_vfs_littlefs_register(const esp_vfs_littlefs_conf_t * conf) } int index; - if(conf->partition_label) - { + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT + if (conf->sdcard) { + if (esp_littlefs_by_sdmmc_handle(conf->sdcard, &index) != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Unable to find SD card \"%p\"", conf->sdcard); + return ESP_ERR_NOT_FOUND; + } + } else if(conf->partition_label) { +#else + if(conf->partition_label) { +#endif if (esp_littlefs_by_label(conf->partition_label, &index) != ESP_OK) { ESP_LOGE(ESP_LITTLEFS_TAG, "Unable to find partition \"%s\"", conf->partition_label); return ESP_ERR_NOT_FOUND; @@ -384,6 +404,29 @@ esp_err_t esp_vfs_littlefs_unregister(const char* partition_label) return ESP_OK; } +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +esp_err_t esp_vfs_littlefs_unregister_sdmmc(sdmmc_card_t *sdcard) +{ + assert(sdcard); + int index; + if (esp_littlefs_by_sdmmc_handle(sdcard, &index) != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Partition was never registered."); + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGV(ESP_LITTLEFS_TAG, "Unregistering SD card \"%p\"", sdcard); + esp_err_t err = esp_vfs_unregister(_efs[index]->base_path); + if (err != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Failed to unregister SD card \"%p\"", sdcard); + return err; + } + + esp_littlefs_free(&_efs[index]); + _efs[index] = NULL; + return ESP_OK; +} +#endif + esp_err_t esp_vfs_littlefs_unregister_partition(const esp_partition_t* partition) { assert(partition); int index; @@ -485,6 +528,53 @@ esp_err_t esp_littlefs_format_partition(const esp_partition_t* partition) { return err; } +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +esp_err_t esp_littlefs_format_sdmmc(sdmmc_card_t *sdcard) +{ + assert(sdcard); + + bool efs_free = false; + int index = -1; + esp_err_t err; + + ESP_LOGV(ESP_LITTLEFS_TAG, "Formatting sdcard %p", sdcard); + + /* Get a context */ + err = esp_littlefs_by_sdmmc_handle(sdcard, &index); + + if( err != ESP_OK ){ + /* Create a tmp context */ + ESP_LOGV(ESP_LITTLEFS_TAG, "Temporarily creating EFS context."); + efs_free = true; + const esp_vfs_littlefs_conf_t conf = { + /* base_name not necessary for initializing */ + .dont_mount = true, + .partition_label = NULL, + .partition = NULL, + .sdcard = sdcard, + }; + + err = esp_littlefs_init(&conf); + if( err != ESP_OK ) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Failed to initialize to format."); + goto exit; + } + + err = esp_littlefs_by_sdmmc_handle(sdcard, &index); + if ( err != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Error obtaining context."); + goto exit; + } + } + + err = format_from_efs(_efs[index]); + +exit: + if(efs_free && index>=0) esp_littlefs_free(&_efs[index]); + return err; +} +#endif + /******************** * Static Functions * ********************/ @@ -656,6 +746,32 @@ static esp_err_t esp_littlefs_by_label(const char* label, int * index){ return ESP_ERR_NOT_FOUND; } +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +static esp_err_t esp_littlefs_by_sdmmc_handle(sdmmc_card_t *handle, int *index) +{ + int i; + esp_littlefs_t * p; + + if(!handle || !index) return ESP_ERR_INVALID_ARG; + + ESP_LOGV(ESP_LITTLEFS_TAG, "Searching for existing filesystem for SD handle %p", handle); + + for (i = 0; i < CONFIG_LITTLEFS_MAX_PARTITIONS; i++) { + p = _efs[i]; + if (p && p->sdcard) { + if (p->sdcard == handle) { + *index = i; + ESP_LOGV(ESP_LITTLEFS_TAG, "Found existing filesystem %p at index %d", p->sdcard, *index); + return ESP_OK; + } + } + } + + ESP_LOGV(ESP_LITTLEFS_TAG, "Existing filesystem %p not found", p->sdcard); + return ESP_ERR_NOT_FOUND; +} +#endif + /** * @brief Get the index of an unallocated LittleFS slot. * @param[out] index Indexd of free LittleFS slot @@ -920,8 +1036,15 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) if (conf->format_if_mount_failed && res != LFS_ERR_OK) { ESP_LOGW(ESP_LITTLEFS_TAG, "mount failed, %s (%i). formatting...", esp_littlefs_errno(res), res); +#ifndef CONFIG_LITTLEFS_SDMMC_SUPPORT err = esp_littlefs_format_partition(efs->partition); - +#else + if (conf->sdcard) { + err = esp_littlefs_format_sdmmc(conf->sdcard); + } else { + err = esp_littlefs_format_partition(efs->partition); + } +#endif if(err != ESP_OK) { ESP_LOGE(ESP_LITTLEFS_TAG, "format failed"); err = ESP_FAIL; @@ -938,7 +1061,15 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) efs->cache = esp_littlefs_calloc(sizeof(*efs->cache), efs->cache_size); if(conf->grow_on_mount){ +#ifndef CONFIG_LITTLEFS_SDMMC_SUPPORT res = lfs_fs_grow(efs->fs, efs->partition->size / efs->cfg.block_size); +#else + if (efs->sdcard) { + res = lfs_fs_grow(efs->fs, efs->sdcard->csd.capacity); + } else { + res = lfs_fs_grow(efs->fs, efs->partition->size / efs->cfg.block_size); + } +#endif if (res != LFS_ERR_OK) { ESP_LOGE(ESP_LITTLEFS_TAG, "FS grow failed, %s (%i)", esp_littlefs_errno(res), res); err = ESP_FAIL; From 86f15aa60f11fa1f31802e05cf50dcc268d1af94 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 12:22:18 +1100 Subject: [PATCH 07/13] Try fix linting error --- src/esp_littlefs.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index c4a7233..e9f4f02 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -749,25 +749,23 @@ static esp_err_t esp_littlefs_by_label(const char* label, int * index){ #ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT static esp_err_t esp_littlefs_by_sdmmc_handle(sdmmc_card_t *handle, int *index) { - int i; - esp_littlefs_t * p; - if(!handle || !index) return ESP_ERR_INVALID_ARG; ESP_LOGV(ESP_LITTLEFS_TAG, "Searching for existing filesystem for SD handle %p", handle); - for (i = 0; i < CONFIG_LITTLEFS_MAX_PARTITIONS; i++) { - p = _efs[i]; - if (p && p->sdcard) { + for (int i = 0; i < CONFIG_LITTLEFS_MAX_PARTITIONS; i++) { + esp_littlefs_t *p = _efs[i]; + if (!p) continue; + if (p->sdcard) { if (p->sdcard == handle) { *index = i; - ESP_LOGV(ESP_LITTLEFS_TAG, "Found existing filesystem %p at index %d", p->sdcard, *index); + ESP_LOGV(ESP_LITTLEFS_TAG, "Found existing filesystem %p at index %d", handle, *index); return ESP_OK; } } } - ESP_LOGV(ESP_LITTLEFS_TAG, "Existing filesystem %p not found", p->sdcard); + ESP_LOGV(ESP_LITTLEFS_TAG, "Existing filesystem %p not found", handle); return ESP_ERR_NOT_FOUND; } #endif From f007e87353bd0cf29a9bfbb0f41c7c4e64f54310 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 12:26:09 +1100 Subject: [PATCH 08/13] Try fix compile error --- src/esp_littlefs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index e9f4f02..f29a816 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -118,7 +118,10 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf); static esp_err_t esp_littlefs_by_label(const char* label, int * index); static esp_err_t esp_littlefs_by_partition(const esp_partition_t* part, int*index); + +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT static esp_err_t esp_littlefs_by_sdmmc_handle(sdmmc_card_t *handle, int *index); +#endif static esp_err_t esp_littlefs_get_empty(int *index); static void esp_littlefs_free(esp_littlefs_t ** efs); From dc62c8491466d3681f0f767cb95ec89b4037fa25 Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 14:39:29 +1100 Subject: [PATCH 09/13] sdmmc: implement get info API --- include/esp_littlefs.h | 19 +++++++++++++++++-- src/esp_littlefs.c | 12 ++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/esp_littlefs.h b/include/esp_littlefs.h index 596ec1a..9d63d8d 100644 --- a/include/esp_littlefs.h +++ b/include/esp_littlefs.h @@ -70,7 +70,7 @@ esp_err_t esp_vfs_littlefs_unregister(const char* partition_label); /** * Unregister and unmount LittleFS from VFS for SD card * - * @param partition_label Label of the partition to unregister. + * @param sdcard SD card to unregister. * * @return * - ESP_OK if successful @@ -136,7 +136,7 @@ esp_err_t esp_littlefs_format_partition(const esp_partition_t* partition); /** * Format the LittleFS on a SD card * - * @param partition partition to format. + * @param sdcard SD card to format * @return * - ESP_OK if successful * - ESP_FAIL on error @@ -170,6 +170,21 @@ esp_err_t esp_littlefs_info(const char* partition_label, size_t* total_bytes, si */ esp_err_t esp_littlefs_partition_info(const esp_partition_t* partition, size_t *total_bytes, size_t *used_bytes); +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +/** + * Get information for littlefs on SD card + * + * @param[in] sdcard the SD card to get info for. + * @param[out] total_bytes Size of the file system + * @param[out] used_bytes Current used bytes in the file system + * + * @return + * - ESP_OK if success + * - ESP_ERR_INVALID_STATE if not mounted + */ +esp_err_t esp_littlefs_sdmmc_info(sdmmc_card_t *sdcard, size_t *total_bytes, size_t *used_bytes); +#endif + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index f29a816..188a3c4 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -342,6 +342,18 @@ esp_err_t esp_littlefs_partition_info(const esp_partition_t* partition, size_t * return ESP_OK; } +esp_err_t esp_littlefs_sdmmc_info(sdmmc_card_t *sdcard, size_t *total_bytes, size_t *used_bytes) +{ + int index; + esp_err_t err; + + err = esp_littlefs_by_sdmmc_handle(sdcard, &index); + if(err != ESP_OK) return err; + get_total_and_used_bytes(_efs[index], total_bytes, used_bytes); + + return ESP_OK; +} + esp_err_t esp_vfs_littlefs_register(const esp_vfs_littlefs_conf_t * conf) { assert(conf->base_path); From 3e5830bc60a14e5c7a60aa1af25cd428fbd9fb1a Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 14:43:02 +1100 Subject: [PATCH 10/13] sdmmc: implement mount check API for SDMMC --- include/esp_littlefs.h | 13 +++++++++++++ src/esp_littlefs.c | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/esp_littlefs.h b/include/esp_littlefs.h index 9d63d8d..7c2bb40 100644 --- a/include/esp_littlefs.h +++ b/include/esp_littlefs.h @@ -112,6 +112,19 @@ bool esp_littlefs_mounted(const char* partition_label); */ bool esp_littlefs_partition_mounted(const esp_partition_t* partition); +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +/** + * Check if littlefs is mounted + * + * @param sdcard SD card to check. + * + * @return + * - true if mounted + * - false if not mounted + */ +bool esp_littlefs_sdmmc_mounted(sdmmc_card_t *sdcard); +#endif + /** * Format the littlefs partition * diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index 188a3c4..f5fd7ba 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -320,6 +320,17 @@ bool esp_littlefs_partition_mounted(const esp_partition_t* partition) { return _efs[index]->cache_size > 0; } +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT +bool esp_littlefs_sdmmc_mounted(sdmmc_card_t *sdcard) +{ + int index; + esp_err_t err = esp_littlefs_by_sdmmc_handle(sdcard, &index); + + if(err != ESP_OK) return false; + return _efs[index]->cache_size > 0; +} +#endif + esp_err_t esp_littlefs_info(const char* partition_label, size_t *total_bytes, size_t *used_bytes){ int index; esp_err_t err; @@ -342,6 +353,7 @@ esp_err_t esp_littlefs_partition_info(const esp_partition_t* partition, size_t * return ESP_OK; } +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT esp_err_t esp_littlefs_sdmmc_info(sdmmc_card_t *sdcard, size_t *total_bytes, size_t *used_bytes) { int index; @@ -353,6 +365,7 @@ esp_err_t esp_littlefs_sdmmc_info(sdmmc_card_t *sdcard, size_t *total_bytes, siz return ESP_OK; } +#endif esp_err_t esp_vfs_littlefs_register(const esp_vfs_littlefs_conf_t * conf) { From 536651bbebe74c1419a91ad715738224c6213d1b Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 15:20:38 +1100 Subject: [PATCH 11/13] Code cleanup as per review comment --- src/esp_littlefs.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index f5fd7ba..572034c 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -249,14 +249,12 @@ esp_err_t format_from_efs(esp_littlefs_t *efs) ESP_LOGV(ESP_LITTLEFS_TAG, "Formatting filesystem"); /* Need to write explicit block_count to cfg; but skip if it's the SD card */ -#ifndef CONFIG_LITTLEFS_SDMMC_SUPPORT - efs->cfg.block_count = efs->partition->size / efs->cfg.block_size; - res = lfs_format(efs->fs, &efs->cfg); - efs->cfg.block_count = 0; -#else +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT if (efs->sdcard) { res = lfs_format(efs->fs, &efs->cfg); - } else { + } else +#else + { efs->cfg.block_count = efs->partition->size / efs->cfg.block_size; res = lfs_format(efs->fs, &efs->cfg); efs->cfg.block_count = 0; @@ -380,21 +378,21 @@ esp_err_t esp_vfs_littlefs_register(const esp_vfs_littlefs_conf_t * conf) int index; + if(conf->partition_label) { + if (esp_littlefs_by_label(conf->partition_label, &index) != ESP_OK) { + ESP_LOGE(ESP_LITTLEFS_TAG, "Unable to find partition \"%s\"", conf->partition_label); + return ESP_ERR_NOT_FOUND; + } + } #ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT - if (conf->sdcard) { + else if (conf->sdcard) { if (esp_littlefs_by_sdmmc_handle(conf->sdcard, &index) != ESP_OK) { ESP_LOGE(ESP_LITTLEFS_TAG, "Unable to find SD card \"%p\"", conf->sdcard); return ESP_ERR_NOT_FOUND; } - } else if(conf->partition_label) { -#else - if(conf->partition_label) { + } #endif - if (esp_littlefs_by_label(conf->partition_label, &index) != ESP_OK) { - ESP_LOGE(ESP_LITTLEFS_TAG, "Unable to find partition \"%s\"", conf->partition_label); - return ESP_ERR_NOT_FOUND; - } - } else { + else { if (esp_littlefs_by_partition(conf->partition, &index) != ESP_OK) { ESP_LOGE(ESP_LITTLEFS_TAG, "Unable to find partition \"0x%08"PRIX32"\"", conf->partition->address); return ESP_ERR_NOT_FOUND; @@ -878,7 +876,7 @@ static esp_err_t esp_littlefs_init_sdcard(esp_littlefs_t** efs, sdmmc_card_t* sd (*efs)->cfg.read_size = sdcard->csd.sector_size; (*efs)->cfg.prog_size = sdcard->csd.sector_size; (*efs)->cfg.block_size = sdcard->csd.sector_size; - (*efs)->cfg.block_count = sdcard->csd.capacity; + (*efs)->cfg.block_count = max_allowed_blk_cnt; (*efs)->cfg.cache_size = MAX(CONFIG_LITTLEFS_CACHE_SIZE, sdcard->csd.sector_size); // Must not be smaller than SD sector size (*efs)->cfg.lookahead_size = CONFIG_LITTLEFS_LOOKAHEAD_SIZE; (*efs)->cfg.block_cycles = CONFIG_LITTLEFS_BLOCK_CYCLES; @@ -1032,8 +1030,9 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) if(err != ESP_OK) { goto exit; } - } else { + } else #endif + { uint32_t flash_page_size = g_rom_flashchip.page_size; uint32_t log_page_size = CONFIG_LITTLEFS_PAGE_SIZE; if (log_page_size % flash_page_size != 0) { @@ -1048,10 +1047,7 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) if(err != ESP_OK) { goto exit; } - -#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT } -#endif // Mount and Error Check _efs[index] = efs; @@ -1062,12 +1058,12 @@ static esp_err_t esp_littlefs_init(const esp_vfs_littlefs_conf_t* conf) if (conf->format_if_mount_failed && res != LFS_ERR_OK) { ESP_LOGW(ESP_LITTLEFS_TAG, "mount failed, %s (%i). formatting...", esp_littlefs_errno(res), res); -#ifndef CONFIG_LITTLEFS_SDMMC_SUPPORT - err = esp_littlefs_format_partition(efs->partition); -#else +#ifdef CONFIG_LITTLEFS_SDMMC_SUPPORT if (conf->sdcard) { err = esp_littlefs_format_sdmmc(conf->sdcard); - } else { + } else +#else + { err = esp_littlefs_format_partition(efs->partition); } #endif From 74cb0385dd80035d7c02edc167d4a51a816eeedb Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 15:21:43 +1100 Subject: [PATCH 12/13] Limit SD card size --- src/esp_littlefs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index 572034c..d23b9b3 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -872,6 +872,16 @@ static esp_err_t esp_littlefs_init_sdcard(esp_littlefs_t** efs, sdmmc_card_t* sd (*efs)->cfg.erase = littlefs_sdmmc_erase; (*efs)->cfg.sync = littlefs_sdmmc_sync; + size_t max_allowed_blk_cnt = 0; + if (((uint64_t)sdcard->csd.capacity * (uint64_t)sdcard->csd.sector_size) > SIZE_MAX) { + max_allowed_blk_cnt = SIZE_MAX / sdcard->csd.sector_size; + ESP_LOGW(ESP_LITTLEFS_TAG, "SD card is too big (sector=%d, count=%d; total=%llu bytes), throttling to maximum possible %u blocks", + sdcard->csd.sector_size, sdcard->csd.capacity, + (((uint64_t)sdcard->csd.capacity * (uint64_t)sdcard->csd.sector_size)), max_allowed_blk_cnt); + } else { + max_allowed_blk_cnt = sdcard->csd.capacity; + } + // block device configuration (*efs)->cfg.read_size = sdcard->csd.sector_size; (*efs)->cfg.prog_size = sdcard->csd.sector_size; From ca0e1395bc4ef0c0929c8767e85f5840ba6e3e6c Mon Sep 17 00:00:00 2001 From: Jackson Ming Hu Date: Wed, 10 Jan 2024 15:41:21 +1100 Subject: [PATCH 13/13] Temporary fix on CMake REQUIRES --- CMakeLists.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 539f1f5..bd6d847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,15 +8,11 @@ if(CONFIG_LITTLEFS_SDMMC_SUPPORT) endif() if(IDF_VERSION_MAJOR GREATER_EQUAL 5) - if (CONFIG_LITTLEFS_SDMMC_SUPPORT) - list(APPEND pub_requires esp_partition sdmmc) - else() - list(APPEND pub_requires esp_partition sdmmc) - endif() + list(APPEND pub_requires esp_partition) else() list(APPEND pub_requires spi_flash) endif() -list(APPEND priv_requires esptool_py spi_flash vfs) +list(APPEND priv_requires esptool_py spi_flash vfs sdmmc) idf_component_register( SRCS ${SOURCES}