# FAT Filesystem Support

[中文]

ESP-IDF uses the FatFs library to work with FAT filesystems through the FatFs component. After a FAT filesystem volume is mounted, the VFS layer exposes standard C library and POSIX file APIs.

Note

FatFs is an ambiguous term, as it refers to the filesystem itself, the upstream library, as well as the component in ESP-IDF. For clarity, this documentation uses the following terms:

- FAT filesystem: the on-disk FAT format (FAT12/FAT16/FAT32), exFAT (see Optional exFAT Support).

- FatFs library: the upstream FatFs library used by ESP-IDF.

- FatFs component: the ESP-IDF integration layer around the FatFs library (mount helpers, wrappers, and related APIs) in fatfs.

Other terms relevant to this documentation are explained in the Glossary section.

## Mount and Use FatFs

The FatFs component provides convenience wrappers for mounting filesystems through the VFS layer. Use these wrappers for most use cases instead of mounting the filesystem manually. For manual setup instructions, refer to Manually mounting a FAT filesystem partition.

The general mounting workflow is:

1. Select a mount path (for example, `"/spiflash"` or `"/sdcard"`) and set `esp_vfs_fat_mount_config_t`.

2. Mount the volume with a convenience helper from fatfs/vfs/esp_vfs_fat.h:

   > - `esp_vfs_fat_spiflash_mount_rw_wl()` for SPI flash partitions with wear leveling.

   > - `esp_vfs_fat_spiflash_mount_ro()` for read-only SPI flash partitions without wear leveling.

   > - `esp_vfs_fat_sdmmc_mount()` or `esp_vfs_fat_sdspi_mount()` for SD cards.

3. Use standard file APIs (`stdio.h` or POSIX) on paths under the mount path.

4. Close open files and call the matching unmount helper.

## Configuration Options

The following configuration options are available for the FatFs component:

- `CONFIG_FATFS_LONG_FILENAMES` - Selects how the FatFs library handles long filename (LFN) support. The available options are CONFIG_FATFS_LFN_NONE to disable LFN support and limit names to the 8.3 format (SFN only), CONFIG_FATFS_LFN_HEAP to enable LFN support with the LFN working buffer stored on the heap (default), and CONFIG_FATFS_LFN_STACK to enable LFN support with the LFN working buffer stored on the stack. For details, see FatFs filenames.

- CONFIG_FATFS_VOLUME_COUNT - Sets the number of logical FatFs volumes. Increasing this value can increase baseline memory usage.

- CONFIG_FATFS_ALLOC_PREFER_EXTRAM - If enabled, the FatFs library prefers external RAM when allocating internal buffers. If external RAM allocation fails, it falls back to internal RAM. This can have a noticeable performance cost on hot I/O paths. Disable this option to prioritize performance; enable it to reduce internal RAM usage.

- CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS - If enabled, the FatFs library tries to allocate heap work buffers in DMA-capable, cache-aligned memory first so SDMMC transfers avoid extra copies. This option is useful on targets that use PSRAM with SDMMC DMA (for example ESP32-P4). If this option and CONFIG_FATFS_ALLOC_PREFER_EXTRAM are both enabled, the FatFs library tries DMA-capable RAM first, then external RAM, then internal RAM.

- CONFIG_FATFS_USE_DYN_BUFFERS - If enabled, the FatFs library allocates instance buffers separately and sizes them according to each mounted volume's logical sector size. This option is useful when multiple FatFs instances use different logical sector sizes, as it can reduce memory usage. If disabled, all instances use buffers sized for the largest configured logical sector size.

- CONFIG_FATFS_PER_FILE_CACHE - If enabled, each open file uses a separate cache buffer. This improves I/O performance but increases RAM usage when multiple files are open. If disabled, a single shared cache is used, which reduces RAM usage but can increase storage read/write operations.

- CONFIG_FATFS_USE_FASTSEEK - If enabled, POSIX `lseek()` runs faster. Fast seek does not work for files opened in write mode. To use fast seek, open the file in read-only mode, or close and reopen it in read-only mode.

- CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE - Sets the CLMT (Cluster Link Map Table) buffer size used by fast seek when CONFIG_FATFS_USE_FASTSEEK is enabled. Larger buffers can improve seek behavior on larger files, but use more RAM.

- CONFIG_FATFS_VFS_FSTAT_BLKSIZE - Sets the default stdio file buffer block size used through VFS. This option is mainly relevant for stdio-based I/O (for example `fread`/`fgets`) and is not the primary tuning knob for direct POSIX `read`/`write` paths. Larger values can improve buffered read throughput, but increase heap usage.

- CONFIG_FATFS_IMMEDIATE_FSYNC - If enabled, the FatFs library calls `f_sync()` automatically after each call to `write()`, `pwrite()`, `link()`, `truncate()`, and `ftruncate()`. This option improves file consistency and size-reporting accuracy, but decreases performance because it triggers frequent disk operations.

- CONFIG_FATFS_LINK_LOCK - If enabled, this option guarantees API thread safety for the `link()` function. Disabling this option can help applications that perform frequent small file operations (for example, file logging). When disabled, the copy performed by `link()` is non-atomic. In that case, using `link()` on a large file on the same volume from another task is not guaranteed to be thread-safe.

- Other relevant options include CONFIG_FATFS_FS_LOCK, CONFIG_FATFS_TIMEOUT_MS, and `CONFIG_FATFS_CHOOSE_CODEPAGE` (especially `CONFIG_FATFS_CODEPAGE_DYNAMIC` for code-size impact). Additional options include `CONFIG_FATFS_SECTOR_SIZE`, `CONFIG_FATFS_MAX_LFN`, `CONFIG_FATFS_API_ENCODING`, and `CONFIG_FATFS_USE_STRFUNC_CHOICE`.

These options control how the FatFs library calculates and reports free space:

- CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT - If set to 1, the FatFs library ignores the free cluster count. The default value is 0.

- CONFIG_FATFS_DONT_TRUST_LAST_ALLOC - If set to 1, the FatFs library ignores the last allocation number. The default value is 0.

Note

Setting these options to 1 can improve `f_getfree()` accuracy, but it reduces performance, for example by forcing a full FAT scan.

## Differences from the POSIX Standard

1. `link()`: FAT filesystems do not support hard links, therefore `link()` copies file contents instead, which applies only to files on FAT filesystem volumes.

2. `unlink()`: If `CONFIG_FATFS_FS_LOCK` is enabled, removing an open file fails with `EBUSY`. Otherwise, behavior is undefined and can corrupt the filesystem.

3. `.` and `..` are not supported as references to the current and parent directory.

## Format a FAT Filesystem

Formatting creates a new FAT filesystem on the target volume and erases the existing directory structure and file data on that volume. Use it for first-time provisioning, or to recover from `FR_NO_FILESYSTEM`.

For mount-time auto-formatting, set `esp_vfs_fat_mount_config_t.format_if_mount_failed` to `true` before calling a mount helper. This is useful when the volume is expected to be blank on first boot. When formatting is triggered this way, the mount configuration also controls the new filesystem layout:

- `allocation_unit_size` sets the cluster size used by `f_mkfs()`. Larger values can improve throughput, but waste more space for many small files.

- `use_one_fat` creates one FAT instead of two. This saves some space, but reduces redundancy.

For explicit formatting after initialization, use the helper that matches the storage type:

- `esp_vfs_fat_spiflash_format_rw_wl()` or `esp_vfs_fat_spiflash_format_cfg_rw_wl()` for SPI flash partitions with wear leveling.

- `esp_vfs_fat_sdcard_format()` or `esp_vfs_fat_sdcard_format_cfg()` for SD cards.

The SPI flash formatting helpers can be called whether the filesystem is currently mounted or not. The SD card formatting helpers require the card (but not the filesystem) to be mounted first.

Read-only SPI flash partitions mounted with `esp_vfs_fat_spiflash_mount_ro()` cannot be reformatted on the target. To populate a read-only partition, generate the image on the host with FatFs Partition Generator.

## FatFs Partition Generator

ESP-IDF provides a FatFs partition generator, wl_fatfsgen.py , which is integrated into the build system.

Use this tool to create filesystem images on a host and populate them from a specified host folder.

The script is based on the partition generator (fatfsgen.py ). In addition to generating a FatFs partition, `wl_fatfsgen.py` initializes wear leveling, so it is typically used for writable SPI flash filesystems. Use `fatfsgen.py` instead for SD card images and read-only SPI flash images.

This tool supports short and long file names, FAT12, and FAT16. Long file names are limited to 255 characters and can contain multiple periods (`.`) in the file name, but not in the path. They can also contain the following additional characters: `+`, `,`, `;`, `=`, `[` and `]`.

An in-depth description of the FatFs partition generator and analyzer can be found at Generating and parsing FAT partition on host.

### Build System Integration with FatFs Partition Generator

Invoke the FatFs generator directly from the CMake build system by calling `fatfs_create_spiflash_image`:

    fatfs_create_spiflash_image(<partition> <base_dir> [optional arguments])

To generate a read-only partition without wear leveling support, use `fatfs_create_rawflash_image`:

    fatfs_create_rawflash_image(<partition> <base_dir> [optional arguments])

Call `fatfs_create_spiflash_image` or `fatfs_create_rawflash_image` from the project's `CMakeLists.txt`.

The function arguments are:

1. partition - Name of the partition as defined in the partition table (e.g., storage/fatfs/fatfsgen/partitions_example.csv).

2. base_dir - Directory encoded into the FAT filesystem partition and optionally flashed to the target. Make sure the partition table defines an appropriate partition size.

3. flag `FLASH_IN_PROJECT` - Optionally flash the image automatically with app binaries, partition tables, and other outputs when you run `idf.py flash -p <PORT>`. If `FLASH_IN_PROJECT` is not specified, the image is still generated, but you must flash it manually by using `esptool` or a custom build-system target.

4. flag `PRESERVE_TIME` - Optionally preserve timestamps from the source folder in the target image. Without this flag, the tool sets every timestamp to the FatFs library default initial time (1 January 1980).

5. flag `ONE_FAT` - Optionally generate a FAT filesystem volume with one FAT (File Allocation Table) instead of two. This increases free space in the FAT filesystem volume by `number of logical sectors used by one FAT * logical sector size`, but it also increases corruption risk.

For example:

    fatfs_create_spiflash_image(my_fatfs_partition my_folder FLASH_IN_PROJECT)

If you generate an image for an SD card, ESP-IDF does not currently provide a host-side flashing step to write that image directly to the card. Use other host tooling, such as `dd`, to deploy the image.

For an example project, see storage/fatfs/fatfsgen.

## FatFs Partition Parser

The fatfsparse.py tool performs the reverse operation of fatfsgen.py . It reconstructs a host folder structure from a FAT filesystem image.

Usage

    ./fatfsparse.py [-h] [--wl-layer {detect,enabled,disabled}] [--verbose] fatfs_image.img

The `--verbose` option prints detailed information from the FAT filesystem image boot sector before the tool generates the folder structure.

## Size Requirements and Limits

The FatFs component supports FAT12, FAT16, and FAT32 filesystem types, and can optionally support exFAT (see Optional exFAT Support).

The filesystem type depends on the number of clusters on the volume:

\[cluster\_count = data\_logical\_sectors / logical\_sectors\_per\_cluster\]

The minimum partition size therefore depends on the number of logical sectors required by FAT metadata and by at least one data cluster. For the terminology used below, see Glossary.

### Raw FAT Filesystem Size

The required size of a raw FAT filesystem consists of the FAT filesystem metadata plus the data area:

