forked from espressif/esp-idf
Merge branch 'feat/simplify_storage_examples' into 'master'
feat(storage/fatfs): update fatfs examples Closes IDF-5705 See merge request espressif/esp-idf!31174
This commit is contained in:
@@ -105,7 +105,7 @@ The most supported file system, recommended for common applications - file/direc
|
|||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
* :example:`storage/sd_card`: access the SD card which uses the FAT file system
|
* :example:`storage/sd_card`: access the SD card which uses the FAT file system
|
||||||
* :example:`storage/ext_flash_fatfs`: access the external flash chip which uses the FAT file system
|
* :example:`storage/fatfs/ext_flash`: access the external flash chip which uses the FAT file system
|
||||||
|
|
||||||
|
|
||||||
.. _spiffs-fs-section:
|
.. _spiffs-fs-section:
|
||||||
|
@@ -301,9 +301,9 @@ Improving I/O Performance
|
|||||||
|
|
||||||
Using standard C library functions like ``fread`` and ``fwrite`` instead of platform-specific unbuffered syscalls such as ``read`` and ``write``, may result in slower performance.
|
Using standard C library functions like ``fread`` and ``fwrite`` instead of platform-specific unbuffered syscalls such as ``read`` and ``write``, may result in slower performance.
|
||||||
|
|
||||||
The ``fread`` and ``fwrite`` functions are designed for portability rather than speed, introducing some overhead due to their buffered nature. Check the example :example:`storage/fatfsgen` to see how to use these two functions.
|
The ``fread`` and ``fwrite`` functions are designed for portability rather than speed, introducing some overhead due to their buffered nature. Check the example :example:`storage/fatfs/getting_started` to see how to use these two functions.
|
||||||
|
|
||||||
In contrast, the ``read`` and ``write`` functions are standard POSIX APIs that can be used directly when working with FatFs through VFS, with ESP-IDF handling the underlying implementation. Check the example :example:`storage/perf_benchmark` to see how to use the two functions.
|
In contrast, the ``read`` and ``write`` functions are standard POSIX APIs that can be used directly when working with FatFs through VFS, with ESP-IDF handling the underlying implementation. Check the example :example:`storage/fatfs/fs_operations` to see how to use the two functions.
|
||||||
|
|
||||||
Additional tips are provided below, and further details can be found in :doc:`/api-reference/storage/fatfs`.
|
Additional tips are provided below, and further details can be found in :doc:`/api-reference/storage/fatfs`.
|
||||||
|
|
||||||
|
@@ -123,7 +123,7 @@ If you decide for any reason to use ``fatfs_create_rawflash_image`` (without wea
|
|||||||
|
|
||||||
The arguments of the function are as follows:
|
The arguments of the function are as follows:
|
||||||
|
|
||||||
#. partition - the name of the partition as defined in the partition table (e.g., :example_file:`storage/fatfsgen/partitions_example.csv`).
|
#. partition - the name of the partition as defined in the partition table (e.g., :example_file:`storage/fatfs/fatfsgen/partitions_example.csv`).
|
||||||
|
|
||||||
#. base_dir - the directory that will be encoded to FatFs partition and optionally flashed into the device. Beware that you have to specify the suitable size of the partition in the partition table.
|
#. base_dir - the directory that will be encoded to FatFs partition and optionally flashed into the device. Beware that you have to specify the suitable size of the partition in the partition table.
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ For example::
|
|||||||
|
|
||||||
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.
|
If FLASH_IN_PROJECT is not specified, the image will still be generated, but you will have to flash it manually using ``esptool.py`` or a custom build system target.
|
||||||
|
|
||||||
For an example, see :example:`storage/fatfsgen`.
|
For an example, see :example:`storage/fatfs/fatfsgen`.
|
||||||
|
|
||||||
|
|
||||||
.. _fatfs-partition-analyzer:
|
.. _fatfs-partition-analyzer:
|
||||||
|
@@ -37,22 +37,15 @@ For information about storage security, please refer to :doc:`Storage Security <
|
|||||||
wear-levelling
|
wear-levelling
|
||||||
storage-security.rst
|
storage-security.rst
|
||||||
|
|
||||||
.. list-table:: Code Examples for Storage API
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. list-table:: NVS API examples
|
||||||
:widths: 25 75
|
:widths: 25 75
|
||||||
:header-rows: 0
|
:header-rows: 0
|
||||||
|
|
||||||
* - **Code Example**
|
* - **Code Example**
|
||||||
- **Description**
|
- **Description**
|
||||||
* - :doc:`fatfs`
|
|
||||||
-
|
|
||||||
* - :example:`wear_leveling <storage/wear_levelling>`
|
|
||||||
- Demonstrates using FATFS over wear leveling on internal flash.
|
|
||||||
* - :example:`ext_flash_fatfs <storage/ext_flash_fatfs>`
|
|
||||||
- Demonstrates using FATFS over wear leveling on external flash.
|
|
||||||
* - :example:`fatfsgen <storage/fatfsgen>`
|
|
||||||
- Demonstrates the capabilities of Python-based tooling for FATFS images available on host computers.
|
|
||||||
* - :doc:`nvs_flash`
|
|
||||||
-
|
|
||||||
* - :example:`nvs_rw_blob <storage/nvs_rw_blob>`
|
* - :example:`nvs_rw_blob <storage/nvs_rw_blob>`
|
||||||
- Shows the use of the C-style API to read and write blob data types in NVS flash.
|
- Shows the use of the C-style API to read and write blob data types in NVS flash.
|
||||||
* - :example:`nvs_rw_value <storage/nvs_rw_value>`
|
* - :example:`nvs_rw_value <storage/nvs_rw_value>`
|
||||||
@@ -61,20 +54,59 @@ For information about storage security, please refer to :doc:`Storage Security <
|
|||||||
- Shows the use of the C++-style API to read and write integer data types in NVS flash.
|
- Shows the use of the C++-style API to read and write integer data types in NVS flash.
|
||||||
* - :example:`nvsgen <storage/nvsgen>`
|
* - :example:`nvsgen <storage/nvsgen>`
|
||||||
- Demonstrates how to use the Python-based NVS image generation tool to create an NVS partition image from the contents of a CSV file.
|
- Demonstrates how to use the Python-based NVS image generation tool to create an NVS partition image from the contents of a CSV file.
|
||||||
* - :doc:`spiffs`
|
|
||||||
-
|
.. list-table:: Common Filesystem API
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **Code Example**
|
||||||
|
- **Description**
|
||||||
|
* - :example:`fatfs/getting_started <storage/fatfs/getting_started>`
|
||||||
|
- Demonstrates basic common file API (stdio.h) usage over internal flash using FATFS.
|
||||||
|
* - :example:`fatfs/fs_operations <storage/fatfs/fs_operations>`
|
||||||
|
- Demonstrates POSIX API for filesystem manipulation, such as moving, removing and renaming files.
|
||||||
|
|
||||||
|
.. list-table:: FATFS API examples
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **Code Example**
|
||||||
|
- **Description**
|
||||||
|
* - :example:`fatfsgen <storage/fatfs/fatfsgen>`
|
||||||
|
- Demonstrates the capabilities of Python-based tooling for FATFS images available on host computers.
|
||||||
|
* - :example:`ext_flash_fatfs <storage/fatfs/ext_flash>`
|
||||||
|
- Demonstrates using FATFS over wear leveling on external flash.
|
||||||
|
* - :example:`wear_leveling <storage/wear_levelling>`
|
||||||
|
- Demonstrates using FATFS over wear leveling on internal flash.
|
||||||
|
|
||||||
|
.. list-table:: SPIFFS API examples
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **Code Example**
|
||||||
|
- **Description**
|
||||||
* - :example:`spiffs <storage/spiffs>`
|
* - :example:`spiffs <storage/spiffs>`
|
||||||
- Shows the use of the SPIFFS API to initialize the filesystem and work with files using POSIX functions.
|
- Shows the use of the SPIFFS API to initialize the filesystem and work with files using POSIX functions.
|
||||||
* - :example:`spiffsgen <storage/spiffsgen>`
|
* - :example:`spiffsgen <storage/spiffsgen>`
|
||||||
- Demonstrates the capabilities of Python-based tooling for SPIFFS images available on host computers.
|
- Demonstrates the capabilities of Python-based tooling for SPIFFS images available on host computers.
|
||||||
* - :doc:`partition`
|
|
||||||
-
|
.. list-table:: Partition API examples
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **Code Example**
|
||||||
|
- **Description**
|
||||||
* - :example:`partition_api <storage/partition_api>`
|
* - :example:`partition_api <storage/partition_api>`
|
||||||
- Provides an overview of API functions to look up particular partitions, perform basic I/O operations, and use partitions via CPU memory mapping.
|
- Provides an overview of API functions to look up particular partitions, perform basic I/O operations, and use partitions via CPU memory mapping.
|
||||||
* - :example:`parttool <storage/parttool>`
|
* - :example:`parttool <storage/parttool>`
|
||||||
- Demonstrates the capabilities of Python-based tooling for partition images available on host computers.
|
- Demonstrates the capabilities of Python-based tooling for partition images available on host computers.
|
||||||
* - :doc:`vfs`
|
|
||||||
-
|
.. list-table:: VFS related examples
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **Code Example**
|
||||||
|
- **Description**
|
||||||
* - :example:`littlefs <storage/littlefs>`
|
* - :example:`littlefs <storage/littlefs>`
|
||||||
- Shows the use of the LittleFS component to initialize the filesystem and work with a file using POSIX functions.
|
- Shows the use of the LittleFS component to initialize the filesystem and work with a file using POSIX functions.
|
||||||
* - :example:`semihost_vfs <storage/semihost_vfs>`
|
* - :example:`semihost_vfs <storage/semihost_vfs>`
|
||||||
|
@@ -301,9 +301,9 @@ ESP-IDF 支持动态 :doc:`/api-reference/system/intr_alloc` 和中断抢占。
|
|||||||
|
|
||||||
使用标准 C 库函数,如 ``fread`` 和 ``fwrite``,相较于使用平台特定的不带缓冲系统调用,如 ``read`` 和 ``write``,可能会导致 I/O 性能下降。
|
使用标准 C 库函数,如 ``fread`` 和 ``fwrite``,相较于使用平台特定的不带缓冲系统调用,如 ``read`` 和 ``write``,可能会导致 I/O 性能下降。
|
||||||
|
|
||||||
``fread`` 与 ``fwrite`` 函数是为可移植性而设计的,而非速度,其缓冲性质会引入一些额外的开销。关于如何使用这两个函数,请参考示例 :example:`storage/fatfsgen`。
|
``fread`` 与 ``fwrite`` 函数是为可移植性而设计的,而非速度,其缓冲性质会引入一些额外的开销。关于如何使用这两个函数,请参考示例 :example:`storage/fatfs/getting_started`。
|
||||||
|
|
||||||
与之相比,``read`` 与 ``write`` 函数是标准的 POSIX API,可直接通过 VFS 处理 FatFs,由 ESP-IDF 负责底层实现。关于如何使用这两个函数,请参考示例 :example:`storage/perf_benchmark`。
|
与之相比,``read`` 与 ``write`` 函数是标准的 POSIX API,可直接通过 VFS 处理 FatFs,由 ESP-IDF 负责底层实现。关于如何使用这两个函数,请参考示例 :example:`storage/fatfs/fs_operations`。
|
||||||
|
|
||||||
下面提供了一些提示,更多信息请见 :doc:`/api-reference/storage/fatfs`。
|
下面提供了一些提示,更多信息请见 :doc:`/api-reference/storage/fatfs`。
|
||||||
|
|
||||||
|
@@ -123,7 +123,7 @@ FatFs 分区生成器
|
|||||||
|
|
||||||
该函数的参数如下:
|
该函数的参数如下:
|
||||||
|
|
||||||
#. partition - 分区的名称,需要在分区表中定义(如 :example_file:`storage/fatfsgen/partitions_example.csv`)。
|
#. partition - 分区的名称,需要在分区表中定义(如 :example_file:`storage/fatfs/fatfsgen/partitions_example.csv`)。
|
||||||
|
|
||||||
#. base_dir - 目录名称,该目录会被编码为 FatFs 分区,也可以选择将其被烧录进设备。但注意必须在分区表中指定合适的分区大小。
|
#. base_dir - 目录名称,该目录会被编码为 FatFs 分区,也可以选择将其被烧录进设备。但注意必须在分区表中指定合适的分区大小。
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ FatFs 分区生成器
|
|||||||
|
|
||||||
没有指定 FLASH_IN_PROJECT 时也可以生成分区镜像,但是用户需要使用 ``esptool.py`` 或自定义的构建系统目标对其手动烧录。
|
没有指定 FLASH_IN_PROJECT 时也可以生成分区镜像,但是用户需要使用 ``esptool.py`` 或自定义的构建系统目标对其手动烧录。
|
||||||
|
|
||||||
相关示例请查看 :example:`storage/fatfsgen`。
|
相关示例请查看 :example:`storage/fatfs/fatfsgen`。
|
||||||
|
|
||||||
|
|
||||||
.. _fatfs-partition-analyzer:
|
.. _fatfs-partition-analyzer:
|
||||||
|
@@ -37,44 +37,76 @@
|
|||||||
wear-levelling
|
wear-levelling
|
||||||
storage-security.rst
|
storage-security.rst
|
||||||
|
|
||||||
|
示例
|
||||||
|
----
|
||||||
|
|
||||||
.. list-table:: 存储 API 相关例程
|
.. list-table:: 存储 API 相关例程
|
||||||
:widths: 25 75
|
:widths: 25 75
|
||||||
:header-rows: 0
|
:header-rows: 0
|
||||||
|
|
||||||
* - **例程**
|
* - **例程**
|
||||||
- **描述**
|
- **描述**
|
||||||
* - :doc:`fatfs`
|
|
||||||
-
|
|
||||||
* - :example:`wear_leveling <storage/wear_levelling>`
|
|
||||||
- 演示了如何在内部 flash 上使用 FATFS 磨损均衡。
|
|
||||||
* - :example:`ext_flash_fatfs <storage/ext_flash_fatfs>`
|
|
||||||
- 演示了如何在外部 flash 上使用 FATFS 磨损均衡。
|
|
||||||
* - :example:`fatfsgen <storage/fatfsgen>`
|
|
||||||
- 演示了在主机计算机上使用 Python 工具生成 FATFS 镜像的功能。
|
|
||||||
* - :doc:`nvs_flash`
|
|
||||||
-
|
|
||||||
* - :example:`nvs_rw_blob <storage/nvs_rw_blob>`
|
* - :example:`nvs_rw_blob <storage/nvs_rw_blob>`
|
||||||
- 演示了如何在 NVS flash 中使用 C 语言 API 读写 blob 数据类型。
|
- 演示了如何在 NVS flash 中使用 C 语言 API 读写 blob 数据类型。
|
||||||
* - :example:`nvs_rw_value <storage/nvs_rw_value>`
|
* - :example:`nvs_rw_value <storage/nvs_rw_value>`
|
||||||
- 演示了如何在 NVS flash 中使用 C 语言 API 读写整数数据类型。
|
- 演示了如何在 NVS flash 中使用 C 语言 API 读写整数数据类型。
|
||||||
* - :example:`nvs_rw_value_cxx <storage/nvs_rw_value_cxx>`
|
* - :example:`nvs_rw_value <storage/nvs_rw_value>`
|
||||||
- 演示了如何在 NVS flash 中使用 C++ 语言 API 读写整数数据类型。
|
- 演示了如何在 NVS flash 中使用 C++ 语言 API 读写整数数据类型。
|
||||||
* - :example:`nvsgen <storage/nvsgen>`
|
* - :example:`nvsgen <storage/nvsgen>`
|
||||||
- 演示了如何使用基于 Python 的 NVS 镜像生成工具,根据 CSV 文件内容创建 NVS 分区镜像。
|
- 演示了如何使用基于 Python 的 NVS 镜像生成工具,根据 CSV 文件内容创建 NVS 分区镜像。
|
||||||
* - :doc:`spiffs`
|
|
||||||
-
|
.. list-table:: 常用文件系统 API
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **代码示例**
|
||||||
|
- **描述**
|
||||||
|
* - :example:`fatfs/getting_started <storage/fatfs/getting_started>`
|
||||||
|
- 演示了如何使用 FATFS 库在内部 flash 上应用标准文件 API (stdio.h)。
|
||||||
|
* - :example:`fatfs/fs_operations <storage/fatfs/fs_operations>`
|
||||||
|
- 演示了如何使用 POSIX API 进行文件系统操作,如移动、删除和重命名文件等。
|
||||||
|
|
||||||
|
.. list-table:: FATFS API 示例
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **代码示例**
|
||||||
|
- **描述**
|
||||||
|
* - :example:`fatfsgen <storage/fatfs/fatfsgen>`
|
||||||
|
- 演示了在主机上使用 Python 工具生成 FATFS 镜像的相关功能。
|
||||||
|
* - :example:`ext_flash_fatfs <storage/fatfs/ext_flash>`
|
||||||
|
- 演示了在外部 flash 上使用带有磨损均衡功能的 FATFS。
|
||||||
|
* - :example:`wear_leveling <storage/wear_levelling>`
|
||||||
|
- 演示了在内部 flash 上使用带有磨损均衡功能的 FATFS。
|
||||||
|
|
||||||
|
.. list-table:: SPIFFS API 示例
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **代码示例**
|
||||||
|
- **描述**
|
||||||
* - :example:`spiffs <storage/spiffs>`
|
* - :example:`spiffs <storage/spiffs>`
|
||||||
- 演示了如何使用 SPIFFS API 初始化文件系统,并使用 POSIX 函数处理文件。
|
- 演示了如何使用 SPIFFS API 初始化文件系统,并使用 POSIX 函数处理文件。
|
||||||
* - :example:`spiffsgen <storage/spiffsgen>`
|
* - :example:`spiffsgen <storage/spiffsgen>`
|
||||||
- 演示了在主机计算机上使用 Python 工具生成 SPIFFS 镜像的功能。
|
- 演示了在主机计算机上使用 Python 工具生成 SPIFFS 镜像的功能。
|
||||||
* - :doc:`partition`
|
|
||||||
-
|
.. list-table:: 分区 API 示例
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **代码示例**
|
||||||
|
- **描述**
|
||||||
* - :example:`partition_api <storage/partition_api>`
|
* - :example:`partition_api <storage/partition_api>`
|
||||||
- 介绍了用于查找特定分区、执行基本 I/O 操作以及通过 CPU 内存映射使用分区的 API 函数。
|
- 介绍了用于查找特定分区、执行基本 I/O 操作以及通过 CPU 内存映射使用分区的 API 函数。
|
||||||
* - :example:`parttool <storage/parttool>`
|
* - :example:`parttool <storage/parttool>`
|
||||||
- 演示了在主机计算机上使用 Python 工具生成分区镜像的功能。
|
- 演示了在主机计算机上使用 Python 工具生成分区镜像的功能。
|
||||||
* - :doc:`vfs`
|
|
||||||
-
|
.. list-table:: VFS 相关示例
|
||||||
|
:widths: 25 75
|
||||||
|
:header-rows: 0
|
||||||
|
|
||||||
|
* - **代码示例**
|
||||||
|
- **描述**
|
||||||
* - :example:`littlefs <storage/littlefs>`
|
* - :example:`littlefs <storage/littlefs>`
|
||||||
- 演示了如何使用 LittleFS 组件初始化文件系统,并使用 POSIX 函数处理文件。
|
- 演示了如何使用 LittleFS 组件初始化文件系统,并使用 POSIX 函数处理文件。
|
||||||
* - :example:`semihost_vfs <storage/semihost_vfs>`
|
* - :example:`semihost_vfs <storage/semihost_vfs>`
|
||||||
|
@@ -19,29 +19,6 @@ examples/storage/emmc:
|
|||||||
- if: IDF_TARGET == "esp32s3"
|
- if: IDF_TARGET == "esp32s3"
|
||||||
reason: only support on esp32s3
|
reason: only support on esp32s3
|
||||||
|
|
||||||
examples/storage/ext_flash_fatfs:
|
|
||||||
depends_components:
|
|
||||||
- fatfs
|
|
||||||
- vfs
|
|
||||||
- spi_flash
|
|
||||||
- driver
|
|
||||||
disable:
|
|
||||||
- if: IDF_TARGET in ["esp32p4", "esp32c5", "esp32c61"]
|
|
||||||
temporary: true
|
|
||||||
reason: not supported on p4 and c5 # TODO: [ESP32C5] IDF-8715, [ESP32C61] IDF-9314
|
|
||||||
disable_test:
|
|
||||||
- if: IDF_TARGET not in ["esp32"]
|
|
||||||
temporary: true
|
|
||||||
reason: lack of runners
|
|
||||||
|
|
||||||
examples/storage/fatfsgen:
|
|
||||||
depends_components:
|
|
||||||
- fatfs
|
|
||||||
- vfs
|
|
||||||
disable_test:
|
|
||||||
- if: IDF_TARGET != "esp32"
|
|
||||||
reason: only one target needed
|
|
||||||
|
|
||||||
examples/storage/nvs_rw_blob:
|
examples/storage/nvs_rw_blob:
|
||||||
depends_components:
|
depends_components:
|
||||||
- nvs_flash
|
- nvs_flash
|
||||||
|
@@ -7,10 +7,11 @@ 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:
|
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.
|
* `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.
|
* `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.
|
* `ext_flash_fatfs` example demonstrates how to use FATFS partition with external SPI FLASH chip.
|
||||||
* `fatfsgen` example demonstrates how to use FATFS partition
|
|
||||||
* `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_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` 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_rw_value_cxx` example demonstrates how to read and write a single integer value using NVS (it uses the C++ NVS handle API).
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
idf_component_register(SRCS "ext_flash_fatfs_example_main.c")
|
|
24
examples/storage/fatfs/.build-test-rules.yml
Normal file
24
examples/storage/fatfs/.build-test-rules.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||||
|
|
||||||
|
examples/storage/fatfs:
|
||||||
|
depends_components:
|
||||||
|
- fatfs
|
||||||
|
- vfs
|
||||||
|
disable_test:
|
||||||
|
- if: IDF_TARGET != "esp32"
|
||||||
|
reason: only one target needed
|
||||||
|
|
||||||
|
examples/storage/fatfs/ext_flash:
|
||||||
|
depends_components:
|
||||||
|
- fatfs
|
||||||
|
- vfs
|
||||||
|
- spi_flash
|
||||||
|
- driver
|
||||||
|
disable:
|
||||||
|
- if: IDF_TARGET in ["esp32p4", "esp32c5", "esp32c61"]
|
||||||
|
temporary: true
|
||||||
|
reason: not supported on p4 and c5 # TODO: [ESP32C5] IDF-8715, [ESP32C61] IDF-9314
|
||||||
|
disable_test:
|
||||||
|
- if: IDF_TARGET not in ["esp32"]
|
||||||
|
temporary: true
|
||||||
|
reason: lack of runners
|
@@ -4,4 +4,4 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
|
|
||||||
# external SPI flash driver not currently supported for ESP32-S2
|
# external SPI flash driver not currently supported for ESP32-S2
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
project(ext_flash_fatfs)
|
project(fatfs_ext_flash)
|
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
This example is similar to the [wear levelling](../wear_levelling/README.md) example, except that it uses an external SPI Flash chip. This can be useful if you need to add more storage to a module with only 4 MB flash size.
|
This example is similar to the [wear levelling](../../wear_levelling/README.md) example, except that it uses an external SPI Flash chip. This can be useful if you need to add more storage to a module with only 4 MB flash size.
|
||||||
|
|
||||||
The flow of the example is as follows:
|
The flow of the example is as follows:
|
||||||
|
|
1
examples/storage/fatfs/ext_flash/main/CMakeLists.txt
Normal file
1
examples/storage/fatfs/ext_flash/main/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
idf_component_register(SRCS "fatfs_ext_flash_example_main.c")
|
@@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
/* Example of FAT filesystem on external Flash.
|
/* Example of FAT filesystem on external Flash.
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
@@ -1,7 +1,5 @@
|
|||||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
|
|
6
examples/storage/fatfs/fatfsgen/CMakeLists.txt
Normal file
6
examples/storage/fatfs/fatfsgen/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
|
# in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(fatfs_fatfsgen)
|
69
examples/storage/fatfs/fatfsgen/README.md
Normal file
69
examples/storage/fatfs/fatfsgen/README.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
|
# FATFS partition generation example
|
||||||
|
|
||||||
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
|
This example demonstrates how to use the FATFS partition
|
||||||
|
generation tool [fatfsgen.py](../../../../components/fatfs/fatfsgen.py) to automatically create a FATFS
|
||||||
|
filesystem image from the contents of a host folder during build, with an option of
|
||||||
|
automatically flashing the created image on invocation of `idf.py -p PORT flash`.
|
||||||
|
Beware that the minimal required size of the flash is 4 MB.
|
||||||
|
You can specify using menuconfig weather example will use read-only or read-write mode. The default option is read-write mode.
|
||||||
|
To change it just use menuconfig:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
idf.py menuconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
Then select `Example Configuration` a chose `Mode for generated FATFS image` either `Read-Write Mode` or `Read-Only Mode`.
|
||||||
|
`Read-Only` option indicates generating raw fatfs image without wear levelling support.
|
||||||
|
On the other hand, for `Read-Write` the generated fatfs image will support wear levelling thus can be mounted in read-write mode.
|
||||||
|
|
||||||
|
|
||||||
|
The following gives an overview of the example:
|
||||||
|
|
||||||
|
1. There is a directory `fatfs_long_name_image` from which the FATFS filesystem image will be created.
|
||||||
|
|
||||||
|
2. Based on the RO/RW configuration either `fatfs_create_rawflash_image` or `fatfs_create_spiflash_image` respectively,
|
||||||
|
is used to specify that a FATFS image should be created during build for the `storage` partition.
|
||||||
|
For CMake, it is called from [the main component's CMakeLists.txt](./main/CMakeLists.txt).
|
||||||
|
`FLASH_IN_PROJECT` specifies that the created image
|
||||||
|
should be flashed on invocation of `idf.py -p PORT flash` together with app, bootloader, partition table, etc.
|
||||||
|
The image is created on the example's build directory with the output filename `storage.bin`.
|
||||||
|
|
||||||
|
3. Upon invocation of `idf.py -p PORT flash monitor`, application loads and
|
||||||
|
finds there is already a valid FATFS filesystem in the `storage` partition with files same as those in `fatfs_image` directory. The application is then
|
||||||
|
able to read those files.
|
||||||
|
|
||||||
|
## 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-]``.)
|
||||||
|
|
||||||
|
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 (322) example: Mounting FAT filesystem
|
||||||
|
I (332) example: Reading file
|
||||||
|
I (332) example: Read from file: 'this is test'
|
||||||
|
I (332) example: Unmounting FAT filesystem
|
||||||
|
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.
|
18
examples/storage/fatfs/fatfsgen/main/CMakeLists.txt
Normal file
18
examples/storage/fatfs/fatfsgen/main/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
idf_component_register(SRCS "fatfsgen_example_main.c"
|
||||||
|
INCLUDE_DIRS ".")
|
||||||
|
|
||||||
|
# Create a FATFS image from the contents of the 'fatfs_long_name_image' directory
|
||||||
|
# that fits the partition named 'storage'. FLASH_IN_PROJECT indicates that
|
||||||
|
# the generated image should be flashed when the entire project is flashed to
|
||||||
|
# the target with 'idf.py -p PORT flash'.
|
||||||
|
# If read-only mode is set (CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY)
|
||||||
|
# the generated image will be raw without wear levelling support.
|
||||||
|
# Otherwise it will support wear levelling and thus enable read-write mounting of the image in the device.
|
||||||
|
|
||||||
|
set(image ../fatfs_image)
|
||||||
|
|
||||||
|
if(CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY)
|
||||||
|
fatfs_create_rawflash_image(storage ${image} FLASH_IN_PROJECT PRESERVE_TIME)
|
||||||
|
else()
|
||||||
|
fatfs_create_spiflash_image(storage ${image} FLASH_IN_PROJECT PRESERVE_TIME)
|
||||||
|
endif()
|
10
examples/storage/fatfs/fatfsgen/main/Kconfig.projbuild
Normal file
10
examples/storage/fatfs/fatfsgen/main/Kconfig.projbuild
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
menu "Example Configuration"
|
||||||
|
|
||||||
|
config EXAMPLE_FATFS_MODE_READ_ONLY
|
||||||
|
bool "Read only mode for generated FATFS image"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
If read-only mode is set, the generated fatfs image will be raw (without wear levelling support).
|
||||||
|
Otherwise it will support wear levelling that enables read-write mounting.
|
||||||
|
|
||||||
|
endmenu
|
92
examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c
Normal file
92
examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_vfs.h"
|
||||||
|
#include "esp_vfs_fat.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
static const char *TAG = "example";
|
||||||
|
|
||||||
|
// Mount path for the partition
|
||||||
|
const char *base_path = "/spiflash";
|
||||||
|
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
// To mount device we need name of device partition, define base_path
|
||||||
|
// and allow format partition in case if it is new one and was not formatted before
|
||||||
|
const esp_vfs_fat_mount_config_t mount_config = {
|
||||||
|
.max_files = 4,
|
||||||
|
.format_if_mount_failed = false,
|
||||||
|
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE,
|
||||||
|
.use_one_fat = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY
|
||||||
|
ESP_LOGI(TAG, "Mounting FAT filesystem in read-only mode");
|
||||||
|
esp_err_t err = esp_vfs_fat_spiflash_mount_ro(base_path, "storage", &mount_config);
|
||||||
|
#else
|
||||||
|
ESP_LOGI(TAG, "Mounting FAT filesystem in read/write mode");
|
||||||
|
static wl_handle_t wl_handle = WL_INVALID_HANDLE;
|
||||||
|
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, "storage", &mount_config, &wl_handle);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[128];
|
||||||
|
|
||||||
|
FILE *f;
|
||||||
|
char *pos;
|
||||||
|
ESP_LOGI(TAG, "Reading file");
|
||||||
|
|
||||||
|
const char *host_filename1 = "/spiflash/subdir/testlongfilenames.txt";
|
||||||
|
|
||||||
|
struct stat info;
|
||||||
|
struct tm timeinfo;
|
||||||
|
char buffer[32];
|
||||||
|
|
||||||
|
if(stat(host_filename1, &info) < 0){
|
||||||
|
ESP_LOGE(TAG, "Failed to read file stats");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
localtime_r(&info.st_mtime, &timeinfo);
|
||||||
|
strftime(buffer, sizeof(buffer), "%Y-%m-%d", &timeinfo);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "The file '%s' was modified at date: %s", host_filename1, buffer);
|
||||||
|
|
||||||
|
|
||||||
|
f = fopen(host_filename1, "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open file for reading");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fgets(line, sizeof(line), f);
|
||||||
|
fclose(f);
|
||||||
|
// strip newline
|
||||||
|
pos = strchr(line, '\n');
|
||||||
|
if (pos) {
|
||||||
|
*pos = '\0';
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Read from file: '%s'", line);
|
||||||
|
|
||||||
|
// Unmount FATFS
|
||||||
|
ESP_LOGI(TAG, "Unmounting FAT filesystem");
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_ro(base_path, "storage"));
|
||||||
|
#else
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_rw_wl(base_path, wl_handle));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Done");
|
||||||
|
}
|
6
examples/storage/fatfs/fatfsgen/partitions_example.csv
Normal file
6
examples/storage/fatfs/fatfsgen/partitions_example.csv
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||||
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
|
factory, app, factory, 0x10000, 1M,
|
||||||
|
storage, data, fat, , 1M,
|
|
@@ -0,0 +1,72 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
idf_path = os.environ['IDF_PATH'] # get value of IDF_PATH from environment
|
||||||
|
parttool_dir = os.path.join(idf_path, 'components', 'partition_table')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.esp32
|
||||||
|
@pytest.mark.generic
|
||||||
|
@pytest.mark.parametrize('config', ['test_read_only_partition_gen_ln',
|
||||||
|
'test_read_write_partition_gen_ln',
|
||||||
|
], indirect=True)
|
||||||
|
def test_examples_fatfs_fatfsgen(config: str, dut: Dut) -> None:
|
||||||
|
# Expects list of strings sequentially
|
||||||
|
def expect_all(msg_list: List[str], to: int) -> None:
|
||||||
|
for msg in msg_list:
|
||||||
|
dut.expect(msg, timeout=to)
|
||||||
|
|
||||||
|
# Expects prefix string followed by date in the format 'yyyy-mm-dd'
|
||||||
|
def expect_date(prefix: str, to: int) -> datetime:
|
||||||
|
expect_str = prefix + '(\\d+)-(\\d+)-(\\d+)'
|
||||||
|
match_ = dut.expect(re.compile(str.encode(expect_str)), timeout=to)
|
||||||
|
year_ = int(match_[1].decode())
|
||||||
|
month_ = int(match_[2].decode())
|
||||||
|
day_ = int(match_[3].decode())
|
||||||
|
return datetime(year_, month_, day_)
|
||||||
|
|
||||||
|
# Calculates absolute difference in days between date_reference and date_actual.
|
||||||
|
# Raises exception if difference exceeds tolerance
|
||||||
|
def evaluate_dates(date_reference: datetime, date_actual: datetime, days_tolerance: int) -> None:
|
||||||
|
td = date_actual - date_reference
|
||||||
|
if abs(td.days) > days_tolerance:
|
||||||
|
raise Exception(f'Too big date difference. Actual: {date_actual}, reference: {date_reference}, tolerance: {days_tolerance} day(s)')
|
||||||
|
|
||||||
|
# Expect timeout
|
||||||
|
timeout = 20
|
||||||
|
|
||||||
|
# We tolerate 30 days difference between actual file creation and date when test was executed.
|
||||||
|
tolerance = 30
|
||||||
|
filename = 'sublongnames/testlongfilenames.txt'
|
||||||
|
date_ref = datetime.today()
|
||||||
|
|
||||||
|
if config in ['test_read_write_partition_gen']:
|
||||||
|
filename_expected = f'/spiflash/{filename}'
|
||||||
|
expect_all(['example: Mounting FAT filesystem',
|
||||||
|
'example: Opening file',
|
||||||
|
'example: File written',
|
||||||
|
'example: Reading file',
|
||||||
|
'example: Read from file: \'This is written by the device\'',
|
||||||
|
'example: Reading file'], timeout)
|
||||||
|
date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout)
|
||||||
|
evaluate_dates(date_ref, date_act, tolerance)
|
||||||
|
expect_all(['example: Read from file: \'This is generated on the host\'',
|
||||||
|
'example: Unmounting FAT filesystem',
|
||||||
|
'example: Done'], timeout)
|
||||||
|
|
||||||
|
elif config in ['test_read_only_partition_gen']:
|
||||||
|
filename_expected = f'/spiflash/{filename}'
|
||||||
|
expect_all(['example: Mounting FAT filesystem',
|
||||||
|
'example: Reading file'], timeout)
|
||||||
|
date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout)
|
||||||
|
evaluate_dates(date_ref, date_act, tolerance)
|
||||||
|
expect_all(['example: Read from file: \'this is test\'',
|
||||||
|
'example: Unmounting FAT filesystem',
|
||||||
|
'example: Done'], timeout)
|
@@ -0,0 +1,4 @@
|
|||||||
|
CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY=y
|
||||||
|
CONFIG_FATFS_LFN_HEAP=y
|
||||||
|
CONFIG_FATFS_LFN_NONE=n
|
||||||
|
CONFIG_FATFS_LFN_STACK=n
|
@@ -0,0 +1,4 @@
|
|||||||
|
CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY=n
|
||||||
|
CONFIG_FATFS_LFN_HEAP=y
|
||||||
|
CONFIG_FATFS_LFN_NONE=n
|
||||||
|
CONFIG_FATFS_LFN_STACK=n
|
4
examples/storage/fatfs/fatfsgen/sdkconfig.defaults
Normal file
4
examples/storage/fatfs/fatfsgen/sdkconfig.defaults
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||||
|
CONFIG_FATFS_LFN_HEAP=y
|
6
examples/storage/fatfs/fs_operations/CMakeLists.txt
Normal file
6
examples/storage/fatfs/fs_operations/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
|
# in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(fatfs_fs_operations)
|
94
examples/storage/fatfs/fs_operations/README.md
Normal file
94
examples/storage/fatfs/fs_operations/README.md
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
|
# FATFS Filesystem Operations Example
|
||||||
|
|
||||||
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
1. Partition labeled `storage` is mounted (and formatted if necessary) as FATFS filesystem to `/spiflash` mountpoint.
|
||||||
|
|
||||||
|
2. All existing files and directories in the root directory are deleted.
|
||||||
|
|
||||||
|
3. File `hello.txt` is created and written to.
|
||||||
|
|
||||||
|
4. File `hello.txt` is inspected using `fstat` function showing file size and last modification time.
|
||||||
|
|
||||||
|
5. File `hello.txt` is written to again, appending to the end of the file.
|
||||||
|
|
||||||
|
6. File `hello.txt` is read from and the contents are printed to the console.
|
||||||
|
|
||||||
|
7. New directory `new_dir` is created.
|
||||||
|
|
||||||
|
8. All files and directories in the root directory are listed.
|
||||||
|
|
||||||
|
9. File `hello.txt` is moved and renamed to `new_dir/hello_renamed.txt`.
|
||||||
|
|
||||||
|
## 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-]``.)
|
||||||
|
|
||||||
|
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 (323) example: Mounting FAT filesystem
|
||||||
|
I (333) example: Deleting everything in /spiflash:
|
||||||
|
I (333) example: Deleting everything in /spiflash/new_dir:
|
||||||
|
I (673) example: Creating a file
|
||||||
|
I (683) example: Writing to the file
|
||||||
|
I (733) example: File stats:
|
||||||
|
File size: 13 bytes
|
||||||
|
File modification time: Thu Jan 1 00:00:00 1970
|
||||||
|
|
||||||
|
I (743) example: Wait for 1 seconds
|
||||||
|
I (1743) example: Write more to the file
|
||||||
|
I (1743) example: File stats:
|
||||||
|
File size: 26 bytes
|
||||||
|
File modification time: Thu Jan 1 00:00:00 1970
|
||||||
|
|
||||||
|
I (1743) example: Go to the beginning of the file
|
||||||
|
I (1753) example: Reading from file:
|
||||||
|
Hello World!
|
||||||
|
Hello World!
|
||||||
|
|
||||||
|
I (1753) example: Closing file
|
||||||
|
I (1993) example: Listing files in /spiflash:
|
||||||
|
/spiflash:
|
||||||
|
file : hello.txt
|
||||||
|
I (1993) example: Creating a new directory
|
||||||
|
I (2383) example: Listing files in /spiflash:
|
||||||
|
/spiflash:
|
||||||
|
file : hello.txt
|
||||||
|
directory: new_dir
|
||||||
|
I (2383) example: Rename a file
|
||||||
|
I (2503) example: Listing files in /spiflash:
|
||||||
|
/spiflash:
|
||||||
|
directory: new_dir
|
||||||
|
I (2503) example: Listing files in /spiflash/new_dir:
|
||||||
|
/spiflash/new_dir:
|
||||||
|
file : hello_renamed.txt
|
||||||
|
I (2513) example: Unmounting FAT filesystem
|
||||||
|
I (2643) example: Done
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
The logic of the example is contained in a [single source file](./main/fatfs_fs_operations_example_main.c),
|
||||||
|
and it should be relatively simple to match points in its execution with the log outputs above.
|
2
examples/storage/fatfs/fs_operations/main/CMakeLists.txt
Normal file
2
examples/storage/fatfs/fs_operations/main/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS "fatfs_fs_operations_example_main.c"
|
||||||
|
INCLUDE_DIRS ".")
|
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include "esp_vfs.h"
|
||||||
|
#include "esp_vfs_fat.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
static const char *TAG = "example";
|
||||||
|
|
||||||
|
// Mount path for the partition
|
||||||
|
static const char *base_path = "/spiflash";
|
||||||
|
|
||||||
|
// File name
|
||||||
|
static const char *filename = "/spiflash/hello.txt";
|
||||||
|
|
||||||
|
// Function to dump contents of a directory
|
||||||
|
static void list_dir(const char *path);
|
||||||
|
|
||||||
|
// Best effort recursive function to clean a directory
|
||||||
|
static void clean_dir(const char *path);
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Mounting FAT filesystem");
|
||||||
|
|
||||||
|
// To mount device we need name of device partition, define base_path
|
||||||
|
// and allow format partition in case if it is new one and was not formatted before
|
||||||
|
const esp_vfs_fat_mount_config_t mount_config = {
|
||||||
|
.max_files = 4,
|
||||||
|
.format_if_mount_failed = true,
|
||||||
|
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE,
|
||||||
|
.use_one_fat = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
wl_handle_t wl_handle = WL_INVALID_HANDLE;
|
||||||
|
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, "storage", &mount_config, &wl_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the working directory is empty
|
||||||
|
clean_dir(base_path);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Creating a file");
|
||||||
|
|
||||||
|
// Unlike C standard library which uses FILE*, POSIX API uses file descriptors for file operations
|
||||||
|
int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open file for writing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Writing to the file");
|
||||||
|
const char *text = "Hello World!\n";
|
||||||
|
write(fd, text, strlen(text));
|
||||||
|
|
||||||
|
struct stat info;
|
||||||
|
// We have to use `stat` instead of `fstat`, because `fstat` currently isn't fully supported
|
||||||
|
if (stat(filename, &info) < 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to stat file: %s", strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(
|
||||||
|
TAG,
|
||||||
|
"File stats:\n"
|
||||||
|
"\tFile size: %ld bytes\n"
|
||||||
|
"\tFile modification time: %s",
|
||||||
|
info.st_size,
|
||||||
|
ctime(&info.st_mtime)
|
||||||
|
);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Wait for 3 seconds");
|
||||||
|
sleep(3);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Write more to the file");
|
||||||
|
write(fd, text, strlen(text));
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Force cached data and metadata to the filesystem");
|
||||||
|
fsync(fd);
|
||||||
|
|
||||||
|
if (stat(filename, &info) < 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to stat file: %s", strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(
|
||||||
|
TAG,
|
||||||
|
"File stats:\n"
|
||||||
|
"\tFile size: %ld bytes\n"
|
||||||
|
"\tFile modification time: %s",
|
||||||
|
info.st_size,
|
||||||
|
ctime(&info.st_mtime)
|
||||||
|
);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Go to the beginning of the file");
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Reading from file:");
|
||||||
|
|
||||||
|
char buf[128] = {0};
|
||||||
|
|
||||||
|
ssize_t len = read(fd, buf, sizeof(buf) - 1);
|
||||||
|
if (len < 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to read file: %s", strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%.*s\n", len, buf);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Closing file");
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
// List files in the directory
|
||||||
|
list_dir(base_path);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Creating a new directory");
|
||||||
|
if (mkdir("/spiflash/new_dir", 0777) < 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to create a new directory: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List files in the directory
|
||||||
|
list_dir(base_path);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Rename a file");
|
||||||
|
|
||||||
|
if (rename(filename, "/spiflash/new_dir/hello_renamed.txt") < 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to rename file: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List files in the directory
|
||||||
|
list_dir(base_path);
|
||||||
|
list_dir("/spiflash/new_dir");
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Unmounting FAT filesystem");
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_rw_wl(base_path, wl_handle));
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Done");
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_dir(const char *path)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Listing files in %s:", path);
|
||||||
|
|
||||||
|
DIR *dir = opendir(path);
|
||||||
|
if (!dir) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open directory: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s:\n", path);
|
||||||
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
printf(
|
||||||
|
" %s: %s\n",
|
||||||
|
(entry->d_type == DT_DIR)
|
||||||
|
? "directory"
|
||||||
|
: "file ",
|
||||||
|
entry->d_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clean_dir(const char *path)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Deleting everything in %s:", path);
|
||||||
|
|
||||||
|
DIR *dir = opendir(path);
|
||||||
|
if (!dir) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open directory: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
char full_path[64] = {0};
|
||||||
|
snprintf(full_path, sizeof(full_path), "%.20s/%.40s", path, entry->d_name);
|
||||||
|
if (entry->d_type == DT_DIR)
|
||||||
|
clean_dir(full_path);
|
||||||
|
if (remove(full_path) != 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to remove %s: %s", full_path, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.esp32
|
||||||
|
@pytest.mark.generic
|
||||||
|
def test_examples_fatfs_fs_operations(config: str, dut: Dut) -> None:
|
||||||
|
# Expects list of strings sequentially
|
||||||
|
def expect_all(msg_list: List[str], to: int) -> None:
|
||||||
|
for msg in msg_list:
|
||||||
|
dut.expect(msg, timeout=to)
|
||||||
|
|
||||||
|
def parse_date() -> datetime:
|
||||||
|
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||||
|
|
||||||
|
pattern = r'([A-Z][a-z]{2}) ([A-Z][a-z]{2}) ([ \d]\d) (\d{2}):(\d{2}):(\d{2}) (\d{4})'
|
||||||
|
|
||||||
|
match = dut.expect(pattern)
|
||||||
|
return datetime(
|
||||||
|
month=months.index(match[2].decode('utf-8')) + 1,
|
||||||
|
day=int(match[3]),
|
||||||
|
hour=int(match[4]),
|
||||||
|
minute=int(match[5]),
|
||||||
|
second=int(match[6]),
|
||||||
|
year=int(match[7]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect_all(
|
||||||
|
[
|
||||||
|
'example: Mounting FAT filesystem',
|
||||||
|
'example: Creating a file',
|
||||||
|
'example: Writing to the file',
|
||||||
|
'example: File stats:',
|
||||||
|
'File size:',
|
||||||
|
],
|
||||||
|
5
|
||||||
|
)
|
||||||
|
|
||||||
|
original = parse_date()
|
||||||
|
|
||||||
|
expect_all(
|
||||||
|
[
|
||||||
|
'example: Wait for 3 seconds',
|
||||||
|
'example: Write more to the file',
|
||||||
|
'example: Force cached data and metadata to the filesystem',
|
||||||
|
'File size:',
|
||||||
|
],
|
||||||
|
5
|
||||||
|
)
|
||||||
|
|
||||||
|
updated = parse_date()
|
||||||
|
|
||||||
|
assert updated > original
|
||||||
|
|
||||||
|
expect_all(
|
||||||
|
[
|
||||||
|
'example: Go to the beginning of the file',
|
||||||
|
'example: Reading from file',
|
||||||
|
'Hello World!',
|
||||||
|
'Hello World!',
|
||||||
|
'example: Closing file',
|
||||||
|
'example: Listing files in /spiflash:',
|
||||||
|
'hello.txt',
|
||||||
|
'example: Creating a new directory',
|
||||||
|
'example: Listing files in /spiflash:',
|
||||||
|
'hello.txt',
|
||||||
|
'new_dir',
|
||||||
|
'example: Rename a file',
|
||||||
|
'example: Listing files in /spiflash:',
|
||||||
|
'new_dir',
|
||||||
|
'example: Listing files in /spiflash/new_dir:',
|
||||||
|
'hello_renamed.txt',
|
||||||
|
],
|
||||||
|
5
|
||||||
|
)
|
7
examples/storage/fatfs/fs_operations/sdkconfig.defaults
Normal file
7
examples/storage/fatfs/fs_operations/sdkconfig.defaults
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||||
|
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
|
||||||
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||||
|
CONFIG_FATFS_LFN_HEAP=y
|
||||||
|
CONFIG_FATFS_LFN_NONE=n
|
||||||
|
CONFIG_FATFS_LFN_STACK=n
|
6
examples/storage/fatfs/getting_started/CMakeLists.txt
Normal file
6
examples/storage/fatfs/getting_started/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
|
# in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(fatfs_getting_started)
|
44
examples/storage/fatfs/getting_started/README.md
Normal file
44
examples/storage/fatfs/getting_started/README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
|
# FATFS 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.
|
||||||
|
|
||||||
|
## 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-]``.)
|
||||||
|
|
||||||
|
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
|
||||||
|
I (331) example: Filesystem mounted
|
||||||
|
I (331) example: Opening file
|
||||||
|
I (731) example: File written
|
||||||
|
I (731) example: Reading file
|
||||||
|
I (741) example: Read from file: 'Hello World!'
|
||||||
|
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.
|
@@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS "fatfs_getting_started_main.c"
|
||||||
|
INCLUDE_DIRS ".")
|
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_vfs.h"
|
||||||
|
#include "esp_vfs_fat.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
static const char *TAG = "example";
|
||||||
|
|
||||||
|
// Mount path for the partition
|
||||||
|
const char *base_path = "/spiflash";
|
||||||
|
|
||||||
|
// Handle of the wear levelling library instance
|
||||||
|
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Mounting FAT filesystem");
|
||||||
|
// To mount device we need name of device partition, define base_path
|
||||||
|
// and allow format partition in case if it is new one and was not formatted before
|
||||||
|
const esp_vfs_fat_mount_config_t mount_config = {
|
||||||
|
.max_files = 4, // Number of files that can be open at a time
|
||||||
|
.format_if_mount_failed = true, // If true, try to format the partition if mount fails
|
||||||
|
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE, // Size of allocation unit, cluster size.
|
||||||
|
.use_one_fat = false, // Use only one FAT table (reduce memory usage), but decrease reliability of file system in case of power failure.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mount FATFS filesystem located on "storage" partition in read-write mode
|
||||||
|
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, "storage", &mount_config, &s_wl_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Filesystem mounted");
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Opening file");
|
||||||
|
|
||||||
|
const char *filename = "/spiflash/example.txt";
|
||||||
|
|
||||||
|
FILE *f = fopen(filename, "wb");
|
||||||
|
if (f == NULL) {
|
||||||
|
perror("fopen"); // Print reason why fopen failed
|
||||||
|
ESP_LOGE(TAG, "Failed to open file for writing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(f, "Hello World!\n");
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "File written");
|
||||||
|
|
||||||
|
// Open file for reading
|
||||||
|
ESP_LOGI(TAG, "Reading file");
|
||||||
|
|
||||||
|
f = fopen(filename, "r");
|
||||||
|
if (f == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open file for reading");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[128];
|
||||||
|
|
||||||
|
fgets(line, sizeof(line), f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
// strip newline
|
||||||
|
char *pos = strchr(line, '\n');
|
||||||
|
if (pos) {
|
||||||
|
*pos = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Read from file: '%s'", line);
|
||||||
|
|
||||||
|
// Unmount FATFS
|
||||||
|
ESP_LOGI(TAG, "Unmounting FAT filesystem");
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_rw_wl(base_path, s_wl_handle));
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Done");
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||||
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
|
factory, app, factory, 0x10000, 1M,
|
||||||
|
storage, data, fat, , 1M,
|
|
@@ -0,0 +1,17 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.esp32
|
||||||
|
@pytest.mark.generic
|
||||||
|
def test_examples_fatfs_getting_started(dut: Dut) -> None:
|
||||||
|
dut.expect('example: Mounting FAT filesystem', timeout=90)
|
||||||
|
dut.expect('example: Filesystem mounted', timeout=90)
|
||||||
|
dut.expect('example: Opening file', timeout=90)
|
||||||
|
dut.expect('example: File written', timeout=90)
|
||||||
|
dut.expect('example: Reading file', timeout=90)
|
||||||
|
dut.expect('example: Read from file: \'Hello World!\'', timeout=90)
|
||||||
|
dut.expect('example: Unmounting FAT filesystem', timeout=90)
|
||||||
|
dut.expect('example: Done', timeout=90)
|
@@ -941,7 +941,6 @@ examples/security/flash_encryption/main/flash_encrypt_main.c
|
|||||||
examples/storage/custom_flash_driver/components/custom_chip_driver/chip_drivers.c
|
examples/storage/custom_flash_driver/components/custom_chip_driver/chip_drivers.c
|
||||||
examples/storage/custom_flash_driver/components/custom_chip_driver/spi_flash_chip_eon.c
|
examples/storage/custom_flash_driver/components/custom_chip_driver/spi_flash_chip_eon.c
|
||||||
examples/storage/custom_flash_driver/main/main.c
|
examples/storage/custom_flash_driver/main/main.c
|
||||||
examples/storage/ext_flash_fatfs/main/ext_flash_fatfs_example_main.c
|
|
||||||
examples/storage/nvs_rw_blob/main/nvs_blob_example_main.c
|
examples/storage/nvs_rw_blob/main/nvs_blob_example_main.c
|
||||||
examples/storage/nvs_rw_value/main/nvs_value_example_main.c
|
examples/storage/nvs_rw_value/main/nvs_value_example_main.c
|
||||||
examples/storage/nvs_rw_value_cxx/main/nvs_value_example_main.cpp
|
examples/storage/nvs_rw_value_cxx/main/nvs_value_example_main.cpp
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||||
|
|
||||||
|
tools/test_apps/storage/fatfsgen:
|
||||||
|
depends_components:
|
||||||
|
- fatfs
|
||||||
|
- vfs
|
||||||
|
disable_test:
|
||||||
|
- if: IDF_TARGET != "esp32"
|
||||||
|
reason: only one target needed
|
||||||
|
|
||||||
tools/test_apps/storage/partition_table_readonly:
|
tools/test_apps/storage/partition_table_readonly:
|
||||||
disable_test:
|
disable_test:
|
||||||
- if: IDF_TARGET not in ["esp32", "esp32c3"]
|
- if: IDF_TARGET not in ["esp32", "esp32c3"]
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
This is generated on the host; long name it has
|
@@ -0,0 +1 @@
|
|||||||
|
this is test; long name it has
|
6
tools/test_apps/storage/fatfsgen/partitions_example.csv
Normal file
6
tools/test_apps/storage/fatfsgen/partitions_example.csv
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||||
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
|
factory, app, factory, 0x10000, 1M,
|
||||||
|
storage, data, fat, , 1M,
|
|
4
tools/test_apps/storage/fatfsgen/sdkconfig.defaults
Normal file
4
tools/test_apps/storage/fatfsgen/sdkconfig.defaults
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||||
|
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
|
||||||
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
Reference in New Issue
Block a user