Merge branch 'docs/clarify-storage-example-readmes' into 'master'

docs(storage): clarify example READMEs and when to use each

Closes IDFGH-15037

See merge request espressif/esp-idf!51840
This commit is contained in:
Martin Vychodil
2026-08-25 18:26:23 +08:00
28 changed files with 221 additions and 51 deletions

View File

@@ -7,26 +7,30 @@ This directory contains a range of examples ESP-IDF projects. These are intended
The examples are grouped into sub-directories by category. Each category directory contains one or more example projects:
* `fatfs_basic` minimal example of FatFS usage on SPI FLASH
* `fatfs_advanced` example demonstrates how to use advanced features for working with FatFS such as automatic partition generation
* `custom_flash_driver` example demonstrates how to implement your own flash chip driver by overriding the default driver.
* `emmc` example demonstrates how to use an eMMC chip with an ESP device.
* `ext_flash_fatfs` example demonstrates how to use FATFS partition with external SPI FLASH chip.
* `fatfsgen` example demonstrates how to use FATFS partition generator
* `nvs_bootloader` example demonstrates how to read data from NVS in the bootloader code.
* `nvs_rw_blob` example demonstrates how to read and write a single integer value and a blob (binary large object) using NVS to preserve them between ESP module restarts.
* `nvs_rw_value` example demonstrates how to read and write a single integer value using NVS.
* `nvs_rw_value_cxx` example demonstrates how to read and write a single integer value using NVS (it uses the C++ NVS handle API).
* `nvs_console` example demonstrates how to use NVS through an interactive console interface.
* `nvs_statistics` example demonstrates how to obtain and interpret stats about used/available NVS storage entries in given NVS partition.
* `nvs_iteration` example demonstrates iterating over entries of specific (or any) data type in given namespace, and the info to be obtained about the entries while doing so.
* `partition_api` examples demonstrate how to use different partition APIs.
* `parttool` example demonstrates common operations the partitions tool allows the user to perform.
* `sd_card` examples demonstrate how to use an SD card with an ESP device.
* `semihost_vfs` example demonstrates how to use semihosting VFS driver with ESP device.
* `spiffs` example demonstrates how to use SPIFFS with ESP device.
* `spiffsgen` example demonstrates how to use the SPIFFS image generation tool spiffsgen.py to automatically create a SPIFFS.
* `wear_levelling` example demonstrates how to use wear levelling library and FATFS library to store files in a partition inside SPI flash.
* `fatfs/getting_started` minimal FATFS on internal SPI flash (mount / write / read / unmount). Wear levelling is used via `esp_vfs_fat_spiflash_mount_rw_wl`.
* `fatfs/fs_operations` — broader FATFS file and directory operations.
* `fatfs/ext_flash` — FATFS on an external SPI flash chip.
* `fatfs/fatfsgen` — build-time FATFS image generation.
* `fatfs/bdl_wl` — FATFS with wear-levelling block device layer (BDL).
* `wear_levelling` — wear levelling + FATFS lifecycle (mount, write/read, format, verify, rewrite). Not a duplicate of `fatfs/getting_started`; use that for the minimal first demo.
* `littlefs` — LittleFS on flash (wear management is built into LittleFS; not the wear_levelling component).
* `custom_flash_driver` — implement a custom flash chip driver by overriding the default driver.
* `emmc` — use an eMMC chip with an ESP device.
* `nvs/nvs_bootloader` — read NVS data from bootloader code.
* `nvs/nvs_rw_blob` — read/write an integer and a blob in NVS across restarts.
* `nvs/nvs_rw_value` — read/write a single integer in NVS.
* `nvs/nvs_rw_value_cxx` — same as `nvs/nvs_rw_value` using the C++ NVS handle API.
* `nvs/nvs_console` — interactive NVS console.
* `nvs/nvs_statistics` — NVS used/available entry statistics.
* `nvs/nvs_iteration` — iterate NVS entries by type/namespace.
* `nvs/nvsgen` — NVS partition / image generation helpers.
* `partition_api` — partition API examples.
* `parttool` — common host-side partition tool operations.
* `sd_card` — SD card examples.
* `semihost_vfs` — semihosting VFS driver.
* `spiffs` — SPIFFS on flash.
* `spiffsgen` — build-time SPIFFS image generation with spiffsgen.py.
* `perf_benchmark` — storage performance benchmarking.
# More

View File

@@ -9,6 +9,10 @@ This example shows how to override the default chip driver list provided by IDF.
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## When to use this example
- You need to support a flash chip that is not covered by the default IDF chip driver list, by providing your own chip driver.
## How to use example
Follow detailed instructions provided specifically for this example.