\[fatfs\_size = (reserved + fats + root\_dir + data) × logical\_sector\_size\]

Where:

- `reserved` is the number of reserved logical sectors

- `fats` is the total number of logical sectors occupied by all FAT copies

- `root_dir` is the number of logical sectors occupied by the root directory on FAT12/FAT16

- `data` is the number of logical sectors in the data area

The FAT area depends on the selected FAT type and the number of clusters:

FAT Type | Cluster Count | FAT Sizing
--- | --- | ---
FAT12 | `<= 4085` | Each FAT entry uses 12 bits, so one FAT copy requires `ceil(((cluster_count + 2) × 3 / 2) / logical_sector_size)` logical sectors.
FAT16 | `4085 < cluster_count < 65526` | Each FAT entry uses 16 bits, so one FAT copy requires `ceil(((cluster_count + 2) × 2) / logical_sector_size)` logical sectors.
FAT32 | `>= 65526` | Each FAT entry uses 32 bits, so one FAT copy requires `ceil(((cluster_count + 2) × 4) / logical_sector_size)` logical sectors.
exFAT | `16 .. 0x7FFFFFFD` | Each FAT entry uses 32 bits, so one FAT copy requires `ceil(((cluster_count + 2) × 4) / logical_sector_size)` logical sectors.

For FAT12 and FAT16, the root directory is outside the data area, so:

\[root\_dir = ceil((root\_dir\_entries × 32) / logical\_sector\_size)\]

For FAT32, the root directory is stored in the data area, so `root_dir = 0` in the formula above.

exFAT uses a different metadata layout. In addition to the FAT area, it requires an allocation bitmap and an up-case table, and its root directory is stored in the data area. As a result, the FAT12/FAT16 root-directory formula above does not apply to exFAT.

When exFAT support is enabled, the minimum exFAT volume size is 4096 logical sectors and the maximum cluster count is `0x7FFFFFFD`.

In practice:

- Increasing the partition size adds data logical sectors and therefore increases usable storage space.

- On small FAT12/FAT16 volumes, the root directory can occupy 1 logical sector. On larger ones, it can occupy 4 logical sectors.

- For FAT12, FAT16, and FAT32, the default layout uses two FATs. Compared with `use_one_fat = true`, this adds the logical sectors required by one extra FAT copy. exFAT uses a single FAT.

- For read-only partitions without wear leveling and with a 512-byte logical sector size, the practical minimum partition size is 2 KB. This minimum layout uses 4 logical sectors: 1 reserved sector, 1 FAT sector, 1 root-directory sector, and 1 data sector.

This minimum raw layout is relevant for media such as SD cards and read-only raw flash partitions.

### FAT Filesystem with Wear Leveling

For a flash partition with wear leveling, the total size is the raw FAT filesystem size from Raw FAT Filesystem Size plus the wear-leveling metadata area:

\[partition\_size = wl\_metadata\_flash\_sectors × flash\_sector\_size + fatfs\_size\]

Where:

- `wl_metadata_flash_sectors` is the number of flash sectors reserved for wear-leveling metadata

- `flash_sector_size` is the SPI flash erase-sector size. On almost all ESP boards it is 4096 bytes

- `fatfs_size` is the raw FAT filesystem size, as defined in Raw FAT Filesystem Size

The minimum supported partition size depends on the WL configuration:

Condition | Minimum Size | Notes
--- | --- | ---
`CONFIG_WL_SECTOR_SIZE = 4096` | 32 KB | The minimum layout consists of 4 flash sectors reserved by the wear leveling layer plus the minimum raw FAT filesystem layout of 4 logical sectors. In this configuration, the logical sector size and the flash-sector size are both 4096 bytes.
`CONFIG_WL_SECTOR_SIZE = 512` and WL Performance mode | 20 KB | The raw FAT filesystem still needs the same minimum layout of 4 logical sectors, but the wear leveling layer keeps its metadata in 4096-byte flash sectors.
`CONFIG_WL_SECTOR_SIZE = 512` and WL Safety mode | 28 KB | Same raw FAT minimum as above, plus 2 additional flash sectors reserved by the wear leveling layer.

For more details, see File System Considerations.

Note

The wear leveling layer protects the underlying flash by distributing write and erase cycles across the managed storage region. Its effectiveness therefore scales with the size of that region. Small partitions restrict wear distribution and can significantly reduce protection, so their use is strongly discouraged. For more information, refer to wear leveling.

## Optimization

FatFs behavior can be tuned for different priorities by choosing the right configuration options and filesystem layout.

The main variables that affect behavior are:

- Buffer placement and sizing (CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS, CONFIG_FATFS_ALLOC_PREFER_EXTRAM, CONFIG_FATFS_USE_DYN_BUFFERS, CONFIG_FATFS_PER_FILE_CACHE, and application I/O buffer sizes).

- Wear leveling logical sector size and mode (`CONFIG_WL_SECTOR_SIZE_*` and `CONFIG_WL_SECTOR_MODE_*`).

- Sync strategy (CONFIG_FATFS_IMMEDIATE_FSYNC).

- Workload pattern (transaction sizes, sequential vs random access, read vs write ratio).

### Optimize I/O Performance

For throughput-oriented workloads:

- Keep CONFIG_FATFS_IMMEDIATE_FSYNC disabled unless your consistency requirements need it.

- If peak speed is the top priority, disable CONFIG_FATFS_ALLOC_PREFER_EXTRAM so buffers stay in internal RAM.

- Prefer larger read/write transaction sizes over many small operations.

- Align transaction sizes to the active sector size when possible (for example 512 B or 4096 B), and pad writes if needed to reduce partial-sector overhead.

- For SPI flash with wear leveling, prefer `CONFIG_WL_SECTOR_SIZE_4096` when RAM budget allows, as it is generally more efficient.

- If using 512-byte WL sectors, use `CONFIG_WL_SECTOR_MODE_PERF` when your application can accept the higher power-loss risk during flash-sector erase.

