diff --git a/docs/en/api-reference/storage/fatfs.rst b/docs/en/api-reference/storage/fatfs.rst index 98ddd976e0..338aac18ed 100644 --- a/docs/en/api-reference/storage/fatfs.rst +++ b/docs/en/api-reference/storage/fatfs.rst @@ -19,33 +19,33 @@ The function :cpp:func:`esp_vfs_fat_unregister_path` deletes the registration wi Most applications use the following workflow when working with ``esp_vfs_fat_`` functions: -1. Call :cpp:func:`esp_vfs_fat_register` to specify: +#. Call :cpp:func:`esp_vfs_fat_register` to specify: - Path prefix where to mount the filesystem (e.g., ``"/sdcard"``, ``"/spiflash"``) - FatFs drive number - A variable which receives the pointer to the ``FATFS`` structure -2. Call :cpp:func:`ff_diskio_register` to register the disk I/O driver for the drive number used in Step 1. +#. Call :cpp:func:`ff_diskio_register` to register the disk I/O driver for the drive number used in Step 1. -3. Call the FatFs function :cpp:func:`f_mount`, and optionally :cpp:func:`f_fdisk`, :cpp:func:`f_mkfs`, to mount the filesystem using the same drive number which was passed to :cpp:func:`esp_vfs_fat_register`. For more information, see `FatFs documentation `_. +#. To mount the filesystem using the same drive number which was passed to :cpp:func:`esp_vfs_fat_register`, call the FatFs function :cpp:func:`f_mount`. If the filesystem is not present on the target logical drive, :cpp:func:`f_mount` will fail with the ``FR_NO_FILESYSTEM`` error. In such case, call :cpp:func:`f_mkfs` to create a fresh FatFS structure on the drive first, and then call:cpp:func:`f_mount` again. Note that SD cards need to be partitioned with :cpp:func:`f_fdisk` prior to previously described steps. For more information, see `FatFs documentation `_. -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"``). The filesystem uses `8.3 filenames `_ format (SFN) by default. If you need to use long filenames (LFN), enable the :ref:`CONFIG_FATFS_LONG_FILENAMES` option. More details on the FatFs filenames are available `here `_. +#. 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"``). The filesystem uses `8.3 filenames `_ format (SFN) by default. If you need to use long filenames (LFN), enable the :ref:`CONFIG_FATFS_LONG_FILENAMES` option. Please refer to `FatFs filenames `_ for more details. -5. Optionally, by enabling the option :ref:`CONFIG_FATFS_USE_FASTSEEK`, you can use the POSIX lseek function to perform it faster. The fast seek does 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. +#. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix, for example, ``"/hello.txt"``. -6. Optionally, by enabling the option :ref:`CONFIG_FATFS_IMMEDIATE_FSYNC`, you can enable automatic calling of :cpp:func:`f_sync` to flush recent file changes after each call of :cpp:func:`vfs_fat_write`, :cpp:func:`vfs_fat_pwrite`, :cpp:func:`vfs_fat_link`, :cpp:func:`vfs_fat_truncate` and :cpp:func:`vfs_fat_ftruncate` functions. This feature improves file-consistency and size reporting accuracy for the FatFs, at a price on decreased performance due to frequent disk operations. +#. Close all open files. -7. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix, for example, ``"/hello.txt"``. +#. Call the FatFs function :cpp:func:`f_mount` for the same drive number with NULL ``FATFS*`` argument to unmount the filesystem. -8. Close all open files. +#. 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. -9. Call the FatFs function :cpp:func:`f_mount` for the same drive number with NULL ``FATFS*`` argument to unmount the filesystem. - -10. 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. - -11. 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. +#. 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 :cpp:func:`esp_vfs_fat_sdmmc_mount`, :cpp:func:`esp_vfs_fat_sdspi_mount`, and :cpp:func:`esp_vfs_fat_sdcard_unmount` wrap the steps described above and also handle SD card initialization. These functions are described in the next section. +.. note:: + + Because FAT filesystem does not support hardlinks, :cpp:func:`link` copies contents of the file instead. (This only applies to files on FatFs volumes.) + Using FatFs with VFS and SD Cards --------------------------------- @@ -60,6 +60,15 @@ Using FatFs with VFS in Read-Only Mode The header file :component_file:`fatfs/vfs/esp_vfs_fat.h` also defines the convenience functions :cpp:func:`esp_vfs_fat_spiflash_mount_ro` and :cpp:func:`esp_vfs_fat_spiflash_unmount_ro`. These functions perform Steps 1-3 and 7-9 respectively for read-only FAT partitions. These are particularly helpful for data partitions written only once during factory provisioning, which will not be changed by production application throughout the lifetime of the hardware. +Configuration options +--------------------- + +The following configuration options are available for the FatFs component: + +* :ref:`CONFIG_FATFS_USE_FASTSEEK` - If enabled, the POSIX :cpp:func:`lseek` function will be performed faster. The fast seek does 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. +* :ref:`CONFIG_FATFS_IMMEDIATE_FSYNC` - If enabled, the FatFs will automatically call :cpp:func:`f_sync` to flush recent file changes after each call of :cpp:func:`write`, :cpp:func:`pwrite`, :cpp:func:`link`, :cpp:func:`truncate` and :cpp:func:`ftruncate` functions. This feature improves file-consistency and size reporting accuracy for the FatFs, at a price on decreased performance due to frequent disk operations. +* :ref:`CONFIG_FATFS_LINK_LOCK` - If enabled, this option guarantees the API thread safety, while disabling this option might be necessary for applications that require fast frequent small file operations (e.g., logging to a file). Note that if this option is disabled, the copying performed by :cpp:func:`link` will be non-atomic. In such case, using :cpp:func:`link` on a large file on the same volume in a different task is not guaranteed to be thread safe. + FatFS Disk IO Layer ------------------- @@ -109,13 +118,13 @@ If you decide for any reason to use ``fatfs_create_rawflash_image`` (without wea The arguments of the function are as follows: -1. partition - the name of the partition as defined in the partition table (e.g., :example_file:`storage/fatfsgen/partitions_example.csv`). +#. partition - the name of the partition as defined in the partition table (e.g., :example_file:`storage/fatfsgen/partitions_example.csv`). -2. base_dir - the directory that will be encoded to FatFs partition and optionally flashed into the device. Beware that you have to specify the suitable size of the partition in the partition table. +#. base_dir - the directory that will be encoded to FatFs partition and optionally flashed into the device. Beware that you have to specify the suitable size of the partition in the partition table. -3. flag ``FLASH_IN_PROJECT`` - optionally, users can have the image automatically flashed together with the app binaries, partition tables, etc. on ``idf.py flash -p `` by specifying ``FLASH_IN_PROJECT``. +#. flag ``FLASH_IN_PROJECT`` - optionally, users can have the image automatically flashed together with the app binaries, partition tables, etc. on ``idf.py flash -p `` by specifying ``FLASH_IN_PROJECT``. -4. flag ``PRESERVE_TIME`` - optionally, users can force preserving the timestamps from the source folder to the target image. Without preserving the time, every timestamp will be set to the FATFS default initial time (1st January 1980). +#. flag ``PRESERVE_TIME`` - optionally, users can force preserving the timestamps from the source folder to the target image. Without preserving the time, every timestamp will be set to the FATFS default initial time (1st January 1980). For example:: diff --git a/docs/zh_CN/api-reference/storage/fatfs.rst b/docs/zh_CN/api-reference/storage/fatfs.rst index e153139b5d..aa13b2dadf 100644 --- a/docs/zh_CN/api-reference/storage/fatfs.rst +++ b/docs/zh_CN/api-reference/storage/fatfs.rst @@ -19,33 +19,33 @@ FatFs 与 VFS 配合使用 多数应用程序在使用 ``esp_vfs_fat_`` 函数时,采用如下步骤: -1. 调用 :cpp:func:`esp_vfs_fat_register`,指定: +#. 调用 :cpp:func:`esp_vfs_fat_register`,指定: - 挂载文件系统的路径前缀(例如,``"/sdcard"`` 或 ``"/spiflash"``) - FatFs 驱动编号 - 一个用于接收指向 ``FATFS`` 结构指针的变量 -2. 调用 :cpp:func:`ff_diskio_register`,为步骤 1 中的驱动编号注册磁盘 I/O 驱动; +#. 调用 :cpp:func:`ff_diskio_register`,为步骤 1 中的驱动编号注册磁盘 I/O 驱动; -3. 调用 FatFs 函数 :cpp:func:`f_mount`,随后调用 :cpp:func:`f_fdisk` 或 :cpp:func:`f_mkfs`,并使用与传递到 :cpp:func:`esp_vfs_fat_register` 相同的驱动编号挂载文件系统。请参考 `FatFs 文档 `_,查看更多信息; +#. 如需使用与传递到 :cpp:func:`esp_vfs_fat_register` 相同的驱动编号挂载文件系统,可调用 FatFs 函数 :cpp:func:`f_mount`。如果目标逻辑驱动上不存在该文件系统,:cpp:func:`f_mount` 将调用失败并报告 ``FR_NO_FILESYSTEM`` 错误。此时,应首先调用 :cpp:func:`f_mkfs`,在驱动上创建新的 FatFS 结构体,然后重新调用 :cpp:func:`f_mount`。注意,应在上述步骤之前调用 :cpp:func:`f_fdisk` 对 SD 卡进行分区。请参考 `FatFs 文档 `_,查看更多信息; -4. 调用 C 标准库和 POSIX API 对路径中带有步骤 1 中所述前缀的文件(例如,``"/sdcard/hello.txt"``)执行打开、读取、写入、擦除、复制等操作。文件系统默认使用 `8.3 文件名 `_ 格式 (SFN)。如需使用长文件名 (LFN),启用 :ref:`CONFIG_FATFS_LONG_FILENAMES` 选项。请参考 `here `_,查看更多信息; +#. 调用 C 标准库和 POSIX API 对路径中带有步骤 1 中所述前缀的文件(例如,``"/sdcard/hello.txt"``)执行打开、读取、写入、擦除、复制等操作。文件系统默认使用 `8.3 文件名 `_ 格式 (SFN)。如需使用长文件名 (LFN),启用 :ref:`CONFIG_FATFS_LONG_FILENAMES` 选项。请参考 `FatFs 文件系统 `_,查看更多信息; -5. 可以启用 :ref:`CONFIG_FATFS_USE_FASTSEEK` 选项,可以使用 POSIX lseek 实现快速执行。快速查找不适用于编辑模式下的文件,所以,使用快速查找时,应在只读模式下打开(或者关闭然后重新打开)文件; +#. 可以直接调用 FatFs 库函数,但需要使用没有 VFS 前缀的路径,如 ``"/hello.txt"``; -6. 可以启用 :ref:`CONFIG_FATFS_IMMEDIATE_FSYNC` 选项,在每次调用 :cpp:func:`vfs_fat_write`、:cpp:func:`vfs_fat_pwrite`、:cpp:func:`vfs_fat_link`、:cpp:func:`vfs_fat_truncate` 和 :cpp:func:`vfs_fat_ftruncate` 函数之后,自动调用 :cpp:func:`f_sync` 以同步最近的文件改动。该功能可提高文件系统中文件的一致性和文件大小报告的准确性,但是由于需要频繁进行磁盘操作,性能将会受到影响; +#. 关闭所有打开的文件; -7. 可以直接调用 FatFs 库函数,但需要使用没有 VFS 前缀的路径,如 ``"/hello.txt"``; +#. 调用 FatFs 函数 :cpp:func:`f_mount` 并使用 NULL ``FATFS*`` 参数,为与上述编号相同的驱动卸载文件系统; -8. 关闭所有打开的文件; +#. 调用 FatFs 函数 :cpp:func:`ff_diskio_register` 并使用 NULL ``ff_diskio_impl_t*`` 参数和相同的驱动编号,来释放注册的磁盘 I/O 驱动; -9. 调用 FatFs 函数 :cpp:func:`f_mount` 并使用 NULL ``FATFS*`` 参数,为与上述编号相同的驱动卸载文件系统; - -10. 调用 FatFs 函数 :cpp:func:`ff_diskio_register` 并使用 NULL ``ff_diskio_impl_t*`` 参数和相同的驱动编号,来释放注册的磁盘 I/O 驱动; - -11. 调用 :cpp:func:`esp_vfs_fat_unregister_path` 并使用文件系统挂载的路径将 FatFs 从 VFS 中移除,并释放步骤 1 中分配的 ``FATFS`` 结构。 +#. 调用 :cpp:func:`esp_vfs_fat_unregister_path` 并使用文件系统挂载的路径将 FatFs 从 VFS 中移除,并释放步骤 1 中分配的 ``FATFS`` 结构。 便捷函数 :cpp:func:`esp_vfs_fat_sdmmc_mount`、:cpp:func:`esp_vfs_fat_sdspi_mount` 和 :cpp:func:`esp_vfs_fat_sdcard_unmount` 对上述步骤进行了封装,并加入了对 SD 卡初始化的处理。我们将在下一章节详细介绍以上函数。 +.. note:: + + FAT 文件系统不支持硬链接,因此调用 :cpp:func:`link` 后会复制文件内容(仅适用于 FatFs 卷上的文件)。 + FatFs 与 VFS 和 SD 卡配合使用 --------------------------------- @@ -60,6 +60,15 @@ FatFs 与 VFS 配合使用(只读模式下) 头文件 :component_file:`fatfs/vfs/esp_vfs_fat.h` 也定义了两个便捷函数 :cpp:func:`esp_vfs_fat_spiflash_mount_ro` 和 :cpp:func:`esp_vfs_fat_spiflash_unmount_ro`。上述两个函数分别对 FAT 只读分区执行步骤 1-3 和步骤 7-9。有些数据分区仅在工厂配置时写入一次,之后在整个硬件生命周期内都不会再有任何改动。利用上述两个函数处理这种数据分区非常方便。 +配置选项 +-------- + +FatFs 组件有以下配置选项: + +* :ref:`CONFIG_FATFS_USE_FASTSEEK` - 如果启用该选项,POSIX :cpp:func:`lseek` 函数将以更快的速度执行。快速查找不适用于编辑模式下的文件,所以,使用快速查找时,应在只读模式下打开(或者关闭然后重新打开)文件。 +* :ref:`CONFIG_FATFS_IMMEDIATE_FSYNC` - 如果启用该选项,FatFs 将在每次调用 :cpp:func:`write`、:cpp:func:`pwrite`、:cpp:func:`link`、:cpp:func:`truncate` 和 :cpp:func:`ftruncate` 函数后,自动调用 :cpp:func:`f_sync` 以同步最近的文件改动。该功能可提高文件系统中文件的一致性和文件大小报告的准确性,但由于需要频繁进行磁盘操作,性能将会受到影响。 +* :ref:`CONFIG_FATFS_LINK_LOCK` - 如果启用该选项,可保证 API 的线程安全,但如果应用程序需要快速频繁地进行小文件操作(例如将日志记录到文件),则可能有必要禁用该选项。请注意,如果禁用该选项,调用 :cpp:func:`link` 后的复制操作将是非原子的,此时如果在不同任务中对同一卷上的大文件调用 :cpp:func:`link`,则无法确保线程安全。 + FatFs 磁盘 I/O 层 ------------------- @@ -109,13 +118,13 @@ FatFs 分区生成器 该函数的参数如下: -1. partition - 分区的名称,需要在分区表中定义(如 :example_file:`storage/fatfsgen/partitions_example.csv`)。 +#. partition - 分区的名称,需要在分区表中定义(如 :example_file:`storage/fatfsgen/partitions_example.csv`)。 -2. base_dir - 目录名称,该目录会被编码为 FatFs 分区,也可以选择将其被烧录进设备。但注意必须在分区表中指定合适的分区大小。 +#. base_dir - 目录名称,该目录会被编码为 FatFs 分区,也可以选择将其被烧录进设备。但注意必须在分区表中指定合适的分区大小。 -3. ``FLASH_IN_PROJECT`` 标志 - 可选参数,用户可以通过指定 ``FLASH_IN_PROJECT``,选择在执行 ``idf.py flash -p `` 时让分区镜像自动与应用程序二进制文件、分区表等一同烧录进设备。 +#. ``FLASH_IN_PROJECT`` 标志 - 可选参数,用户可以通过指定 ``FLASH_IN_PROJECT``,选择在执行 ``idf.py flash -p `` 时让分区镜像自动与应用程序二进制文件、分区表等一同烧录进设备。 -4. ``PRESERVE_TIME`` 标志 - 可选参数,用户可强制让目标镜像保留源文件夹的时间戳。如果不保留,每个目标镜像的时间戳都将设置为 FATFS 默认初始时间(1980 年 1 月 1 日)。 +#. ``PRESERVE_TIME`` 标志 - 可选参数,用户可强制让目标镜像保留源文件夹的时间戳。如果不保留,每个目标镜像的时间戳都将设置为 FATFS 默认初始时间(1980 年 1 月 1 日)。 例如::