View File

@@ -19,6 +19,9 @@ This example demonstrates how to use an eMMC chip with an ESP device. Example do
This example supports eMMC chips.
## When to use this example
- Your board has a soldered eMMC chip connected over the SDMMC host (ESP32-S3 / ESP32-P4) and you want FATFS on it.
## Hardware

View File

@@ -26,6 +26,11 @@ The key advantage of BDL is that **the same `diskio_bdl` adapter works with any
You can swap the bottom of the stack (e.g., use `sdmmc_get_blockdev()` for an SD card) without
changing the FatFS integration code.
## When to use this example
- You want the newer Block Device Layer (BDL) approach to mounting FATFS instead of the legacy `wl_handle_t` API.
- You plan to reuse the same FATFS integration across different backends (flash partition, SD card, etc.).
## How to use example
### Build and flash

View File

@@ -17,6 +17,11 @@ The flow of the example is as follows:
4. Do some read and write operations using C standard library functions: create a file, write to it, open it for reading, print the contents to the console.
## When to use this example
- You need to add FATFS storage on an *external* SPI flash chip (e.g. to extend a module with only 4 MB of internal flash).
- You want to see how to register an external flash chip as a partition (`esp_flash_t` / `esp_partition_t`).
## How to use example
### Hardware required

View File

@@ -67,3 +67,8 @@ I (342) example: Done
The logic of the example is contained in a [single source file](./main/fatfsgen_example_main.c),
and it should be relatively simple to match points in its execution with the log outputs above.
## When to use this example
- You want to ship pre-created files on a FATFS partition, generated at build time from a host folder.
- You need a read-only or read-write FATFS image flashed together with the app.

View File

@@ -8,6 +8,11 @@
This example demonstrates some of the POSIX functions available for working with the FATFS filesystem.
Including basic read and write operations, as well as creating moving, and deleting files and directories.
## When to use this example
- You already know how to mount FATFS and want to see richer file/directory operations (`fstat`, append, list, `mkdir`, rename/move, delete).
- You need a reference for POSIX calls against a FATFS volume.
## Overview
1. Partition labeled `storage` is mounted (and formatted if necessary) as FATFS filesystem to `/spiflash` mountpoint.

View File