- Prefer POSIX `read`/`write` over `fread`/`fwrite` on hot paths when possible. For broader speed guidance, see Maximizing Execution Speed.

- On SDMMC DMA targets (for example ESP32-P4 with PSRAM), enable CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS to reduce extra buffer copies.

- Enable CONFIG_FATFS_USE_FASTSEEK for read-heavy workloads with long backward seeks.

Note

For a baseline of what to expect in a performance-optimized scenario, see storage/perf_benchmark.

### Optimize Memory Usage

- Disable CONFIG_FATFS_PER_FILE_CACHE to use a single shared cache when reducing RAM usage is the priority.

- Tune `esp_vfs_fat_mount_config_t.max_files` (see Mount and Use FatFs) as low as practical; each simultaneously open file increases RAM usage.

- If CONFIG_FATFS_PER_FILE_CACHE is enabled, prefer `CONFIG_WL_SECTOR_SIZE_512` to reduce per-file cache size.

- If CONFIG_FATFS_PER_FILE_CACHE is disabled, `CONFIG_WL_SECTOR_SIZE_4096` may be a better tradeoff.

- Enable CONFIG_FATFS_ALLOC_PREFER_EXTRAM on targets with external RAM support to reduce internal RAM pressure, but expect lower I/O performance.

- Consider `CONFIG_FATFS_LONG_FILENAMES = CONFIG_FATFS_LFN_NONE` when SFN (8.3) filenames are acceptable.

- If long filenames are required, reduce `CONFIG_FATFS_MAX_LFN` to the smallest value that meets your needs.

- Enable CONFIG_FATFS_USE_DYN_BUFFERS so each mounted volume uses buffers sized to its actual sector size.

### Optimize Storage Efficiency

For maximizing usable filesystem capacity:

- For generated read-only images, consider the `ONE_FAT` option in `fatfs_create_spiflash_image` (see FatFs Partition Generator) to use one FAT instead of two.

- Consider `CONFIG_WL_SECTOR_SIZE_512` when minimizing overhead is a priority, as smaller sectors can improve usable storage efficiency in some layouts.

- Size partitions with margin. Very small partitions have proportionally higher metadata and wear leveling overhead.

- Keep long filenames short where possible; long names consume additional directory entries.

- For read-only data, consider raw FAT partitions without wear leveling where appropriate.

## Advanced Operations

Manual mounting may be required when you use storage media that ESP-IDF does not support directly or when you need access to low-level FatFs library functions.

### Optional exFAT Support

The upstream FatFs library includes optional exFAT support, but ESP-IDF does not enable it by default.

If your project requires exFAT, you must modify the FatFs configuration in the fatfs component manually and integrate the resulting configuration into your build and validation flow. ESP-IDF does not provide a dedicated menuconfig option or a standard high-level enablement path for exFAT.

Before enabling exFAT, review any licensing or other intellectual-property considerations that may apply to your product, distribution model, and target markets.

### Architecture Overview

The following diagram illustrates the layered architecture of FatFs and its relationship with other ESP-IDF components:

    +---------------------------------------------------------------+
    |              Newlib/Picolib (C Standard Library)              |
    |           fopen, fread, fwrite, fclose, fseek, etc.           |
    +---------------------------------------------------------------+
    |                  VFS (Virtual File System)                    |
    |  POSIX API: open, read, write, close, lseek, stat, etc.       |
    +---------------------------------------------------------------+
    |                       FatFs Library                           |
    |       f_mount, f_open, f_read, f_write, f_close, f_mkfs       |
    +---------------------------------------------------------------+
    |                      Disk I/O Layer                           |
    |  ff_diskio_register, disk_read, disk_write, disk_ioctl, etc.  |
    +-------------------------------+-------------------------------+
    |   Wear Leveling  (optional)   |                               |
    |  wl_mount, wl_read, wl_write  |        SD/MMC Driver          |
    +-------------------------------+                               |
    |         esp_partition         |   sdmmc_read/write_sectors    |
    |    esp_partition_read/write   |                               |
    +-------------------------------+-------------------------------+
    |           SPI Flash           |           SD Card             |
    +-------------------------------+-------------------------------+

### Manually Mount a FAT Filesystem Partition

When mounting a FAT filesystem partition manually, follow the same general flow used by the convenience wrappers described in Mount and Use FatFs: register the filesystem with the FatFs library, then mount it through the VFS.

1. Register the filesystem with the VFS by calling `esp_vfs_fat_register()`. This allocates the `FATFS` structure and sets up the interface between the VFS and the FatFs library. Specify:

   > - The path prefix where the filesystem will be mounted (for example, `"/sdcard"` or `"/spiflash"`).

   > - The FatFs drive number.

   > - A variable that receives a pointer to the `FATFS` structure.

2. Register the disk I/O driver for the drive number used in Step 1 by calling `ff_diskio_register()`.

3. Mount the filesystem for the drive number passed to `esp_vfs_fat_register()` by calling `f_mount()`.

   If no filesystem is present on the target logical drive, `f_mount()` fails with `FR_NO_FILESYSTEM`. In that case, create a new FAT filesystem on the drive with `f_mkfs()`, and then call `f_mount()` again.

   For SD cards, create a partition table first with `f_fdisk()`. For details, see the FatFs documentation.

To unmount, follow these general steps:

1. Unmount the filesystem by calling `f_mount()` with the same drive number and a NULL `FATFS*` argument.

2. Unregister the disk I/O driver by calling `ff_diskio_register()` with the same drive number and a NULL `ff_diskio_impl_t*` argument.

3. Remove the VFS registration and free the `FATFS` structure allocated in Step 1 of the mounting procedure by calling `esp_vfs_fat_unregister_path()` with the mount path.

When calling low-level functions provided by the FatFs library, use paths without the mount-point prefix. For example, use `"/hello.txt"`.

