Merge branch 'feature/fatfs_allocation_unit_size' into 'master'

fatfs: add option to set allocation unit size

See merge request idf/esp-idf!1760
This commit is contained in:
Ivan Grokhotkov 2018-02-11 16:43:39 +08:00
commit 56843281c7
8 changed files with 87 additions and 15 deletions

View file

@ -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

View file

@ -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 <sys/param.h>
#include <stddef.h>
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;
}

View file

@ -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"
@ -112,16 +113,23 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
goto fail;
}
ESP_LOGW(TAG, "partitioning card");
DWORD plist[] = {100, 0, 0, 0};
workbuf = malloc(workbuf_size);
if (workbuf == NULL) {
err = ESP_ERR_NO_MEM;
goto fail;
}
DWORD plist[] = {100, 0, 0, 0};
res = f_fdisk(s_pdrv, plist, workbuf);
if (res != FR_OK) {
err = ESP_FAIL;
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);

View file

@ -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,15 @@ 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);
if (workbuf == NULL) {
result = ESP_ERR_NO_MEM;
goto fail;
}
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);

View file

@ -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));

View file

@ -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.

View file

@ -1,4 +1,4 @@
# SD Card example
# Wear levelling example
This example demonstrates how to use wear levelling library and FATFS library to store files in a partition inside SPI flash. Example does the following steps:
@ -15,9 +15,14 @@ This example demonstrates how to use wear levelling library and FATFS library to
Here is an typical example console output.
```
Try to open file ...
I (239) wear_level: Reading file
Read from file: 'Hello User! I'm happy to see you!1'
W (239) wear_levelling: wl_unmount Delete driver
I (280) example: Mounting FAT filesystem
W (440) vfs_fat_spiflash: f_mount failed (13)
I (440) vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=4096
I (660) vfs_fat_spiflash: Mounting again
I (660) example: Opening file
I (910) example: File written
I (910) example: Reading file
I (920) example: Read from file: 'written using ESP-IDF v3.1-dev-171-gf9ad17eee-dirty'
I (920) example: Unmounting FAT filesystem
I (1000) example: Done
```

View file

@ -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) {