kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/fatfs_fast_seek' into 'master'
feature/fatfs: enable the usage of fast-seek algorithm See merge request espressif/esp-idf!9916pull/6192/head
commit
6ce34a227e
|
@ -180,4 +180,26 @@ menu "FAT Filesystem support"
|
|||
Disable this option if optimizing for performance. Enable this option if
|
||||
optimizing for internal memory size.
|
||||
|
||||
|
||||
config FATFS_USE_FASTSEEK
|
||||
bool "Enable fast seek algorithm when using lseek function through VFS FAT"
|
||||
default n
|
||||
help
|
||||
The fast seek feature enables fast backward/long seek operations without
|
||||
FAT access by using an in-memory CLMT (cluster link map table).
|
||||
Please note, fast-seek is only allowed for read-mode files, if a
|
||||
file is opened in write-mode, the seek mechanism will automatically fallback
|
||||
to the default implementation.
|
||||
|
||||
|
||||
config FATFS_FAST_SEEK_BUFFER_SIZE
|
||||
int "Fast seek CLMT buffer size"
|
||||
default 64
|
||||
depends on FATFS_USE_FASTSEEK
|
||||
help
|
||||
If fast seek algorithm is enabled, this defines the size of
|
||||
CLMT buffer used by this algorithm in 32-bit word units.
|
||||
This value should be chosen based on prior knowledge of
|
||||
maximum elements of each file entry would store.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FASTSEEK 0
|
||||
#define FF_USE_FASTSEEK CONFIG_FATFS_USE_FASTSEEK
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
|
|
|
@ -217,11 +217,27 @@ void test_fatfs_lseek(const char* filename)
|
|||
TEST_ASSERT_EQUAL(18, ftell(f));
|
||||
TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_SET));
|
||||
char buf[20];
|
||||
|
||||
TEST_ASSERT_EQUAL(18, fread(buf, 1, sizeof(buf), f));
|
||||
const char ref_buf[] = "0123456789\n\0\0\0abc\n";
|
||||
TEST_ASSERT_EQUAL_INT8_ARRAY(ref_buf, buf, sizeof(ref_buf) - 1);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
||||
|
||||
#ifdef CONFIG_FATFS_USE_FASTSEEK
|
||||
f = fopen(filename, "rb+");
|
||||
TEST_ASSERT_NOT_NULL(f);
|
||||
TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_END));
|
||||
TEST_ASSERT_EQUAL(18, ftell(f));
|
||||
TEST_ASSERT_EQUAL(0, fseek(f, -4, SEEK_CUR));
|
||||
TEST_ASSERT_EQUAL(14, ftell(f));
|
||||
TEST_ASSERT_EQUAL(0, fseek(f, -14, SEEK_CUR));
|
||||
TEST_ASSERT_EQUAL(0, ftell(f));
|
||||
|
||||
TEST_ASSERT_EQUAL(18, fread(buf, 1, sizeof(buf), f));
|
||||
TEST_ASSERT_EQUAL_INT8_ARRAY(ref_buf, buf, sizeof(ref_buf) - 1);
|
||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void test_fatfs_truncate_file(const char* filename)
|
||||
|
|
|
@ -307,6 +307,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode)
|
|||
errno = ENFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FRESULT res = f_open(&fat_ctx->files[fd], path, fat_mode_conv(flags));
|
||||
if (res != FR_OK) {
|
||||
file_cleanup(fat_ctx, fd);
|
||||
|
@ -315,6 +316,40 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode)
|
|||
errno = fresult_to_errno(res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FATFS_USE_FASTSEEK
|
||||
FIL* file = &fat_ctx->files[fd];
|
||||
//fast-seek is only allowed in read mode, since file cannot be expanded
|
||||
//to use it.
|
||||
if(!(fat_mode_conv(flags) & (FA_WRITE))) {
|
||||
DWORD *clmt_mem = ff_memalloc(sizeof(DWORD) * CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE);
|
||||
if (clmt_mem == NULL) {
|
||||
f_close(file);
|
||||
file_cleanup(fat_ctx, fd);
|
||||
_lock_release(&fat_ctx->lock);
|
||||
ESP_LOGE(TAG, "open: Failed to pre-allocate CLMT buffer for fast-seek");
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
file->cltbl = clmt_mem;
|
||||
file->cltbl[0] = CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE;
|
||||
res = f_lseek(file, CREATE_LINKMAP);
|
||||
ESP_LOGD(TAG, "%s: fast-seek has: %s",
|
||||
__func__,
|
||||
(res == FR_OK) ? "activated" : "failed");
|
||||
if(res != FR_OK) {
|
||||
ESP_LOGW(TAG, "%s: fast-seek not activated reason code: %d",
|
||||
__func__, res);
|
||||
//If linkmap creation fails, fallback to the non fast seek.
|
||||
ff_memfree(file->cltbl);
|
||||
file->cltbl = NULL;
|
||||
}
|
||||
} else {
|
||||
file->cltbl = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// O_APPEND need to be stored because it is not compatible with FA_OPEN_APPEND:
|
||||
// - FA_OPEN_APPEND means to jump to the end of file only after open()
|
||||
// - O_APPEND means to jump to the end only before each write()
|
||||
|
@ -375,6 +410,7 @@ static ssize_t vfs_fat_pread(void *ctx, int fd, void *dst, size_t size, off_t of
|
|||
const off_t prev_pos = f_tell(file);
|
||||
|
||||
FRESULT f_res = f_lseek(file, offset);
|
||||
|
||||
if (f_res != FR_OK) {
|
||||
ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res);
|
||||
errno = fresult_to_errno(f_res);
|
||||
|
@ -414,6 +450,7 @@ static ssize_t vfs_fat_pwrite(void *ctx, int fd, const void *src, size_t size, o
|
|||
const off_t prev_pos = f_tell(file);
|
||||
|
||||
FRESULT f_res = f_lseek(file, offset);
|
||||
|
||||
if (f_res != FR_OK) {
|
||||
ESP_LOGD(TAG, "%s: fresult=%d", __func__, f_res);
|
||||
errno = fresult_to_errno(f_res);
|
||||
|
@ -465,6 +502,12 @@ static int vfs_fat_close(void* ctx, int fd)
|
|||
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
|
||||
_lock_acquire(&fat_ctx->lock);
|
||||
FIL* file = &fat_ctx->files[fd];
|
||||
|
||||
#ifdef CONFIG_FATFS_USE_FASTSEEK
|
||||
ff_memfree(file->cltbl);
|
||||
file->cltbl = NULL;
|
||||
#endif
|
||||
|
||||
FRESULT res = f_close(file);
|
||||
file_cleanup(fat_ctx, fd);
|
||||
_lock_release(&fat_ctx->lock);
|
||||
|
@ -494,6 +537,8 @@ static off_t vfs_fat_lseek(void* ctx, int fd, off_t offset, int mode)
|
|||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "%s: offset=%ld, filesize:=%d", __func__, new_pos, f_size(file));
|
||||
FRESULT res = f_lseek(file, new_pos);
|
||||
if (res != FR_OK) {
|
||||
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
|
||||
|
|
|
@ -29,15 +29,17 @@ Most applications use the following workflow when working with ``esp_vfs_fat_``
|
|||
|
||||
4. Call the C standard library and POSIX API functions to perform such actions on files as open, read, write, erase, copy, etc. Use paths starting with the path prefix passed to :cpp:func:`esp_vfs_register` (for example, ``"/sdcard/hello.txt"``).
|
||||
|
||||
5. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix (for example, ``"/hello.txt"``).
|
||||
5. Optionally, by enabling the option `CONFIG_FATFS_USE_FASTSEEK`, use the POSIX lseek function to perform it faster, the fast seek will not work for files in write mode, so to take advantage of fast seek, you should open (or close and then reopen) the file in read-only mode.
|
||||
|
||||
6. Close all open files.
|
||||
6. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix (for example, ``"/hello.txt"``).
|
||||
|
||||
7. Call the FatFs function ``f_mount`` for the same drive number, with NULL ``FATFS*`` argument, to unmount the filesystem.
|
||||
7. Close all open files.
|
||||
|
||||
8. Call the FatFs function :cpp:func:`ff_diskio_register` with NULL ``ff_diskio_impl_t*`` argument and the same drive number to unregister the disk I/O driver.
|
||||
8. Call the FatFs function ``f_mount`` for the same drive number, with NULL ``FATFS*`` argument, to unmount the filesystem.
|
||||
|
||||
9. Call :cpp:func:`esp_vfs_fat_unregister_path` with the path where the file system is mounted to remove FatFs from VFS, and free the ``FATFS`` structure allocated in Step 1.
|
||||
9. Call the FatFs function :cpp:func:`ff_diskio_register` with NULL ``ff_diskio_impl_t*`` argument and the same drive number to unregister the disk I/O driver.
|
||||
|
||||
10. Call :cpp:func:`esp_vfs_fat_unregister_path` with the path where the file system is mounted to remove FatFs from VFS, and free the ``FATFS`` structure allocated in Step 1.
|
||||
|
||||
The convenience functions ``esp_vfs_fat_sdmmc_mount``, ``esp_vfs_fat_sdspi_mount`` and ``esp_vfs_fat_sdcard_unmount`` wrap the steps described above and also handle SD card initialization. These two functions are described in the next section.
|
||||
|
||||
|
|
|
@ -351,6 +351,7 @@ UT_002:
|
|||
|
||||
UT_003:
|
||||
extends: .unit_test_template
|
||||
parallel: 2
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_SDMODE
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
TEST_COMPONENTS=fatfs
|
||||
CONFIG_FATFS_USE_FASTSEEK=y
|
||||
CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE=64
|
Ładowanie…
Reference in New Issue