### FatFs Disk I/O Layer

FatFs provides APIs to register disk I/O drivers at runtime. These APIs form the interface between medium-specific access functions and the FatFs library.

The disk I/O layer uses `ff_diskio_impl_t` to provide medium access functions. Pass this structure to `ff_diskio_register()`.

ESP-IDF provides convenience wrappers for the supported storage media. These include:

> - `ff_diskio_register_wl_partition()` for SPI flash partitions with wear leveling.

> - `ff_diskio_register_raw_partition()` for read-only SPI flash partitions without wear leveling.

> - `ff_diskio_register_sdmmc()` for both SDMMC and SPI connected SD cards.

For API reference, see Disk I/O API Reference.

## Glossary

Term | Description
--- | ---
VFS | Virtual File System, an abstraction layer provided by ESP-IDF that allows applications to access different underlying filesystems through unified POSIX and `stdio.h` interfaces.
Logical Sector | The logical block size presented to FatFs and the disk I/O layer. For wear-leveled SPI flash, this is the WL sector size. For read-only raw SPI flash partitions, this is the flash-sector size. For SD cards, it is typically 512 bytes.
WL Sector | The logical sector size exposed by the wear leveling layer to FatFs. Depending on `CONFIG_WL_SECTOR_SIZE`, it is either 512 bytes or 4096 bytes.
Flash Sector | The underlying SPI flash erase unit used by the flash chip. On nearly all ESP boards, this is 4096 bytes. It can differ from the WL sector size presented to FatFs when wear leveling is configured for 512-byte sectors.
Cluster | The minimum logical FAT allocation unit, consisting of one or more contiguous logical sectors.
FAT | File Allocation Table, which records the usage status of each cluster and the linkage relationships between file data blocks.
Wear Leveling | A technique to extend the lifespan of flash memory by distributing write operations evenly across storage cells, preventing specific blocks from wearing out prematurely due to frequent erasing.
Drive Number | A number (0-9) used by FatFs to identify different logical drives, each corresponding to an independent filesystem instance.
Mount | The process of associating a filesystem with a specified path, enabling applications to access the filesystem contents through that path.
SFN/LFN | Short File Name (8.3 format) and Long File Name (up to 255 characters).

## Application Examples

- storage/fatfs/getting_started demonstrates the minimal setup required to store persistent data on SPI flash with FatFs, including mounting the filesystem, opening a file, performing basic read and write operations, and unmounting the filesystem.

- storage/fatfs/fs_operations demonstrates advanced FatFs operations, including reading and writing files, creating, moving, and deleting files and directories, and inspecting file details.

- storage/fatfs/ext_flash demonstrates how to operate an external SPI flash formatted with FatFs, including initializing the SPI bus, configuring the flash chip, registering it as a partition, and performing read and write operations.

## High-level API Reference

### Header File

- components/fatfs/vfs/esp_vfs_fat.h

- This header file can be included with:

  >     #include "esp_vfs_fat.h"

- This header file is a part of the API provided by the `fatfs` component. To declare that your component depends on `fatfs`, add the following to your CMakeLists.txt:

  >     REQUIRES fatfs

  > or

  >     PRIV_REQUIRES fatfs

### Functions

esp_err_t esp_vfs_fat_register(const esp_vfs_fat_conf_t *conf, FATFS **out_fs)

  Register FATFS with VFS component.

  This function registers given FAT drive in VFS, at the specified base path. Input arguments are held in esp_vfs_fat_conf_t structure. If only one drive is used, fat_drive argument can be an empty string. Refer to FATFS library documentation on how to specify FAT drive. This function also allocates FATFS structure which should be used for f_mount call.

  Note

  This function doesn't mount the drive into FATFS, it just connects POSIX and C standard library IO function with FATFS. You need to mount desired drive into FATFS separately.

  Parameters:

    - conf -- pointer to esp_vfs_fat_conf_t configuration structure

    - out_fs -- [out] pointer to FATFS structure which can be used for FATFS f_mount call is returned via this argument.

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_STATE if a filesystem is already registered at this base path. If `out_fs` is not NULL, `*out_fs` is set to the existing FATFS object so callers can run f_mount (e.g. remount the same path).

    - ESP_ERR_NO_MEM if not enough memory or too many VFSes already registered

esp_err_t esp_vfs_fat_unregister_path(const char *base_path)

  Un-register FATFS from VFS.

  Note

  FATFS structure returned by esp_vfs_fat_register is destroyed after this call. Make sure to call f_mount function to unmount it before calling esp_vfs_fat_unregister_ctx. Difference between this function and the one above is that this one will release the correct drive, while the one above will release the last registered one

  Parameters:

    base_path -- path prefix where FATFS is registered. This is the same used when esp_vfs_fat_register was called

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS

esp_err_t esp_vfs_fat_sdmmc_mount(const char *base_path, const sdmmc_host_t *host_config, const void *slot_config, const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t **out_card)

  Convenience function to get FAT filesystem on SD card registered in VFS.

  This is an all-in-one function which does the following:

  - initializes SDMMC driver or SPI driver with configuration in host_config

  - initializes SD card with configuration in slot_config

  - mounts FAT partition on SD card using FATFS library, with configuration in mount_config

  - registers FATFS library with VFS, with prefix given by base_prefix variable

  This function is intended to make example code more compact. For real world applications, developers should implement the logic of probing SD card, locating and mounting partition, and registering FATFS in VFS, with proper error checking and handling of exceptional conditions.

  Note

  Use this API to mount a card through SDSPI is deprecated. Please call `esp_vfs_fat_sdspi_mount()` instead for that case.

  Parameters:

    - base_path -- path where partition should be registered (e.g. "/sdcard")

    - host_config -- Pointer to structure describing SDMMC host. When using SDMMC peripheral, this structure can be initialized using SDMMC_HOST_DEFAULT() macro. When using SPI peripheral, this structure can be initialized using SDSPI_HOST_DEFAULT() macro.

    - slot_config -- Pointer to structure with slot configuration. For SDMMC peripheral, pass a pointer to sdmmc_slot_config_t structure initialized using SDMMC_SLOT_CONFIG_DEFAULT.

    - mount_config -- pointer to structure with extra parameters for mounting FATFS

    - out_card -- [out] pointer to the card information structure will be returned via this argument

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if any of the arguments is NULL

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called

    - ESP_ERR_NO_MEM if memory can not be allocated

    - ESP_FAIL if partition can not be mounted

    - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers

