FAT Filesystem Support

[中文]

ESP-IDF uses the FatFs 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 fatfs/vfs/esp_vfs_fat.h defines the functions for connecting FatFs and VFS.

The function 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 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 esp_vfs_fat_register() to specify:
    • Path prefix where to mount the filesystem (e.g. "/sdcard", "/spiflash")

    • FatFs drive number

    • A variable which will receive the pointer to the FATFS structure

  2. Call ff_diskio_register() to register the disk I/O driver for the drive number used in Step 1.

  3. Call the FatFs function f_mount, and optionally f_fdisk, f_mkfs, to mount the filesystem using the same drive number which was passed to esp_vfs_fat_register(). 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 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 CONFIG_FATFS_LONG_FILENAMES option. More details on the FatFs filenames are available here.

  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. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix (for example, "/hello.txt").

  7. Close all open files.

  8. Call the FatFs function f_mount for the same drive number, with NULL FATFS* argument, to unmount the filesystem.

  9. Call the FatFs function ff_diskio_register() with NULL ff_diskio_impl_t* argument and the same drive number to unregister the disk I/O driver.

  10. Call 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.

esp_err_t esp_vfs_fat_register(const char *base_path, const char *fat_drive, size_t max_files, FATFS **out_fs)

Register FATFS with VFS component.

This function registers given FAT drive in VFS, at the specified base path. 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.

Return

  • ESP_OK on success

  • ESP_ERR_INVALID_STATE if esp_vfs_fat_register was already called

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

Parameters
  • base_path: path prefix where FATFS should be registered

  • fat_drive: FATFS drive specification; if only one drive is used, can be an empty string

  • max_files: maximum number of files which can be open at the same time

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

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

Return

  • ESP_OK on success

  • ESP_ERR_INVALID_STATE if FATFS is not registered in VFS

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

Using FatFs with VFS and SD cards

The header file fatfs/vfs/esp_vfs_fat.h defines convenience functions esp_vfs_fat_sdmmc_mount(), esp_vfs_fat_sdspi_mount() and esp_vfs_fat_sdcard_unmount(). These function perform Steps 1–3 and 7–9 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 esp_vfs_fat_sdmmc_unmount() unmounts the filesystem and releases the resources acquired by esp_vfs_fat_sdmmc_mount().

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.

Return

  • ESP_OK on success

  • 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

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. (Deprecated) For SPI peripheral, pass a pointer to sdspi_slot_config_t structure initialized using SDSPI_SLOT_CONFIG_DEFAULT().

  • mount_config: pointer to structure with extra parameters for mounting FATFS

  • [out] out_card: if not NULL, pointer to the card information structure will be returned via this argument

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.

Return

  • ESP_OK on success

  • 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

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] out_card: If not NULL, 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.

struct esp_vfs_fat_mount_config_t

Configuration arguments for esp_vfs_fat_sdmmc_mount and esp_vfs_fat_spiflash_mount 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.

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()

Return

  • 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

Using FatFs with VFS in read-only mode

The header file fatfs/vfs/esp_vfs_fat.h also defines the convenience functions esp_vfs_fat_rawflash_mount() and esp_vfs_fat_rawflash_unmount(). 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.

esp_err_t esp_vfs_fat_rawflash_mount(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.

Return

  • 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_rawflash_mount 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

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

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

Unmount FAT filesystem and release resources acquired using esp_vfs_fat_rawflash_mount.

Return

  • ESP_OK on success

  • ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount hasn’t been called

Parameters
  • base_path: path where partition should be registered (e.g. “/spiflash”)

  • partition_label: label of partition to be unmounted

FatFS disk IO layer

FatFs has been extended with API functions that register the disk I/O driver at runtime.

They provide implementation of disk I/O functions for SD/MMC cards and can be registered for the given FatFs drive number using the function ff_diskio_register_sdmmc().

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, unsigned count)

sector read function

DRESULT (*write)(unsigned char pdrv, const unsigned char *buff, uint32_t sector, unsigned 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.

FATFS partition generator

We provide a partition generator for 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 (fatfsgen.py) and except for generating partition also initializes wear levelling.

Current implementation supports short file names and FAT12. Long file names, and FAT16 are subjects of the future work.

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 decided because of 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. 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 specified suitable size of the partition in the partition table.

  3. flag FLASH_IN_PROJECT - optionally, user can opt to have the image automatically flashed together with the app binaries, partition tables, etc. on idf.py flash -p <PORT> by specifying FLASH_IN_PROJECT.

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 storage/fatfsgen.