@@ -1,32 +1,49 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# FATFS minimal example
# FATFS getting started (minimal) example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates the minimal setup required to store persistent data on SPI Flash using the FAT filesystem.
Beware that the minimal required size of the flash is 4 MB.
## Purpose
Minimal FAT filesystem example for beginners: mount a FAT volume on internal SPI flash, write one file, read it back, then unmount.
Wear levelling is enabled by the mount API used here (`esp_vfs_fat_spiflash_mount_rw_wl`), which is required for safe read-write FAT on SPI flash.
## When to use this example
- You want the shortest path to store files with FATFS on internal SPI flash.
- You are learning the basic mount / write / read / unmount flow.
## What this example demonstrates
- Mount FAT on the `storage` partition with `esp_vfs_fat_spiflash_mount_rw_wl`
- Create and write a file with `fopen` / `fprintf`
- Read the file back with `fopen` / `fgets`
- Unmount with `esp_vfs_fat_spiflash_unmount_rw_wl`
Source: [main/fatfs_getting_started_main.c](./main/fatfs_getting_started_main.c)
## Requirements
- Internal SPI flash large enough for the example partition table (typically at least 4 MB modules)
- Partition label: `storage` (see [partitions_example.csv](./partitions_example.csv))
## How to use example
### Build and flash
To run the example, type the following command:
```CMake
# CMake
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
(Replace `PORT` with the serial port name. Exit the serial monitor with ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is the example's console output:
```
...
I (321) example: Mounting FAT filesystem
@@ -39,6 +56,3 @@ I (741) example: Unmounting FAT filesystem
I (851) example: Done
...
```
The logic of the example is contained in a [single source file](./main/fatfs_getting_started_main.c),
and it should be relatively simple to match points in its execution with the log outputs above.

View File

@@ -35,6 +35,11 @@ This example demonstrates how to use LittleFS with ESP32. Example does the follo
LittleFS partition size is set in partitions_demo_esp_littlefs.csv file. See [Partition Tables](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html) documentation for more information.
## When to use this example
- You want a power-fail-resilient flash filesystem with wear levelling built in (no separate wear_levelling component needed).
- You are choosing a modern general-purpose filesystem for internal flash and do not mind slower access speeds.
## How to use example
### Hardware required

View File

@@ -7,6 +7,11 @@ The purpose of this example is to show how to use the simplified, read-only API
A very practical application of being able to access the NVS in the bootloader build would be faster device restoration, where-in the application stores the device's current state/configurations and post a reset it would read the NVS to restore the device's last state, without waiting for application to boot-up.
## When to use this example
- You need to read NVS data from the bootloader (before the app starts), e.g. for fast state restoration.
- You want to use the simplified, read-only NVS bootloader API.
## Usage of this example:
Simply compile it:

View File

@@ -5,6 +5,11 @@
This example demonstrates how to use Non-Volatile Storage (NVS) through an interactive console interface. It provides a set of commands to read, write, and manage data in NVS.
## When to use this example
- You want to inspect and modify NVS interactively at runtime (set/get/erase/list keys across namespaces).
- You are debugging stored values or exploring NVS behavior without writing custom firmware.
## Hardware Required
This example can run on any ESP32 family development board.

View File

@@ -5,6 +5,11 @@
This example showcases how to iterate and obtain info about NVS entries of a specific (or any) NVS datatype.
## When to use this example
- You need to enumerate NVS entries in code, filtered by type and/or namespace (`nvs_entry_find` / `nvs_entry_info`).
- You are building tooling that discovers keys rather than reading known keys.
Default "nvs" partition is first erased to allow for clean example run, followed by writing 2 sets of key value pairs of different types to NVS storage.
After that, iteration is performed over the individual data types, as well as the generic `NVS_TYPE_ANY`, and relevant entry info gained from iteration is verbosely logged.
@@ -66,4 +71,4 @@ I (825) nvs_iteration_example: Iterated over 14 entries.
I (825) nvs_iteration_example: Returning from app_main().
I (835) main_task: Returned from app_main()
...
```
```

View File

@@ -16,6 +16,11 @@ Detailed functional description of NVS and API is provided in [documentation](ht
If not done already, consider checking simpler example *storage/nvs/nvs_rw_value*, that has been used as a starting point for preparing this one.
## When to use this example
- You need to store variable-length binary data (a blob), such as a table or struct, in NVS.
- You want to see blob read-modify-write across reboots, including a button-triggered update.
## How to use example
### Hardware required

View File

@@ -15,6 +15,11 @@ Detailed functional description of NVS and API is provided in [documentation](ht
Check another example *storage/nvs/nvs_rw_blob*, which shows how to read and write variable length binary data (blob).
## When to use this example
- You are new to NVS and want the simplest read/write of a single integer that survives reboots.
- You need a starting template for storing small configuration/counter values.
## How to use example
### Hardware required

View File

@@ -9,6 +9,10 @@ This example demonstrates how to read and write a single integer value using NVS
It is essentially the same as the nvs_rw_value example. The only difference is that it uses the C++ NVS handle API.
Please see [nvs_rw_value README](../nvs_rw_value/README.md) for more details about this example.
## When to use this example
- You are writing C++ and want the RAII-style C++ NVS handle API instead of the C API.
## How to use example
### Hardware required

View File

@@ -5,6 +5,11 @@
This example demonstrates the usage of obtaining and interpreting statistics about the a given NVS partition, namely free/used/available/total entries and namespace count.
## When to use this example
- You want to measure NVS partition usage (free/used/available/total entries, namespace count) via `nvs_get_stats()`.
- You need to understand blob storage overhead and fragmentation before sizing an NVS partition.
The default "nvs" partition is first erased, then a mock string data configuration is written to 2 different namespaces, followed by checking the changed statistics and mainly the number of newly used NVS entries.
Statistics obtained via [nvs_get_stats()](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/storage/nvs_flash.html#_CPPv413nvs_get_statsPKcP11nvs_stats_t) are the following:

View File

@@ -52,3 +52,8 @@ I (387) example: Reading values from NVS done - all OK
```
The logic of the example is contained in a [single source file](./main/nvsgen_example_main.c), and it should be relatively simple to match points in its execution with the log outputs above.
## When to use this example
- You want to pre-populate an NVS partition at build time from a CSV file and flash it with the app.
- You need factory/default configuration baked into NVS without writing it from firmware.

View File

@@ -8,6 +8,10 @@ These functions return the matching partitions given a set of constraints. By co
properties that returned results should match - notably partition type, subtype and label/name. In the case of `esp_partition_find_first`, the first matching instance is returned;
for `esp_partition_find`, an iterator is returned iterating over matching instances.
## When to use this example
- You need to locate partitions by type/subtype/label at runtime (`esp_partition_find` / `esp_partition_find_first`).
# Example Flow
The example uses a [custom partition table](./partitions_example.csv). The first part uses `esp_partition_find_first` to search for partition instances