esp_err_t esp_vfs_fat_sdspi_mount(const char *base_path, const sdmmc_host_t *host_config_input, const sdspi_device_config_t *slot_config, const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t **out_card)

  Convenience function to get FAT filesystem on SD card registered in VFS.

  This is an all-in-one function which does the following:

  - initializes an SPI Master device based on the SPI Master driver with configuration in slot_config, and attach it to an initialized SPI bus.

  - initializes SD card with configuration in host_config_input

  - mounts FAT partition on SD card using FATFS library, with configuration in mount_config

  - registers FATFS library with VFS, with prefix given by base_prefix variable

  This function is intended to make example code more compact. For real world applications, developers should implement the logic of probing SD card, locating and mounting partition, and registering FATFS in VFS, with proper error checking and handling of exceptional conditions.

  Note

  This function try to attach the new SD SPI device to the bus specified in host_config. Make sure the SPI bus specified in `host_config->slot` have been initialized by `spi_bus_initialize()` before.

  Parameters:

    - base_path -- path where partition should be registered (e.g. "/sdcard")

    - host_config_input -- Pointer to structure describing SDMMC host. This structure can be initialized using SDSPI_HOST_DEFAULT() macro.

    - slot_config -- Pointer to structure with slot configuration. For SPI peripheral, pass a pointer to sdspi_device_config_t structure initialized using SDSPI_DEVICE_CONFIG_DEFAULT().

    - mount_config -- pointer to structure with extra parameters for mounting FATFS

    - out_card -- [out] Pointer to the card information structure will be returned via this argument. It is suggested to hold this handle and use it to unmount the card later if needed. Otherwise it's not suggested to use more than one card at the same time and unmount one of them in your application.

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if any of the arguments is NULL

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called

    - ESP_ERR_NO_MEM if memory can not be allocated

    - ESP_FAIL if partition can not be mounted

    - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers

esp_err_t esp_vfs_fat_sdcard_unmount(const char *base_path, sdmmc_card_t *card)

  Unmount an SD card from the FAT filesystem and release resources acquired using `esp_vfs_fat_sdmmc_mount()` or `esp_vfs_fat_sdspi_mount()`

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if the card argument is unregistered

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount hasn't been called

esp_err_t esp_vfs_fat_sdcard_format_cfg(const char *base_path, sdmmc_card_t *card, esp_vfs_fat_mount_config_t *cfg)

  Format FAT filesystem with given configuration.

  Note

  This API should be only called when the FAT is already mounted.

  Parameters:

    - base_path -- Path where partition should be registered (e.g. "/sdcard")

    - card -- Pointer to the card handle, which should be initialised by calling `esp_vfs_fat_sdspi_mount` first

    - cfg -- Pointer to structure with extra parameters for formatting FATFS (only relevant fields are used). If NULL, the previous configuration will be used.

  Returns:

    - ESP_OK

    - ESP_ERR_INVALID_STATE: FAT partition isn't mounted, call esp_vfs_fat_sdmmc_mount or esp_vfs_fat_sdspi_mount first

    - ESP_ERR_NO_MEM: if memory can not be allocated

    - ESP_FAIL: fail to format it, or fail to mount back

esp_err_t esp_vfs_fat_sdcard_format(const char *base_path, sdmmc_card_t *card)

  Format FAT filesystem.

  Note

  This API should be only called when the FAT is already mounted.

  Parameters:

    - base_path -- Path where partition should be registered (e.g. "/sdcard")

    - card -- Pointer to the card handle, which should be initialised by calling `esp_vfs_fat_sdspi_mount` first

  Returns:

    - ESP_OK

    - ESP_ERR_INVALID_STATE: FAT partition isn't mounted, call esp_vfs_fat_sdmmc_mount or esp_vfs_fat_sdspi_mount first

    - ESP_ERR_NO_MEM: if memory can not be allocated

    - ESP_FAIL: fail to format it, or fail to mount back

esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char *base_path, const char *partition_label, const esp_vfs_fat_mount_config_t *mount_config, wl_handle_t *wl_handle)

  Convenience function to initialize FAT filesystem in SPI flash and register it in VFS.

  This is an all-in-one function which does the following:

  - finds the partition with defined partition_label. Partition label should be configured in the partition table.

  - initializes flash wear levelling library on top of the given partition

  - mounts FAT partition using FATFS library on top of flash wear levelling library

  - registers FATFS library with VFS, with prefix given by base_prefix variable

  This function is intended to make example code more compact.

  Parameters:

    - base_path -- path where FATFS partition should be mounted (e.g. "/spiflash")

    - partition_label -- label of the partition which should be used

    - mount_config -- pointer to structure with extra parameters for mounting FATFS

    - wl_handle -- [out] wear levelling driver handle

  Returns:

    - ESP_OK on success

    - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount_rw_wl was already called

    - ESP_ERR_NO_MEM if memory can not be allocated

    - ESP_FAIL if partition can not be mounted

    - other error codes from wear levelling library, SPI flash driver, or FATFS drivers

