diff --git a/components/fatfs/src/esp_vfs_fat.h b/components/fatfs/src/esp_vfs_fat.h index 278e427c5..bd86e681a 100644 --- a/components/fatfs/src/esp_vfs_fat.h +++ b/components/fatfs/src/esp_vfs_fat.h @@ -88,8 +88,26 @@ esp_err_t esp_vfs_fat_unregister_path(const char* base_path); * @brief Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount functions */ typedef struct { - bool format_if_mount_failed; ///< If FAT partition can not be mounted, and this parameter is true, create partition table and format the filesystem + /** + * If FAT partition can not be mounted, and this parameter is true, + * create partition table and format the filesystem. + */ + bool format_if_mount_failed; int max_files; ///< Max number of open files + /** + * If format_if_mount_failed is set, and mount fails, format the card + * with given allocation unit size. Must be a power of 2, between sector + * size and 128 * sector size. + * For SD cards, sector size is always 512 bytes. For wear_levelling, + * sector size is determined by CONFIG_WL_SECTOR_SIZE option. + * + * Using larger allocation unit size will result in higher read/write + * performance and higher overhead when storing small files. + * + * Setting this field to 0 will result in allocation unit set to the + * sector size. + */ + size_t allocation_unit_size; } esp_vfs_fat_mount_config_t; // Compatibility definition diff --git a/components/fatfs/src/vfs_fat_internal.h b/components/fatfs/src/vfs_fat_internal.h new file mode 100644 index 000000000..dc3bae271 --- /dev/null +++ b/components/fatfs/src/vfs_fat_internal.h @@ -0,0 +1,30 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_vfs_fat.h" +#include +#include + +static inline size_t esp_vfs_fat_get_allocation_unit_size( + size_t sector_size, size_t requested_size) +{ + size_t alloc_unit_size = requested_size; + const size_t max_sectors_per_cylinder = 128; + const size_t max_size = sector_size * max_sectors_per_cylinder; + alloc_unit_size = MAX(alloc_unit_size, sector_size); + alloc_unit_size = MIN(alloc_unit_size, max_size); + return alloc_unit_size; +} diff --git a/components/fatfs/src/vfs_fat_sdmmc.c b/components/fatfs/src/vfs_fat_sdmmc.c index 5e79d4a9f..f4128d68f 100644 --- a/components/fatfs/src/vfs_fat_sdmmc.c +++ b/components/fatfs/src/vfs_fat_sdmmc.c @@ -17,6 +17,7 @@ #include "esp_log.h" #include "esp_vfs.h" #include "esp_vfs_fat.h" +#include "vfs_fat_internal.h" #include "driver/sdmmc_host.h" #include "driver/sdspi_host.h" #include "sdmmc_cmd.h" @@ -120,8 +121,11 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, ESP_LOGD(TAG, "f_fdisk failed (%d)", res); goto fail; } - ESP_LOGW(TAG, "formatting card"); - res = f_mkfs(drv, FM_ANY, s_card->csd.sector_size, workbuf, workbuf_size); + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( + s_card->csd.sector_size, + mount_config->allocation_unit_size); + ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size); + res = f_mkfs(drv, FM_ANY, alloc_unit_size, workbuf, workbuf_size); if (res != FR_OK) { err = ESP_FAIL; ESP_LOGD(TAG, "f_mkfs failed (%d)", res); diff --git a/components/fatfs/src/vfs_fat_spiflash.c b/components/fatfs/src/vfs_fat_spiflash.c index 2e90468d2..3f874eda7 100644 --- a/components/fatfs/src/vfs_fat_spiflash.c +++ b/components/fatfs/src/vfs_fat_spiflash.c @@ -17,6 +17,7 @@ #include "esp_log.h" #include "esp_vfs.h" #include "esp_vfs_fat.h" +#include "vfs_fat_internal.h" #include "diskio.h" #include "wear_levelling.h" @@ -78,8 +79,11 @@ esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path, goto fail; } workbuf = malloc(workbuf_size); - ESP_LOGI(TAG, "Formatting FATFS partition"); - fresult = f_mkfs(drv, FM_ANY | FM_SFD, workbuf_size, workbuf, workbuf_size); + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( + CONFIG_WL_SECTOR_SIZE, + mount_config->allocation_unit_size); + ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); + fresult = f_mkfs(drv, FM_ANY | FM_SFD, alloc_unit_size, workbuf, workbuf_size); if (fresult != FR_OK) { result = ESP_FAIL; ESP_LOGE(TAG, "f_mkfs failed (%d)", fresult); diff --git a/components/fatfs/test/test_fatfs_sdmmc.c b/components/fatfs/test/test_fatfs_sdmmc.c index 3610511a9..5b6a2471e 100644 --- a/components/fatfs/test/test_fatfs_sdmmc.c +++ b/components/fatfs/test/test_fatfs_sdmmc.c @@ -185,7 +185,8 @@ static void speed_test(void* buf, size_t buf_size, size_t file_size, bool write) sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = write, - .max_files = 5 + .max_files = 5, + .allocation_unit_size = 64 * 1024 }; TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL)); diff --git a/examples/storage/sd_card/main/sd_card_example_main.c b/examples/storage/sd_card/main/sd_card_example_main.c index 459673e95..bf9b5deab 100644 --- a/examples/storage/sd_card/main/sd_card_example_main.c +++ b/examples/storage/sd_card/main/sd_card_example_main.c @@ -81,7 +81,8 @@ void app_main(void) // formatted in case when mounting fails. esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = false, - .max_files = 5 + .max_files = 5, + .allocation_unit_size = 16 * 1024 }; // Use settings defined above to initialize SD card and mount FAT filesystem. diff --git a/examples/storage/wear_levelling/main/wear_levelling_example_main.c b/examples/storage/wear_levelling/main/wear_levelling_example_main.c index dd02542fc..474b608c5 100644 --- a/examples/storage/wear_levelling/main/wear_levelling_example_main.c +++ b/examples/storage/wear_levelling/main/wear_levelling_example_main.c @@ -32,7 +32,8 @@ void app_main(void) // and allow format partition in case if it is new one and was not formated before const esp_vfs_fat_mount_config_t mount_config = { .max_files = 4, - .format_if_mount_failed = true + .format_if_mount_failed = true, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE }; esp_err_t err = esp_vfs_fat_spiflash_mount(base_path, "storage", &mount_config, &s_wl_handle); if (err != ESP_OK) {