View File

@@ -5,6 +5,10 @@
This example demonstrates how to use `esp_partition_mmap` to configure MMU and map a partition into memory address space for read operations.
## When to use this example
- You want to read a flash partition as if it were memory (memory-mapped), e.g. for zero-copy access to large read-only data.
# Example Flow
The example uses a [custom partition table](./partitions_example.csv), with a data partition `storage` used for demonstration. Before mapping this partition to memory,

View File

@@ -5,6 +5,10 @@
This example demonstrates how to perform partition read, write and erase operations using API functions `esp_partition_read`, `esp_partition_write` and `esp_partition_erase`.
## When to use this example
- You want raw read/write/erase access to a flash partition without a filesystem on top.
# Example Flow
The example uses a [custom partition table](./partitions_example.csv), with a data partition `storage` used as the demo partition. For the most part the example code is well-commented so users should be able to follow along the code easily. Nevertheless, this section provides an overview of the code flow.

View File

@@ -17,6 +17,10 @@ The example performs the operations mentioned above in a straightforward manner:
by reading it back. For partitions, contents are compared to the originally written file. For the partition table, contents are verified against the partition table CSV
file. An erased partition's contents is compared to a generated blank file.
## When to use this example
- You want to manipulate partitions from the *host* PC (read/write/erase, dump the partition table) using `parttool.py`.
## How to use example
### Build and Flash

View File

@@ -12,6 +12,11 @@ Only ESP32 and ESP32-S3 targets can use SDMMC mode when connecting to a SD card.
This example provides comparison between different types of storage in terms of speed under various configurable (from menuconfig) conditions
## When to use this example
- You want to benchmark and compare read/write speed across storage media and filesystems (SPI flash / SD card; raw, FATFS, SPIFFS, LittleFS).
- You are deciding which filesystem or medium best fits your performance needs.
Currently these mediums and file-systems are supported:
- SPI Flash
- Raw access

View File

@@ -18,6 +18,11 @@ This example demonstrates how to use an SD card with an ESP device. Example does
1. Create a file using `fopen` and write to it using `fprintf`.
1. Rename the file. Before renaming, check if destination file already exists using `stat` function, and remove it using `unlink` function.
1. Open renamed file for reading, read back the line, and print it to the terminal.
## When to use this example
- You have a removable SD/MMC card wired to the SDMMC host and want FATFS access with best throughput (1/4/8-line).
1. __OPTIONAL:__ Format the SD card, check if the file doesn't exist anymore.
This example supports SD (SDSC, SDHC, SDXC) cards and eMMC chips.

View File

@@ -18,6 +18,11 @@ This example demonstrates how to use an SD card with an ESP device over an SPI i
1. Create a file using `fopen` and write to it using `fprintf`.
1. Rename the file. Before renaming, check if destination file already exists using `stat` function, and remove it using `unlink` function.
1. Open renamed file for reading, read back the line, and print it to the terminal.
## When to use this example
- You want to access a removable SD card over the SPI bus, which works on any target and uses flexible GPIOs.
1. __OPTIONAL:__ Format the SD card, check if the file doesn't exist anymore.
This example support SD (SDSC, SDHC, SDXC) cards.

View File

@@ -14,6 +14,10 @@ This example demonstrates how to use semihosting VFS driver with ESP32. Example
5. Opens text file on the host.
6. Reads the file and prints its content on stdout.
## When to use this example
- You want the device to read/write files on the *host* PC through the debugger (semihosting), e.g. for logging or test data, without on-device storage.
## How to use example
### Hardware and tools required

View File

@@ -3,6 +3,8 @@
# SPIFFS example
**Note:** SPIFFS is not recommended for new designs. Use FATFS or LittleFS instead.
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use SPIFFS with ESP32. Example does the following steps:
@@ -17,6 +19,10 @@ This example demonstrates how to use SPIFFS with ESP32. Example does the followi
SPIFFS partition size is set in partitions_example.csv file. See [Partition Tables](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html) documentation for more information.
## When to use this example
- You need to work with a legacy SPIFFS image.
## How to use example
### Hardware required

View File

