mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
Merge branch 'feat/fatfs_support_sector_less_than_128' into 'master'
feat(fatfs): enable partition handling for sectors less than 128 Closes IDF-8538 See merge request espressif/esp-idf!33569
This commit is contained in:
commit
2c5dcc977e
@ -1,10 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import Any, List, Optional
|
||||
from typing import Any
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
from fatfs_utils.boot_sector import BootSector
|
||||
from fatfs_utils.exceptions import NoFreeClusterException
|
||||
@ -12,10 +13,16 @@ from fatfs_utils.fat import FAT
|
||||
from fatfs_utils.fatfs_state import FATFSState
|
||||
from fatfs_utils.fs_object import Directory
|
||||
from fatfs_utils.long_filename_utils import get_required_lfn_entries_count
|
||||
from fatfs_utils.utils import (BYTES_PER_DIRECTORY_ENTRY, FATFS_INCEPTION, FATFS_MIN_ALLOC_UNIT,
|
||||
RESERVED_CLUSTERS_COUNT, FATDefaults, get_args_for_partition_generator,
|
||||
get_fat_sectors_count, get_non_data_sectors_cnt, read_filesystem,
|
||||
required_clusters_count)
|
||||
from fatfs_utils.utils import BYTES_PER_DIRECTORY_ENTRY
|
||||
from fatfs_utils.utils import FATDefaults
|
||||
from fatfs_utils.utils import FATFS_INCEPTION
|
||||
from fatfs_utils.utils import FATFS_MIN_ALLOC_UNIT
|
||||
from fatfs_utils.utils import get_args_for_partition_generator
|
||||
from fatfs_utils.utils import get_fat_sectors_count
|
||||
from fatfs_utils.utils import get_non_data_sectors_cnt
|
||||
from fatfs_utils.utils import read_filesystem
|
||||
from fatfs_utils.utils import required_clusters_count
|
||||
from fatfs_utils.utils import RESERVED_CLUSTERS_COUNT
|
||||
|
||||
|
||||
def duplicate_fat_decorator(func): # type: ignore
|
||||
@ -48,14 +55,15 @@ class FATFS:
|
||||
volume_label: str = FATDefaults.VOLUME_LABEL,
|
||||
file_sys_type: str = FATDefaults.FILE_SYS_TYPE,
|
||||
root_entry_count: int = FATDefaults.ROOT_ENTRIES_COUNT,
|
||||
explicit_fat_type: int = None,
|
||||
explicit_fat_type: Optional[int] = None,
|
||||
media_type: int = FATDefaults.MEDIA_TYPE) -> None:
|
||||
# root directory bytes should be aligned by sector size
|
||||
assert (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0
|
||||
assert (int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0
|
||||
# number of bytes in the root dir must be even multiple of BPB_BytsPerSec
|
||||
assert ((root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0
|
||||
if (int(root_entry_count) > 128):
|
||||
assert ((int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0
|
||||
|
||||
root_dir_sectors_cnt: int = (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size
|
||||
root_dir_sectors_cnt: int = (int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) // sector_size
|
||||
|
||||
self.state: FATFSState = FATFSState(sector_size=sector_size,
|
||||
explicit_fat_type=explicit_fat_type,
|
||||
|
@ -44,7 +44,10 @@ TEST_CASE("Create volume, open file, write and read back data", "[fatfs]")
|
||||
|
||||
fr_result = f_fdisk(pdrv, part_list, work_area);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0};
|
||||
|
||||
// For host tests, include FM_SFD flag when formatting partitions smaller than 128KB.
|
||||
// if n_root field of MKFS_PARM is set to 128 => 1 root directory sec and if set to 0(default 512) => 4 root directory sectors.
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, 0};
|
||||
fr_result = f_mkfs("", &opt, work_area, sizeof(work_area)); // Use default volume
|
||||
|
||||
// Mount the volume
|
||||
@ -56,7 +59,7 @@ TEST_CASE("Create volume, open file, write and read back data", "[fatfs]")
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
|
||||
// Generate data
|
||||
uint32_t data_size = 100000;
|
||||
uint32_t data_size = 1000;
|
||||
|
||||
char *data = (char*) malloc(data_size);
|
||||
char *read = (char*) malloc(data_size);
|
||||
@ -130,7 +133,7 @@ static void prepare_fatfs(const char* partition_label, const esp_partition_t** p
|
||||
|
||||
fr_result = f_fdisk(_pdrv, part_list, work_area);
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0};
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, 0};
|
||||
fr_result = f_mkfs(drv, &opt, work_area, sizeof(work_area)); // Use default volume
|
||||
REQUIRE(fr_result == FR_OK);
|
||||
}
|
||||
@ -222,7 +225,7 @@ TEST_CASE("Test mounting 2 volumes, writing data and formatting the 2nd one, rea
|
||||
const size_t workbuf_size = 4096;
|
||||
void *workbuf = ff_memalloc(workbuf_size);
|
||||
REQUIRE(workbuf != NULL);
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 0, CONFIG_WL_SECTOR_SIZE};
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, CONFIG_WL_SECTOR_SIZE};
|
||||
fr_result = f_mkfs(drv1, &opt, workbuf, workbuf_size);
|
||||
free(workbuf);
|
||||
workbuf = NULL;
|
||||
|
@ -3,5 +3,5 @@
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, fat, , 1M,
|
||||
storage2, data, fat, , 1M,
|
||||
storage, data, fat, , 32k,
|
||||
storage2, data, fat, , 32k,
|
||||
|
|
@ -34,7 +34,6 @@
|
||||
#error Wrong include file (ff.h).
|
||||
#endif
|
||||
|
||||
|
||||
/* Limits and boundaries */
|
||||
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
||||
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
||||
@ -43,6 +42,10 @@
|
||||
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
||||
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
||||
|
||||
#define MIN_FAT12_SEC_VOL 4 /* Min size of the FAT sector volume
|
||||
1 FAT, 1 root dir, 1 reserved, 1 data sector */
|
||||
#define MIN_FAT12_DATA_SEC 1 /* Min FAT data sectors */
|
||||
|
||||
|
||||
/* Character code support macros */
|
||||
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||
@ -3318,7 +3321,7 @@ static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS,
|
||||
&& ld_word(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of reserved sectors (MNBZ) */
|
||||
&& (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of FATs (1 or 2) */
|
||||
&& ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir entries (MNBZ) */
|
||||
&& (ld_word(fs->win + BPB_TotSec16) >= 128 || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=128) */
|
||||
&& (ld_word(fs->win + BPB_TotSec16) >= MIN_FAT12_SEC_VOL || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=MIN_FAT12_SEC_VOL) */
|
||||
&& ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */
|
||||
return 0; /* It can be presumed an FAT VBR */
|
||||
}
|
||||
@ -6034,7 +6037,11 @@ FRESULT f_mkfs (
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */
|
||||
if (n_fat == 1) {
|
||||
if (sz_vol < MIN_FAT12_SEC_VOL) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >= MIN_FAT12_SEC_VOLs */
|
||||
} else {
|
||||
if (sz_vol < (MIN_FAT12_SEC_VOL + 1)) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >= (MIN_FAT12_SEC_VOL+1)s */
|
||||
}
|
||||
|
||||
/* Now start to create an FAT volume at b_vol and sz_vol */
|
||||
|
||||
@ -6265,7 +6272,7 @@ FRESULT f_mkfs (
|
||||
}
|
||||
|
||||
/* Determine number of clusters and final check of validity of the FAT sub-type */
|
||||
if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
||||
if (sz_vol < b_data + pau * MIN_FAT12_DATA_SEC - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
||||
n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau;
|
||||
if (fsty == FS_FAT32) {
|
||||
if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32? */
|
||||
|
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "test_fatfs_flash_wl.c"
|
||||
idf_component_register(SRCS "test_fatfs_flash_wl.c" "test_fatfs_small_partition.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES unity spi_flash fatfs vfs test_fatfs_common
|
||||
WHOLE_ARCHIVE)
|
||||
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/unistd.h>
|
||||
#include "unity.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
|
||||
static wl_handle_t s_test_wl_handle;
|
||||
static void test_setup(void)
|
||||
{
|
||||
// With this configuration, for 32k partition size,
|
||||
// 4 sectors will be used for WL and 4 sectors for FATFS
|
||||
// (1 FAT, 1 root directory, 1 reserved and 1 data sector)
|
||||
esp_vfs_fat_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = true,
|
||||
.max_files = 5,
|
||||
.use_one_fat = true,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(esp_vfs_fat_spiflash_format_cfg_rw_wl("/spiflash", "storage1", &mount_config));
|
||||
TEST_ESP_OK(esp_vfs_fat_spiflash_mount_rw_wl("/spiflash", "storage1", &mount_config, &s_test_wl_handle));
|
||||
}
|
||||
|
||||
static void test_teardown(void)
|
||||
{
|
||||
TEST_ESP_OK(esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", s_test_wl_handle));
|
||||
}
|
||||
|
||||
static void test_write_data_sec(int num_data_sec)
|
||||
{
|
||||
int fd = open("/spiflash/test.txt", O_CREAT | O_WRONLY);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, fd);
|
||||
|
||||
// Generate data
|
||||
uint32_t data_size = 4096*num_data_sec;
|
||||
|
||||
char *data = (char*) malloc(data_size);
|
||||
char *read_data = (char*) malloc(data_size);
|
||||
|
||||
for(uint32_t i = 0; i < (data_size); i += sizeof(i))
|
||||
{
|
||||
*((uint32_t*)(data + i)) = i;
|
||||
}
|
||||
ssize_t wr = write(fd, data, data_size);
|
||||
if (num_data_sec == 1) {
|
||||
TEST_ASSERT_EQUAL(data_size, wr);
|
||||
} else {
|
||||
TEST_ASSERT_NOT_EQUAL(data_size, wr);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
|
||||
fd = open("/spiflash/test.txt", O_RDONLY);
|
||||
int r = read(fd, read_data, data_size);
|
||||
if (num_data_sec == 1) {
|
||||
TEST_ASSERT_EQUAL(data_size, r);
|
||||
} else {
|
||||
TEST_ASSERT_NOT_EQUAL(data_size, r);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(0, strcmp(data, read_data));
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
}
|
||||
|
||||
TEST_CASE("(WL) can format small partition and read-write data", "[fatfs][wear_levelling][timeout=120]")
|
||||
{
|
||||
test_setup();
|
||||
test_write_data_sec(1); //for 1 data sectors, write and read func should work
|
||||
test_write_data_sec(2); //for 2 data sectors, write and read func should fail
|
||||
test_teardown();
|
||||
}
|
@ -2,3 +2,4 @@
|
||||
factory, app, factory, 0x10000, 768k,
|
||||
storage, data, fat, , 528k,
|
||||
storage2, data, fat, , 528k,
|
||||
storage1, data, fat, , 32k,
|
||||
|
|
@ -15,6 +15,10 @@
|
||||
#include "wear_levelling.h"
|
||||
#include "diskio_wl.h"
|
||||
|
||||
// If the available sectors based on partition size are less than 128,
|
||||
// the root directory sector should be set to 1.
|
||||
#define MIN_REQ_SEC 128
|
||||
|
||||
static const char* TAG = "vfs_fat_spiflash";
|
||||
|
||||
static vfs_fat_spiflash_ctx_t *s_ctx[FF_VOLUMES] = {};
|
||||
@ -74,7 +78,7 @@ vfs_fat_spiflash_ctx_t* get_vfs_fat_spiflash_ctx(wl_handle_t wlhandle)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags)
|
||||
static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags, size_t sec_num)
|
||||
{
|
||||
FRESULT fresult = f_mount(fs, drv, 1);
|
||||
if (fresult != FR_OK) {
|
||||
@ -93,7 +97,13 @@ static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_moun
|
||||
|
||||
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);
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, 0, alloc_unit_size};
|
||||
UINT root_dir_entries;
|
||||
if (CONFIG_WL_SECTOR_SIZE == 512) {
|
||||
root_dir_entries = 16;
|
||||
} else {
|
||||
root_dir_entries = 128;
|
||||
}
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size};
|
||||
fresult = f_mkfs(drv, &opt, workbuf, workbuf_size);
|
||||
free(workbuf);
|
||||
workbuf = NULL;
|
||||
@ -157,8 +167,9 @@ esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char* base_path,
|
||||
|
||||
vfs_fat_x_ctx_flags_t flags = 0;
|
||||
|
||||
size_t sec_num = wl_size(*wl_handle) / wl_sector_size(*wl_handle);
|
||||
// Try to mount partition
|
||||
ret = s_f_mount_rw(fs, drv, mount_config, &flags);
|
||||
ret = s_f_mount_rw(fs, drv, mount_config, &flags, sec_num);
|
||||
if (ret != ESP_OK) {
|
||||
goto fail;
|
||||
}
|
||||
@ -224,6 +235,7 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
|
||||
wl_handle_t temp_handle = WL_INVALID_HANDLE;
|
||||
uint32_t id = FF_VOLUMES;
|
||||
size_t sec_num = 0;
|
||||
|
||||
bool found = s_get_context_id_by_label(partition_label, &id);
|
||||
if (!found) {
|
||||
@ -239,6 +251,7 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, mount_cfg, &temp_handle), TAG, "Failed to mount");
|
||||
found = s_get_context_id_by_label(partition_label, &id);
|
||||
sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle);
|
||||
assert(found);
|
||||
if (s_ctx[id]->flags & FORMATTED_DURING_LAST_MOUNT) {
|
||||
ESP_LOGD(TAG, "partition was formatted during mounting, skipping another format");
|
||||
@ -250,6 +263,8 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
if (cfg) {
|
||||
s_ctx[id]->mount_config = *cfg;
|
||||
}
|
||||
temp_handle = s_ctx[id]->wlhandle;
|
||||
sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle);
|
||||
}
|
||||
|
||||
//unmount
|
||||
@ -266,7 +281,13 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
}
|
||||
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, s_ctx[id]->mount_config.allocation_unit_size);
|
||||
ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size);
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, 0, alloc_unit_size};
|
||||
UINT root_dir_entries;
|
||||
if (CONFIG_WL_SECTOR_SIZE == 512) {
|
||||
root_dir_entries = 16;
|
||||
} else {
|
||||
root_dir_entries = 128;
|
||||
}
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size};
|
||||
fresult = f_mkfs(drv, &opt, workbuf, workbuf_size);
|
||||
free(workbuf);
|
||||
workbuf = NULL;
|
||||
@ -274,7 +295,7 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
|
||||
mount_back:
|
||||
if (partition_was_mounted) {
|
||||
esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config, NULL);
|
||||
esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config, NULL, sec_num);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to mount back, go to recycle");
|
||||
goto recycle;
|
||||
|
@ -50,7 +50,7 @@ The most significant properties and features of above-mentioned file systems are
|
||||
- Integrated
|
||||
- Integrated
|
||||
* - Minimum partition size
|
||||
- * 128 sectors With wear levelling on (WL sector=4096B):
|
||||
- * 8 sectors with wear levelling on (4 FATFS sectors + 4 WL sectors with WL sector size = 4096B)
|
||||
* plus 4 sectors at least
|
||||
* real number given by WL configuration (Safe, Perf)
|
||||
- * 6 logical blocks
|
||||
|
@ -157,6 +157,32 @@ Usage::
|
||||
|
||||
Parameter --verbose prints detailed information from boot sector of the FatFs image to the terminal before folder structure is generated.
|
||||
|
||||
FATFS Minimum Partition Size and Limits
|
||||
---------------------------------------
|
||||
|
||||
The FATFS component supports FAT12, FAT16, and FAT32 file system types. The file system type is determined by the number of clusters (calculated as data sectors divided by sectors per cluster) on the volume. The minimum partition size is defined by the number of sectors allocated to FAT tables, root directories and data clusters.
|
||||
|
||||
* The minimum supported size for a FAT partition with wear leveling enabled is 32 KB for a sector size of 4096 bytes. For a sector size of 512 bytes, the minimum partition size varies based on the WL configuration: 20 KB for Performance mode and 28 KB for Safety mode (requiring 2 extra sectors).
|
||||
* For a partition with wear leveling enabled, 4 sectors will be reserved for wear-leveling operations, and 4 sectors will be used by the FATFS (1 reserved sector, 1 FAT sector, 1 root directory sector and 1 data sector).
|
||||
* Increasing the partition size will allocate additional data sectors, allowing for more storage space.
|
||||
* For partition sizes less than 528 KB, 1 root directory sector will be allocated; for larger partitions, 4 root directory sectors will be used.
|
||||
* By default, two FAT sectors are created, increasing the partition size by one sector to accommodate the extra FAT sector. To enable a single FAT sector, configure the `use_one_fat` option in `struct esp_vfs_fat_mount_config_t` (see :component_file:`fatfs/vfs/esp_vfs_fat.h`). Enabling this option allows the minimum partition size to be reduced to 32 KB.
|
||||
* The general formula for calculating the partition size for a wear-leveled partition is::
|
||||
|
||||
partition_size = Wear-levelling sectors * FLASH_SEC_SIZE + FATFS partition sectors * FAT_SEC_SIZE
|
||||
|
||||
Where:
|
||||
|
||||
- Wear-leveling sectors are fixed at 4
|
||||
- FLASH_SEC_SIZE is 4096 bytes
|
||||
- FATFS partition sectors include: 1 reserved sector + FAT sectors + root directory sectors + data sectors
|
||||
- FAT_SEC_SIZE can be either 512 bytes or 4096 bytes, depending on the configuration
|
||||
|
||||
* For read-only partitions without wear leveling enabled and a sector size of 512 bytes, the minimum partition size can be reduced to as low as 2 KB.
|
||||
|
||||
Please refer :doc:`File System Considerations <../../api-guides/file-system-considerations>` for further details.
|
||||
|
||||
|
||||
High-level API Reference
|
||||
------------------------
|
||||
|
||||
|
@ -99,7 +99,7 @@ FatFs 分区生成器
|
||||
|
||||
该生成器可以在主机上创建文件系统镜像,并用指定的主机文件夹内容对其进行填充。
|
||||
|
||||
该脚本是建立在分区生成器的基础上 (:component_file:`fatfsgen.py<fatfs/fatfsgen.py>`),目前除了可以生成分区外,也可以初始化磨损均衡。
|
||||
该脚本是建立在分区生成器的基础上 (:component_file:`fatfsgen.py<fatfs/fatfsgen.py>`),目前除了可以生成分区外,也可以初始化损耗均衡。
|
||||
|
||||
目前的最新版本支持短文件名、长文件名、FAT12 和 FAT16。长文件名的上限是 255 个字符,文件名中可以包含多个 ``.`` 字符以及其他字符,如 ``+``、``,``、``;``、``=``、``[`` and ``]`` 等。
|
||||
|
||||
@ -112,13 +112,13 @@ FatFs 分区生成器
|
||||
|
||||
fatfs_create_spiflash_image(<partition> <base_dir> [FLASH_IN_PROJECT])
|
||||
|
||||
如果不希望在生成分区时使用磨损均衡,可以使用 ``fatfs_create_rawflash_image``::
|
||||
如果不希望在生成分区时使用损耗均衡,可以使用 ``fatfs_create_rawflash_image``::
|
||||
|
||||
fatfs_create_rawflash_image(<partition> <base_dir> [FLASH_IN_PROJECT])
|
||||
|
||||
``fatfs_create_spiflash_image`` 以及 ``fatfs_create_rawflash_image`` 必须从项目的 CMakeLists.txt 中调用。
|
||||
|
||||
如果决定使用 ``fatfs_create_rawflash_image`` (不支持磨损均衡),请注意它仅支持在设备中以只读模式安装。
|
||||
如果决定使用 ``fatfs_create_rawflash_image`` (不支持损耗均衡),请注意它仅支持在设备中以只读模式安装。
|
||||
|
||||
|
||||
该函数的参数如下:
|
||||
@ -157,6 +157,33 @@ FatFs 分区分析器
|
||||
|
||||
生成文件夹结构之前,参数 --verbose 将根据 FatFs 镜像的引导扇区在终端打印详细信息。
|
||||
|
||||
|
||||
FATFS 最小分区大小及限制
|
||||
------------------------
|
||||
|
||||
FATFS 组件支持 FAT12、FAT16 和 FAT32 文件系统类型。文件系统类型取决于卷上簇的数量(簇数通过数据扇区数量除以每簇包含的扇区数计算得出)。最小分区大小由分配给 FAT 表、根目录和数据簇的扇区数量决定。
|
||||
|
||||
* 对于 4096 字节的扇区,启用损耗均衡的 FAT 分区大小最小支持 32 KB。对于 512 字节的扇区,最小分区大小取决于损耗均衡的配置:性能模式下,最小支持 20 KB,安全模式下最小支持 28 KB(需要额外的 2 个扇区)。
|
||||
* 启用了损耗均衡的分区会预留 4 个扇区用于损耗均衡操作。此外,FATFS 本身也会使用 4 个扇区,分别为 1 个保留扇区、1 个 FAT 扇区、1 个根目录扇区和 1 个数据扇区。
|
||||
* 增加分区大小将分配更多的数据扇区,提供更大的存储空间。
|
||||
* 对小于 528 KB 的分区,将分配 1 个根目录扇区;对于更大的分区,将分配 4 个根目录扇区。
|
||||
* 默认会创建两个 FAT 扇区,因此分区大小会增加一个扇区来容纳这个额外的 FAT 扇区。如要启用单个 FAT 扇区,可以在 `struct esp_vfs_fat_mount_config_t` 中(参见 :component_file:`fatfs/vfs/esp_vfs_fat.h`)设置 `use_one_fat` 选项。启用此选项后,最小分区大小可减少至 32 KB。
|
||||
* 计算损耗均衡分区大小的一般公式为::
|
||||
|
||||
partition_size = 损耗均衡扇区数 * FLASH_SEC_SIZE + FATFS 分区扇区数量 * FAT_SEC_SIZE
|
||||
|
||||
其中:
|
||||
|
||||
- 损耗均衡扇区数固定为 4 个
|
||||
- FLASH_SEC_SIZE 为 4096 字节
|
||||
- FATFS 分区扇区包括:1 个保留扇区 + FAT 扇区 + 根目录扇区 + 数据扇区
|
||||
- FAT_SEC_SIZE 根据不同的配置,可以是 512 字节或 4096 字节
|
||||
|
||||
* 对于未启用损耗均衡、扇区大小为 512 字节的只读分区,最小分区大小可减少至 2 KB。
|
||||
|
||||
更多详情请参考 :doc:`文件系统注意事项 <../../api-guides/file-system-considerations>`。
|
||||
|
||||
|
||||
高级 API 参考
|
||||
------------------------
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user