esp_err_t esp_vfs_fat_spiflash_unmount_rw_wl(const char *base_path, wl_handle_t wl_handle)

  Unmount FAT filesystem and release resources acquired using esp_vfs_fat_spiflash_mount_rw_wl.

  Parameters:

    - base_path -- path where partition should be registered (e.g. "/spiflash")

    - wl_handle -- wear levelling driver handle returned by esp_vfs_fat_spiflash_mount_rw_wl

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount_rw_wl hasn't been called

esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char *base_path, const char *partition_label, esp_vfs_fat_mount_config_t *cfg)

  Format FAT filesystem with given configuration.

  Note

  This API can be called when the FAT is mounted / not mounted. If this API is called when the FAT isn't mounted (by calling esp_vfs_fat_spiflash_mount_rw_wl), this API will first mount the FAT then format it, then restore back to the original state.

  Parameters:

    - base_path -- Path where partition should be registered (e.g. "/spiflash")

    - partition_label -- Label of the partition which should be used

    - cfg -- Pointer to structure with extra parameters for formatting FATFS (only relevant fields are used). If NULL and mounted the previous configuration will be used. If NULL and unmounted the default configuration will be used.

  Returns:

    - ESP_OK

    - ESP_ERR_NO_MEM: if memory can not be allocated

    - Other errors from esp_vfs_fat_spiflash_mount_rw_wl

esp_err_t esp_vfs_fat_spiflash_format_rw_wl(const char *base_path, const char *partition_label)

  Format FAT filesystem.

  Note

  This API can be called when the FAT is mounted / not mounted. If this API is called when the FAT isn't mounted (by calling esp_vfs_fat_spiflash_mount_rw_wl), this API will first mount the FAT then format it, then restore back to the original state.

  Parameters:

    - base_path -- Path where partition should be registered (e.g. "/spiflash")

    - partition_label -- Label of the partition which should be used

  Returns:

    - ESP_OK

    - ESP_ERR_NO_MEM: if memory can not be allocated

    - Other errors from esp_vfs_fat_spiflash_mount_rw_wl

esp_err_t esp_vfs_fat_spiflash_mount_ro(const char *base_path, const char *partition_label, const esp_vfs_fat_mount_config_t *mount_config)

  Convenience function to initialize read-only FAT filesystem and register it in VFS.

  This is an all-in-one function which does the following:

  - finds the partition with defined partition_label. Partition label should be configured in the partition table.

  - mounts FAT partition using FATFS library

  - registers FATFS library with VFS, with prefix given by base_prefix variable

  Note

  Wear levelling is not used when FAT is mounted in read-only mode using this function.

  Parameters:

    - base_path -- path where FATFS partition should be mounted (e.g. "/spiflash")

    - partition_label -- label of the partition which should be used

    - mount_config -- pointer to structure with extra parameters for mounting FATFS

  Returns:

    - ESP_OK on success

    - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount_ro was already called for the same partition

    - ESP_ERR_NO_MEM if memory can not be allocated

    - ESP_FAIL if partition can not be mounted

    - other error codes from SPI flash driver, or FATFS drivers

esp_err_t esp_vfs_fat_spiflash_unmount_ro(const char *base_path, const char *partition_label)

  Unmount FAT filesystem and release resources acquired using esp_vfs_fat_spiflash_mount_ro.

  Parameters:

    - base_path -- path where partition should be registered (e.g. "/spiflash")

    - partition_label -- label of partition to be unmounted

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount_ro hasn't been called

esp_err_t esp_vfs_fat_bdl_mount(const char *base_path, esp_blockdev_handle_t bdl_handle, const esp_vfs_fat_mount_config_t *mount_config)

  Convenience function to mount a FatFS volume on a BDL (Block Device Layer) device.

  The FatFS logical sector size is derived from BDL geometry as LCM(FF_MIN_SS, read_size, write_size [, erase_size]). erase_size is included when it fits within FF_MAX_SS, making the sector erase-aligned for NOR-style devices and page-aligned for NAND-style devices (where the FTL/WL layer handles erase internally).

  The caller is responsible for constructing the BDL stack (e.g. partition BDL -> WL BDL) before calling this function. Read-only devices are detected automatically.

  Parameters:

    - base_path -- path where FATFS partition should be mounted (e.g. "/spiflash")

    - bdl_handle -- BDL device handle providing the storage

    - mount_config -- pointer to structure with extra parameters for mounting FATFS

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if any of the arguments is invalid

    - ESP_ERR_NO_MEM if memory can not be allocated or no free drives

    - ESP_FAIL if partition can not be mounted

esp_err_t esp_vfs_fat_bdl_unmount(const char *base_path, esp_blockdev_handle_t bdl_handle)

  Unmount FAT filesystem and release resources acquired using esp_vfs_fat_bdl_mount.

  Note

  This function does NOT release the BDL device handle — the caller owns the BDL stack lifecycle.

  Parameters:

    - base_path -- path where partition was registered (e.g. "/spiflash")

    - bdl_handle -- BDL device handle used during mount

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_STATE if esp_vfs_fat_bdl_mount hasn't been called

esp_err_t esp_vfs_fat_info(const char *base_path, uint64_t *out_total_bytes, uint64_t *out_free_bytes)

  Get information for FATFS partition.

  Parameters:

    - base_path -- Base path of the partition examined (e.g. "/spiflash")

    - out_total_bytes -- [out] Size of the file system

    - out_free_bytes -- [out] Free bytes available in the file system

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_STATE if partition not found

    - ESP_FAIL if another FRESULT error (saved in errno)

esp_err_t esp_vfs_fat_create_contiguous_file(const char *base_path, const char *full_path, uint64_t size, bool alloc_now)

  Create a file with contiguous space at given path.

  Note

  The file cannot exist before calling this function (or the file size has to be 0) For more information see documentation for `f_expand` from FATFS library

  Parameters:

    - base_path -- Base path of the partition examined (e.g. "/spiflash")

    - full_path -- Full path of the file (e.g. "/spiflash/ABC.TXT")

    - size -- File size expanded to, number of bytes in size to prepare or allocate for the file

    - alloc_now -- True == allocate space now, false == prepare to allocate – see `f_expand` from FATFS

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if invalid arguments (e.g. any of arguments are NULL or size lower or equal to 0)

    - ESP_ERR_INVALID_STATE if partition not found

    - ESP_FAIL if another FRESULT error (saved in errno)