@@ -54,3 +54,7 @@ I (330) example: SPIFFS unmounted
```
The logic of the example is contained in a [single source file](./main/spiffsgen_example_main.c), and it should be relatively simple to match points in its execution with the log outputs above.
## When to use this example
- You want to ship pre-created files on a SPIFFS partition, generated at build time from a host folder.

View File

@@ -1,21 +1,52 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# Wear levelling example
# Wear levelling + FATFS example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use wear levelling library and FATFS library to store files in a partition inside SPI flash. Example does the following steps:
## Purpose
1. Use an "all-in-one" `esp_vfs_fat_spiflash_mount_rw_wl` function to:
- find a partition in SPI flash,
- initialize wear levelling library using this partition
- mount FAT filesystem using FATFS library (and format the filesystem, if the filesystem can not be mounted),
- register FAT filesystem in VFS, enabling C standard library and POSIX functions to be used.
2. Create a file using `fopen` and write to it using `fprintf`.
3. Open file for reading, read back the line, and print it to the terminal.
Demonstrate the wear levelling library together with FATFS on an internal SPI flash partition: mount, write/read files, format the FAT volume through the wear-levelling path, confirm files are gone, then write again and unmount.
Wear levelling partition size is set in partitions_example.csv file. See [Partition Tables](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html) documentation for more information.
## When to use this example
- You need the wear levelling + FATFS lifecycle, especially the format step (`esp_vfs_fat_spiflash_format_rw_wl`).
- You want to see mount → write/read → format → verify → rewrite → unmount in one flow.
Use a different example when you need:
- the shortest first FATFS demo → [fatfs/getting_started](../fatfs/getting_started/)
- FATFS on an external SPI flash chip → [fatfs/ext_flash](../fatfs/ext_flash/)
- broader FATFS file operations → [fatfs/fs_operations](../fatfs/fs_operations/)
### Wear levelling vs other storage
- **FATFS on SPI flash (this example):** use the wear_levelling component via `esp_vfs_fat_spiflash_mount_rw_wl` so repeated writes do not wear out the same flash sectors.
- **LittleFS:** wear management is part of the filesystem design; see [littlefs](../littlefs/) (does not use this wear_levelling component).
- **NVS:** flash wear is handled inside NVS; see [nvs](../nvs/) for keys/values, not general files.
## What this example demonstrates
1. Mount with the all-in-one API `esp_vfs_fat_spiflash_mount_rw_wl`, which:
- finds the `storage` partition in SPI flash
- initializes the wear levelling library on that partition
- mounts FATFS (and formats if mount fails when `format_if_mount_failed` is set)
- registers the volume in VFS so POSIX / C library file APIs work
2. Write a file (`fopen` / `fprintf`) and read it back
3. Format the mounted volume with `esp_vfs_fat_spiflash_format_rw_wl`
4. Verify the previous file no longer exists (`stat`)
5. Write and read a new file after format
6. Unmount with `esp_vfs_fat_spiflash_unmount_rw_wl`
Source: [main/wear_levelling_example_main.c](./main/wear_levelling_example_main.c)
Partition size is set in [partitions_example.csv](./partitions_example.csv). See [Partition Tables](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html).
## Requirements
- No special hardware; any common development board with enough internal flash for the partition table
- Partition label: `storage`
## How to use example
@@ -31,15 +62,15 @@ Build the project and flash it to the board, then run monitor tool to view seria
idf.py -p PORT flash monitor
```
(Replace PORT with serial port name.)
(To exit the serial monitor, type ``Ctrl-]``.)
(Replace `PORT` with the serial port name. Exit the serial monitor with ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
To wipe the wear-levelling / FAT contents and start clean, run `idf.py erase-flash`, then flash the example again.
## Example output
Here is a typical example console output.
Typical console output (IDs and IDF version string vary):
```
I (280) example: Mounting FAT filesystem
@@ -49,9 +80,14 @@ I (660) vfs_fat_spiflash: Mounting again
I (660) example: Opening file
I (910) example: File written
I (910) example: Reading file
I (920) example: Read from file: 'written using ESP-IDF v3.1-dev-171-gf9ad17eee-dirty'
I (920) example: Unmounting FAT filesystem
I (920) example: Read from file: 'hello world, from ESP-IDF <version>'
I (920) example: file does not exist, format done
I (920) example: Opening file
I (950) example: File written
I (950) example: Reading file
I (960) example: Read from file: 'nihao shijie, from ESP-IDF <version>'
I (960) example: Unmounting FAT filesystem
I (1000) example: Done
```
To erase the contents of wear levelling partition, run `idf.py erase-flash` command. Then upload the example again as described above.
The `f_mount failed` / formatting lines appear on a fresh (unformatted) partition; later runs may skip that path if the filesystem already exists.