esp-idf/docs/en/api-reference/storage/fatfs.rst
radek.tandler a640626b76 fix(fatfs): Fixed fatfsparse.py parsing of FAT boot sector
The fatfsparse.py script was too strict in parsing the FAT boot sector, causing it to fail in
certain cases. This commit fixes the issue by making the parsing less strict and allowing for more
flexibility in the boot sector format.

This change improves the reliability and compatibility of the fatfsparse.py script, ensuring that it
can correctly parse a wider range of FAT boot sectors.

Docs updated
2023-12-06 08:31:50 +01:00

147 lines
9.2 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

FAT Filesystem Support
======================
:link_to_translation:`zh_CN:[中文]`
ESP-IDF uses the `FatFs <http://elm-chan.org/fsw/ff/00index_e.html>`_ library to work with FAT filesystems. FatFs resides in the ``fatfs`` component. Although the library can be used directly, many of its features can be accessed via VFS using the C standard library and POSIX API functions.
Additionally, FatFs has been modified to support the runtime pluggable disk I/O layer. This allows mapping of FatFs drives to physical disks at runtime.
Using FatFs with VFS
--------------------
The header file :component_file:`fatfs/vfs/esp_vfs_fat.h` defines the functions for connecting FatFs and VFS.
The function :cpp:func:`esp_vfs_fat_register` allocates a ``FATFS`` structure and registers a given path prefix in VFS. Subsequent operations on files starting with this prefix are forwarded to FatFs APIs.
The function :cpp:func:`esp_vfs_fat_unregister_path` deletes the registration with VFS, and frees the ``FATFS`` structure.
Most applications use the following workflow when working with ``esp_vfs_fat_`` functions:
1. 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.
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 <http://elm-chan.org/fsw/ff/doc/mount.html>`_.
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 <https://en.wikipedia.org/wiki/8.3_filename>`_ 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 <http://elm-chan.org/fsw/ff/doc/filename.html>`_.
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.
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.
7. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix, for example, ``"/hello.txt"``.
8. Close all open files.
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.
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.
Using FatFs with VFS and SD Cards
---------------------------------
The header file :component_file:`fatfs/vfs/esp_vfs_fat.h` defines convenience functions :cpp:func:`esp_vfs_fat_sdmmc_mount`, :cpp:func:`esp_vfs_fat_sdspi_mount`, and :cpp:func:`esp_vfs_fat_sdcard_unmount`. These functions perform Steps 13 and 79 respectively and handle SD card initialization, but provide only limited error handling. Developers are encouraged to check its source code and incorporate more advanced features into production applications.
The convenience function :cpp:func:`esp_vfs_fat_sdmmc_unmount` unmounts the filesystem and releases the resources acquired by :cpp:func:`esp_vfs_fat_sdmmc_mount`.
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.
FatFS Disk IO Layer
-------------------
FatFs has been extended with API functions that register the disk I/O driver at runtime.
These APIs provide implementation of disk I/O functions for SD/MMC cards and can be registered for the given FatFs drive number using the function :cpp:func:`ff_diskio_register_sdmmc`.
.. doxygenfunction:: ff_diskio_register
.. doxygenstruct:: ff_diskio_impl_t
:members:
.. doxygenfunction:: ff_diskio_register_sdmmc
.. doxygenfunction:: ff_diskio_register_wl_partition
.. doxygenfunction:: ff_diskio_register_raw_partition
.. _fatfs-partition-generator:
FatFs Partition Generator
-------------------------
We provide a partition generator for FatFs (:component_file:`wl_fatfsgen.py <fatfs/wl_fatfsgen.py>`) which is integrated into the build system and could be easily used in the user project.
The tool is used to create filesystem images on a host and populate it with content of the specified host folder.
The script is based on the partition generator (:component_file:`fatfsgen.py <fatfs/fatfsgen.py>`). Apart from generating partition, it can also initialize wear levelling.
The latest version supports both short and long file names, FAT12 and FAT16. The long file names are limited to 255 characters and can contain multiple periods (``.``) characters within the filename and additional characters ``+``, ``,``, ``;``, ``=``, ``[`` and ``]``.
An in-depth description of the FatFs partition generator and analyzer can be found at :doc:`Generating and parsing FAT partition on host <fatfsgen>`.
Build System Integration with FatFs Partition Generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is possible to invoke FatFs generator directly from the CMake build system by calling ``fatfs_create_spiflash_image``::
fatfs_create_spiflash_image(<partition> <base_dir> [FLASH_IN_PROJECT])
If you prefer generating partition without wear levelling support, you can use ``fatfs_create_rawflash_image``::
fatfs_create_rawflash_image(<partition> <base_dir> [FLASH_IN_PROJECT])
``fatfs_create_spiflash_image`` respectively ``fatfs_create_rawflash_image`` must be called from project's CMakeLists.txt.
If you decide for any reason to use ``fatfs_create_rawflash_image`` (without wear levelling support), beware that it supports mounting only in read-only mode in the device.
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`).
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.
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 <PORT>`` 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).
For example::
fatfs_create_spiflash_image(my_fatfs_partition my_folder FLASH_IN_PROJECT)
If FLASH_IN_PROJECT is not specified, the image will still be generated, but you will have to flash it manually using ``esptool.py`` or a custom build system target.
For an example, see :example:`storage/fatfsgen`.
FatFs Partition Analyzer
------------------------
(:component_file:`fatfsparse.py <fatfs/fatfsparse.py>`) is a partition analyzing tool for FatFs.
It is a reverse tool of (:component_file:`fatfsgen.py <fatfs/fatfsgen.py>`), i.e., it can generate the folder structure on the host based on the FatFs image.
Usage::
./fatfsparse.py [-h] [--wl-layer {detect,enabled,disabled}] [--verbose] fatfs_image.img
Parameter --verbose prints detailed information from boot sector of the FatFs image to the terminal before folder structure is generated.
High-level API Reference
------------------------
.. include-build-file:: inc/esp_vfs_fat.inc