esp_err_t esp_vfs_fat_test_contiguous_file(const char *base_path, const char *full_path, bool *is_contiguous)

  Test if a file is contiguous in the FAT filesystem.

  Parameters:

    - base_path -- Base path of the partition examined (e.g. "/spiflash")

    - full_path -- Full path of the file (e.g. "/spiflash/ABC.TXT")

    - is_contiguous -- [out] True == allocate space now, false == prepare to allocate – see `f_expand` from FATFS

  Returns:

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if invalid arguments (e.g. any of arguments are NULL)

    - ESP_ERR_INVALID_STATE if partition not found

    - ESP_FAIL if another FRESULT error (saved in errno)

### Structures

struct esp_vfs_fat_conf_t

  Configuration structure for esp_vfs_fat_register.

  Public Members

  const char *base_path

    Path prefix where FATFS should be registered,

  const char *fat_drive

    FATFS drive specification; if only one drive is used, can be an empty string.

  size_t max_files

    Maximum number of files which can be open at the same time.

struct esp_vfs_fat_mount_config_t

  Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount_rw_wl functions.

  Public Members

  bool format_if_mount_failed

    If FAT partition can not be mounted, and this parameter is true, create partition table and format the filesystem.

  int max_files

    Max number of open files.

  size_t allocation_unit_size

    If format_if_mount_failed is set, and mount fails, format the card with given allocation unit size. Must be a power of 2, between sector size and 128 * sector size. For SD cards, sector size is always 512 bytes. For wear_levelling, sector size is determined by CONFIG_WL_SECTOR_SIZE option.

    Using larger allocation unit size will result in higher read/write performance and higher overhead when storing small files.

    Setting this field to 0 will result in allocation unit set to the sector size.

  bool disk_status_check_enable

    Enables real ff_disk_status function implementation for SD cards (ff_sdmmc_status). Possibly slows down IO performance.

    Try to enable if you need to handle situations when SD cards are not unmounted properly before physical removal or you are experiencing issues with SD cards.

    Doesn't do anything for other memory storage media.

  bool use_one_fat

    Use 1 FAT (File Allocation Tables) instead of 2. This decreases reliability, but makes more space available (usually only one sector). Note that this option has effect only when the filesystem is formatted. When mounting an already-formatted partition, the actual number of FATs may be different.

### Macros

VFS_FAT_MOUNT_DEFAULT_CONFIG()

### Type Definitions

typedef PARTITION esp_vfs_fat_pdrv_part_t

typedef LBA_t esp_vfs_fat_drive_divide_arr_t[4]

  For example:

  `{100, 0, 0, 0}` will create a single partition with 100% of the drive space. `{50, 50, 0, 0}` will create two partitions, first with 50% of the drive space and second with the remaining 50%. `{0x10000000, 0x10000000, 0x10000000, 0}` will create three partitions, each with a size of 256 MiB, leaving remaining space non-allocated.

  Note

  When the value of item is less than or equal to 100, it specifies the partition size in percentage of the entire drive space. When it is larger than 100, it specifies number of sectors. The partition map table is terminated by a zero, 4th partition in MBR format or no remaining space for next allocation. If the specified size is larger than remaining space on the drive, the partition is truncated at end of the drive.

typedef esp_vfs_fat_mount_config_t esp_vfs_fat_sdmmc_mount_config_t

### Enumerations

enum vfs_fat_x_ctx_flags_t

  Values:

  enumerator FORMATTED_DURING_LAST_MOUNT

### Disk I/O API Reference

void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t *discio_impl)

  Register or unregister diskio driver for given drive number.

  When FATFS library calls one of disk_xxx functions for driver number pdrv, corresponding function in discio_impl for given pdrv will be called.

  Parameters:

    - pdrv -- drive number

    - discio_impl -- pointer to ff_diskio_impl_t structure with diskio functions or NULL to unregister and free previously registered drive

struct ff_diskio_impl_t

  Structure of pointers to disk IO driver functions.

  See FatFs documentation for details about these functions

  Public Members

  DSTATUS (*init)(unsigned char pdrv)

    disk initialization function

  DSTATUS (*status)(unsigned char pdrv)

    disk status check function

  DRESULT (*read)(unsigned char pdrv, unsigned char *buff, uint32_t sector, UINT count)

    sector read function

  DRESULT (*write)(unsigned char pdrv, const unsigned char *buff, uint32_t sector, UINT count)

    sector write function

  DRESULT (*ioctl)(unsigned char pdrv, unsigned char cmd, void *buff)

    function to get info about disk and do some misc operations

void ff_diskio_register_sdmmc(unsigned char pdrv, sdmmc_card_t *card)

  Register SD/MMC diskio driver

  Parameters:

    - pdrv -- drive number

    - card -- pointer to sdmmc_card_t structure describing a card; card should be initialized before calling f_mount.

esp_err_t ff_diskio_register_wl_partition(unsigned char pdrv, wl_handle_t flash_handle)

  Register spi flash partition

  Parameters:

    - pdrv -- drive number

    - flash_handle -- handle of the wear levelling partition.

esp_err_t ff_diskio_register_raw_partition(unsigned char pdrv, const esp_partition_t *part_handle)

  Register spi flash partition

  Parameters:

    - pdrv -- drive number

    - part_handle -- pointer to raw flash partition.

Was this page helpful?

- Thank you! We received your feedback.
- If you have any comments, fill in Espressif Documentation Feedback Form.

- We value your feedback.
- Let us know how we can improve this page by filling in Espressif Documentation Feedback Form.