Skip to content

Commit 5684328

Browse files
committed
Merge branch 'feature/fatfs_allocation_unit_size' into 'master'
fatfs: add option to set allocation unit size See merge request idf/esp-idf!1760
2 parents e381c6a + 95ff768 commit 5684328

File tree

8 files changed

+87
-15
lines changed

8 files changed

+87
-15
lines changed

components/fatfs/src/esp_vfs_fat.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,26 @@ esp_err_t esp_vfs_fat_unregister_path(const char* base_path);
8888
* @brief Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount functions
8989
*/
9090
typedef struct {
91-
bool format_if_mount_failed; ///< If FAT partition can not be mounted, and this parameter is true, create partition table and format the filesystem
91+
/**
92+
* If FAT partition can not be mounted, and this parameter is true,
93+
* create partition table and format the filesystem.
94+
*/
95+
bool format_if_mount_failed;
9296
int max_files; ///< Max number of open files
97+
/**
98+
* If format_if_mount_failed is set, and mount fails, format the card
99+
* with given allocation unit size. Must be a power of 2, between sector
100+
* size and 128 * sector size.
101+
* For SD cards, sector size is always 512 bytes. For wear_levelling,
102+
* sector size is determined by CONFIG_WL_SECTOR_SIZE option.
103+
*
104+
* Using larger allocation unit size will result in higher read/write
105+
* performance and higher overhead when storing small files.
106+
*
107+
* Setting this field to 0 will result in allocation unit set to the
108+
* sector size.
109+
*/
110+
size_t allocation_unit_size;
93111
} esp_vfs_fat_mount_config_t;
94112

95113
// Compatibility definition
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include "esp_vfs_fat.h"
18+
#include <sys/param.h>
19+
#include <stddef.h>
20+
21+
static inline size_t esp_vfs_fat_get_allocation_unit_size(
22+
size_t sector_size, size_t requested_size)
23+
{
24+
size_t alloc_unit_size = requested_size;
25+
const size_t max_sectors_per_cylinder = 128;
26+
const size_t max_size = sector_size * max_sectors_per_cylinder;
27+
alloc_unit_size = MAX(alloc_unit_size, sector_size);
28+
alloc_unit_size = MIN(alloc_unit_size, max_size);
29+
return alloc_unit_size;
30+
}

components/fatfs/src/vfs_fat_sdmmc.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "esp_log.h"
1818
#include "esp_vfs.h"
1919
#include "esp_vfs_fat.h"
20+
#include "vfs_fat_internal.h"
2021
#include "driver/sdmmc_host.h"
2122
#include "driver/sdspi_host.h"
2223
#include "sdmmc_cmd.h"
@@ -112,16 +113,23 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
112113
goto fail;
113114
}
114115
ESP_LOGW(TAG, "partitioning card");
115-
DWORD plist[] = {100, 0, 0, 0};
116116
workbuf = malloc(workbuf_size);
117+
if (workbuf == NULL) {
118+
err = ESP_ERR_NO_MEM;
119+
goto fail;
120+
}
121+
DWORD plist[] = {100, 0, 0, 0};
117122
res = f_fdisk(s_pdrv, plist, workbuf);
118123
if (res != FR_OK) {
119124
err = ESP_FAIL;
120125
ESP_LOGD(TAG, "f_fdisk failed (%d)", res);
121126
goto fail;
122127
}
123-
ESP_LOGW(TAG, "formatting card");
124-
res = f_mkfs(drv, FM_ANY, s_card->csd.sector_size, workbuf, workbuf_size);
128+
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(
129+
s_card->csd.sector_size,
130+
mount_config->allocation_unit_size);
131+
ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size);
132+
res = f_mkfs(drv, FM_ANY, alloc_unit_size, workbuf, workbuf_size);
125133
if (res != FR_OK) {
126134
err = ESP_FAIL;
127135
ESP_LOGD(TAG, "f_mkfs failed (%d)", res);

components/fatfs/src/vfs_fat_spiflash.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "esp_log.h"
1818
#include "esp_vfs.h"
1919
#include "esp_vfs_fat.h"
20+
#include "vfs_fat_internal.h"
2021
#include "diskio.h"
2122

2223
#include "wear_levelling.h"
@@ -78,8 +79,15 @@ esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path,
7879
goto fail;
7980
}
8081
workbuf = malloc(workbuf_size);
81-
ESP_LOGI(TAG, "Formatting FATFS partition");
82-
fresult = f_mkfs(drv, FM_ANY | FM_SFD, workbuf_size, workbuf, workbuf_size);
82+
if (workbuf == NULL) {
83+
result = ESP_ERR_NO_MEM;
84+
goto fail;
85+
}
86+
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(
87+
CONFIG_WL_SECTOR_SIZE,
88+
mount_config->allocation_unit_size);
89+
ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size);
90+
fresult = f_mkfs(drv, FM_ANY | FM_SFD, alloc_unit_size, workbuf, workbuf_size);
8391
if (fresult != FR_OK) {
8492
result = ESP_FAIL;
8593
ESP_LOGE(TAG, "f_mkfs failed (%d)", fresult);

components/fatfs/test/test_fatfs_sdmmc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ static void speed_test(void* buf, size_t buf_size, size_t file_size, bool write)
185185
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
186186
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
187187
.format_if_mount_failed = write,
188-
.max_files = 5
188+
.max_files = 5,
189+
.allocation_unit_size = 64 * 1024
189190
};
190191
TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL));
191192

examples/storage/sd_card/main/sd_card_example_main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ void app_main(void)
8181
// formatted in case when mounting fails.
8282
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
8383
.format_if_mount_failed = false,
84-
.max_files = 5
84+
.max_files = 5,
85+
.allocation_unit_size = 16 * 1024
8586
};
8687

8788
// Use settings defined above to initialize SD card and mount FAT filesystem.

examples/storage/wear_levelling/README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SD Card example
1+
# Wear levelling example
22

33
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:
44

@@ -15,9 +15,14 @@ This example demonstrates how to use wear levelling library and FATFS library to
1515
Here is an typical example console output.
1616

1717
```
18-
Try to open file ...
19-
I (239) wear_level: Reading file
20-
Read from file: 'Hello User! I'm happy to see you!1'
21-
W (239) wear_levelling: wl_unmount Delete driver
18+
I (280) example: Mounting FAT filesystem
19+
W (440) vfs_fat_spiflash: f_mount failed (13)
20+
I (440) vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=4096
21+
I (660) vfs_fat_spiflash: Mounting again
22+
I (660) example: Opening file
23+
I (910) example: File written
24+
I (910) example: Reading file
25+
I (920) example: Read from file: 'written using ESP-IDF v3.1-dev-171-gf9ad17eee-dirty'
26+
I (920) example: Unmounting FAT filesystem
27+
I (1000) example: Done
2228
```
23-

examples/storage/wear_levelling/main/wear_levelling_example_main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ void app_main(void)
3232
// and allow format partition in case if it is new one and was not formated before
3333
const esp_vfs_fat_mount_config_t mount_config = {
3434
.max_files = 4,
35-
.format_if_mount_failed = true
35+
.format_if_mount_failed = true,
36+
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE
3637
};
3738
esp_err_t err = esp_vfs_fat_spiflash_mount(base_path, "storage", &mount_config, &s_wl_handle);
3839
if (err != ESP_OK) {

0 commit comments

Comments
 (0)