mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-05 12:25:03 +02:00
Doc/review api ref storage
This commit is contained in:
committed by
Krzysztof Budzynski
parent
e20b37aff9
commit
4faf2de035
@@ -1,36 +1,43 @@
|
||||
FAT Filesystem Support
|
||||
======================
|
||||
|
||||
ESP-IDF uses `FatFs <http://elm-chan.org/fsw/ff/00index_e.html>`_ library to work with FAT filesystems. FatFs library resides in ``fatfs`` component. Although it can be used directly, many of its features can be accessed via VFS using C standard library and POSIX APIs.
|
||||
ESP-IDF uses the `FatFs <http://elm-chan.org/fsw/ff/00index_e.html>`_ library to work with FAT filesystems. FatFs resides in the ``fatfs`` component. Although the library can be used directly, many of its features can be accessed via VFS, using the C standard library and POSIX API functions.
|
||||
|
||||
Additionally, FatFs has been modified to support the runtime pluggable disk I/O layer. This allows mapping of FatFs drives to physical disks at runtime.
|
||||
|
||||
Additionally, FatFs has been modified to support run-time pluggable disk IO layer. This allows mapping of FatFs drives to physical disks at run-time.
|
||||
|
||||
Using FatFs with VFS
|
||||
--------------------
|
||||
|
||||
:component_file:`fatfs/src/esp_vfs_fat.h` header file defines functions to connect FatFs with VFS. :cpp:func:`esp_vfs_fat_register` function 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. :cpp:func:`esp_vfs_fat_unregister_path` function deletes the registration with VFS, and frees the ``FATFS`` structure.
|
||||
The header file :component_file:`fatfs/src/esp_vfs_fat.h` defines the functions for connecting FatFs and VFS.
|
||||
|
||||
Most applications will use the following flow when working with ``esp_vfs_fat_`` functions:
|
||||
The function :cpp:func:`esp_vfs_fat_register` allocates a ``FATFS`` structure and registers a given path prefix in VFS. Subsequent operations on files starting with this prefix are forwarded to FatFs APIs.
|
||||
The function :cpp:func:`esp_vfs_fat_unregister_path` deletes the registration with VFS, and frees the ``FATFS`` structure.
|
||||
|
||||
1. Call :cpp:func:`esp_vfs_fat_register`, specifying path prefix where the filesystem has to be mounted (e.g. ``"/sdcard"``, ``"/spiflash"``), FatFs drive number, and a variable which will receive a pointer to ``FATFS`` structure.
|
||||
Most applications use the following workflow when working with ``esp_vfs_fat_`` functions:
|
||||
|
||||
2. Call :cpp:func:`ff_diskio_register` function to register disk IO driver for the drive number used in step 1.
|
||||
1. Call :cpp:func:`esp_vfs_fat_register` to specify:
|
||||
- Path prefix where to mount the filesystem (e.g. ``"/sdcard"``, ``"/spiflash"``)
|
||||
- FatFs drive number
|
||||
- A variable which will receive the pointer to the ``FATFS`` structure
|
||||
|
||||
3. Call FatFs ``f_mount`` function (and optionally ``f_fdisk``, ``f_mkfs``) to mount the filesystem using the same drive number which was passed to :cpp:func:`esp_vfs_fat_register`. See `FatFs documentation for more details <http://www.elm-chan.org/fsw/ff/doc/mount.html>`.
|
||||
2. Call :cpp:func:`ff_diskio_register` to register the disk I/O driver for the drive number used in Step 1.
|
||||
|
||||
4. Call POSIX and C standard library functions to open, read, write, erase, copy files, etc. Use paths starting with the prefix passed to :cpp:func:`esp_vfs_register` (such as ``"/sdcard/hello.txt"``).
|
||||
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 :cpp:func:`esp_vfs_fat_register`. For more information, see `FatFs documentation <http://www.elm-chan.org/fsw/ff/doc/mount.html>`.
|
||||
|
||||
5. Optionally, call FatFs library functions directly. Use paths without a VFS prefix in this case (``"/hello.txt"``).
|
||||
4. Call the C standard library and POSIX API functions to perform such actions on files as open, read, write, erase, copy, etc. Use paths starting with the path prefix passed to :cpp:func:`esp_vfs_register` (for example, ``"/sdcard/hello.txt"``).
|
||||
|
||||
5. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix (for example, ``"/hello.txt"``).
|
||||
|
||||
6. Close all open files.
|
||||
|
||||
7. Call FatFs ``f_mount`` function for the same drive number, with NULL ``FATFS*`` argument, to unmount the filesystem.
|
||||
7. Call the FatFs function ``f_mount`` for the same drive number, with NULL ``FATFS*`` argument, to unmount the filesystem.
|
||||
|
||||
8. Call FatFs :cpp:func:`ff_diskio_register` with NULL ``ff_diskio_impl_t*`` argument and the same drive number.
|
||||
8. Call the FatFs function :cpp:func:`ff_diskio_register` with NULL ``ff_diskio_impl_t*`` argument and the same drive number to unregister the disk I/O driver.
|
||||
|
||||
9. Call :cpp:func:`esp_vfs_fat_unregister_path` with the path where the file system is mounted to remove FatFs from VFS, and free the ``FATFS`` structure allocated on step 1.
|
||||
9. Call :cpp:func:`esp_vfs_fat_unregister_path` with the path where the file system is mounted to remove FatFs from VFS, and free the ``FATFS`` structure allocated in Step 1.
|
||||
|
||||
Convenience functions, ``esp_vfs_fat_sdmmc_mount`` and ``esp_vfs_fat_sdmmc_unmount``, which wrap these steps and also handle SD card initialization, are described in the next section.
|
||||
The convenience functions ``esp_vfs_fat_sdmmc_mount`` and ``esp_vfs_fat_sdmmc_unmount`` wrap the steps described above and also handle SD card initialization. These two functions are described in the next section.
|
||||
|
||||
.. doxygenfunction:: esp_vfs_fat_register
|
||||
.. doxygenfunction:: esp_vfs_fat_unregister_path
|
||||
@@ -39,7 +46,9 @@ Convenience functions, ``esp_vfs_fat_sdmmc_mount`` and ``esp_vfs_fat_sdmmc_unmou
|
||||
Using FatFs with VFS and SD cards
|
||||
---------------------------------
|
||||
|
||||
:component_file:`fatfs/src/esp_vfs_fat.h` header file also provides a convenience function to perform steps 1–3 and 7–9, and also handle SD card initialization: :cpp:func:`esp_vfs_fat_sdmmc_mount`. This function does only limited error handling. Developers are encouraged to look at its source code and incorporate more advanced versions into production applications. :cpp:func:`esp_vfs_fat_sdmmc_unmount` function unmounts the filesystem and releases resources acquired by :cpp:func:`esp_vfs_fat_sdmmc_mount`.
|
||||
The header file :component_file:`fatfs/src/esp_vfs_fat.h` defines convenience functions :cpp:func:`esp_vfs_fat_sdmmc_mount` and :cpp:func:`esp_vfs_fat_sdmmc_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 :cpp:func:`esp_vfs_fat_sdmmc_unmount` unmounts the filesystem and releases the resources acquired by :cpp:func:`esp_vfs_fat_sdmmc_mount`.
|
||||
|
||||
.. doxygenfunction:: esp_vfs_fat_sdmmc_mount
|
||||
.. doxygenstruct:: esp_vfs_fat_mount_config_t
|
||||
@@ -50,17 +59,18 @@ Using FatFs with VFS and SD cards
|
||||
Using FatFs with VFS in read-only mode
|
||||
--------------------------------------
|
||||
|
||||
Convenience functions, :cpp:func:`esp_vfs_fat_rawflash_mount` and :cpp:func:`esp_vfs_fat_rawflash_unmount`, are provided by :component_file:`fatfs/src/esp_vfs_fat.h` header file in order to perform steps 1-3 and 7-9 for read-only FAT partitions. These are particularly helpful for data partitions written only once during factory provisioning and need not be changed by production application throughout the lifetime.
|
||||
The header file :component_file:`fatfs/src/esp_vfs_fat.h` also defines the convenience functions :cpp:func:`esp_vfs_fat_rawflash_mount` and :cpp:func:`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.
|
||||
|
||||
.. doxygenfunction:: esp_vfs_fat_rawflash_mount
|
||||
.. doxygenfunction:: esp_vfs_fat_rawflash_unmount
|
||||
|
||||
|
||||
FatFS disk IO layer
|
||||
-------------------
|
||||
|
||||
FatFs has been extended with an API to register disk IO driver at runtime.
|
||||
FatFs has been extended with API functions that register the disk I/O driver at runtime.
|
||||
|
||||
Implementation of disk IO functions for SD/MMC cards is provided. It can be registered for the given FatFs drive number using :cpp:func:`ff_diskio_register_sdmmc` function.
|
||||
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 :cpp:func:`ff_diskio_register_sdmmc`.
|
||||
|
||||
.. doxygenfunction:: ff_diskio_register
|
||||
.. doxygenstruct:: ff_diskio_impl_t
|
||||
|
||||
@@ -15,4 +15,4 @@ Storage API
|
||||
Mass Manufacturing Utility <mass_mfg.rst>
|
||||
|
||||
|
||||
Example code for this API section is provided in :example:`storage` directory of ESP-IDF examples.
|
||||
Code examples for this API section are provided in the :example:`storage` directory of ESP-IDF examples.
|
||||
|
||||
@@ -3,29 +3,29 @@
|
||||
NVS Partition Generator Utility
|
||||
-------------------------------
|
||||
|
||||
This utility helps in generating NVS-esque partition binary file which can be flashed separately on a dedicated partition via a flashing utility. Key-value pairs to be flashed onto the partition can be provided via a CSV file. Refer to :doc:`NVS Partition Generator Utility <nvs_partition_gen>` for more details.
|
||||
This utility helps generate NVS partition binary files which can be flashed separately on a dedicated partition via a flashing utility. Key-value pairs to be flashed onto the partition can be provided via a CSV file. For more details, please refer to :doc:`NVS Partition Generator Utility <nvs_partition_gen>`.
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
Two examples are provided in :example:`storage` directory of ESP-IDF examples:
|
||||
You can find two code examples in the :example:`storage` directory of ESP-IDF examples:
|
||||
|
||||
:example:`storage/nvs_rw_value`
|
||||
|
||||
Demonstrates how to read and write a single integer value using NVS.
|
||||
Demonstrates how to read a single integer value from, and write it to NVS.
|
||||
|
||||
The value holds the number of ESP32 module restarts. Since it is written to NVS, the value is preserved between restarts.
|
||||
The value checked in this example holds the number of the ESP32 module restarts. The value's function as a counter is only possible due to its storing in NVS.
|
||||
|
||||
Example also shows how to check if read / write operation was successful, or certain value is not initialized in NVS. Diagnostic is provided in plain text to help track program flow and capture any issues on the way.
|
||||
The example also shows how to check if a read / write operation was successful, or if a certain value has not been initialized in NVS. The diagnostic procedure is provided in plain text to help you track the program flow and capture any issues on the way.
|
||||
|
||||
:example:`storage/nvs_rw_blob`
|
||||
|
||||
Demonstrates how to read and write a single integer value and a blob (binary large object) using NVS to preserve them between ESP32 module restarts.
|
||||
Demonstrates how to read a single integer value and a blob (binary large object), and write them to NVS to preserve this value between ESP32 module restarts.
|
||||
|
||||
* value - tracks number of ESP32 module soft and hard restarts.
|
||||
* blob - contains a table with module run times. The table is read from NVS to dynamically allocated RAM. New run time is added to the table on each manually triggered soft restart and written back to NVS. Triggering is done by pulling down GPIO0.
|
||||
* value - tracks the number of the ESP32 module soft and hard restarts.
|
||||
* blob - contains a table with module run times. The table is read from NVS to dynamically allocated RAM. A new run time is added to the table on each manually triggered soft restart, and then the added run time is written to NVS. Triggering is done by pulling down GPIO0.
|
||||
|
||||
Example also shows how to implement diagnostics if read / write operation was successful.
|
||||
The example also shows how to implement the diagnostic procedure to check if the read / write operation was successful.
|
||||
|
||||
|
||||
API Reference
|
||||
|
||||
@@ -4,77 +4,93 @@ SD/SDIO/MMC Driver
|
||||
Overview
|
||||
--------
|
||||
|
||||
SD/SDIO/MMC driver currently supports SD memory, SDIO cards, and eMMC chips. This protocol level driver builds on top of SDMMC and SD SPI host drivers.
|
||||
The SD/SDIO/MMC driver currently supports SD memory, SDIO cards, and eMMC chips. This is a protocol level driver built on top of SDMMC and SD SPI host drivers.
|
||||
|
||||
SDMMC and SD SPI host drivers (``driver/sdmmc_host.h``) provide APIs to send commands to the slave device(s), send and receive data, and handle error conditions on the bus.
|
||||
|
||||
- See :doc:`SDMMC Host API <../peripherals/sdmmc_host>` for functions used to initialize and configure SDMMC host.
|
||||
- See :doc:`SD SPI Host API <../peripherals/sdspi_host>` for functions used to initialize and configure SD SPI host.
|
||||
SDMMC and SD SPI host drivers (:component:`driver/include/driver/sdmmc_host.h`) provide API functions for:
|
||||
|
||||
SDMMC protocol layer (``sdmmc_cmd.h``), described in this document, handles specifics of SD protocol such as card initialization and data transfer commands.
|
||||
- Sending commands to slave devices
|
||||
- Sending and receiving data
|
||||
- Handling error conditions within the bus
|
||||
|
||||
For functions used to initialize and configure:
|
||||
|
||||
- SDMMC host, see :doc:`SDMMC Host API <../peripherals/sdmmc_host>`
|
||||
- SD SPI host, see :doc:`SD SPI Host API <../peripherals/sdspi_host>`
|
||||
|
||||
|
||||
The SDMMC protocol layer described in this document handles the specifics of the SD protocol, such as the card initialization and data transfer commands.
|
||||
|
||||
The protocol layer works with the host via the :cpp:class:`sdmmc_host_t` structure. This structure contains pointers to various functions of the host.
|
||||
|
||||
Protocol layer works with the host via :cpp:class:`sdmmc_host_t` structure. This structure contains pointers to various functions of the host.
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
An example which combines SDMMC driver with FATFS library is provided in ``examples/storage/sd_card`` directory. This example initializes the card, writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information.
|
||||
An example which combines the SDMMC driver with the FATFS library is provided in the :example:`storage/sd_card` directory of ESP-IDF examples. This example initializes the card, then writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information.
|
||||
|
||||
|
||||
Protocol layer APIs
|
||||
-------------------
|
||||
|
||||
Protocol layer is given :cpp:class:`sdmmc_host_t` structure which describes the SD/MMC host driver, lists its capabilites, and provides pointers to functions of the driver. Protocol layer stores card-specific information in :cpp:class:`sdmmc_card_t` structure. When sending commands to the SD/MMC host driver, protocol layer uses :cpp:class:`sdmmc_command_t` structure to describe the command, argument, expected return value, and data to transfer, if any.
|
||||
Protocol layer API
|
||||
------------------
|
||||
|
||||
Usage with SD memory cards
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Call the host driver functions to initialize the host (e.g. :cpp:func:`sdmmc_host_init`, :cpp:func:`sdmmc_host_init_slot`).
|
||||
2. Call :cpp:func:`sdmmc_card_init` to initialize the card, passing it host driver information (``host``) and a pointer to :cpp:class:`sdmmc_card_t` structure which will be filled in (``card``).
|
||||
3. To read and write sectors of the card, use :cpp:func:`sdmmc_read_sectors` and :cpp:func:`sdmmc_write_sectors`, passing the pointer to card information structure (``card``).
|
||||
4. When card is not used anymore, call the host driver function to disable the host peripheral and free resources allocated by the driver (e.g. :cpp:func:`sdmmc_host_deinit`).
|
||||
|
||||
Usage with eMMC chips
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
From the perspective of the protocol layer, eMMC memory chips behave the same way as SD memory cards. Because of similarity of the protocol, even though eMMC are chips don't have the "card" form factor, same terminology is used as for SD cards (`sdmmc_card_t`, `sdmmc_card_init`). Note that eMMC chips can not be used over SPI, therefore are incompatible with SD SPI host driver.
|
||||
|
||||
To initialize eMMC memory and do read/write operations, follow the steps listed above for SD cards.
|
||||
The protocol layer is given the :cpp:class:`sdmmc_host_t` structure. This structure describes the SD/MMC host driver, lists its capabilities, and provides pointers to functions of the driver. The protocol layer stores card-specific information in the :cpp:class:`sdmmc_card_t` structure. When sending commands to the SD/MMC host driver, the protocol layer uses the :cpp:class:`sdmmc_command_t` structure to describe the command, arguments, expected return values, and data to transfer if there is any.
|
||||
|
||||
|
||||
Usage with SDIO cards
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Using API with SD memory cards
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Initialization an probing process is the same as with SD memory cards. Only data transfer commands differ in SDIO mode.
|
||||
1. To initialize the host, call the host driver functions, e.g., :cpp:func:`sdmmc_host_init`, :cpp:func:`sdmmc_host_init_slot`.
|
||||
2. To initialize the card, call :cpp:func:`sdmmc_card_init` and pass to it the parameters ``host`` - the host driver information, and ``card`` - a pointer to the structure :cpp:class:`sdmmc_card_t` which will be filled with information about the card when the function completes.
|
||||
3. To read and write sectors of the card, use :cpp:func:`sdmmc_read_sectors` and :cpp:func:`sdmmc_write_sectors` respectively and pass to it the parameter ``card`` - a pointer to the card information structure.
|
||||
4. If the card is not used anymore, call the host driver function - e.g., :cpp:func:`sdmmc_host_deinit` - to disable the host peripheral and free the resources allocated by the driver.
|
||||
|
||||
During probing and card initialization (done by :cpp:func:`sdmmc_card_init`), the driver only configures the following registers of the IO card:
|
||||
|
||||
1. The IO portion of the card is reset by setting RES bit in "I/O Abort" (0x06) register.
|
||||
2. If 4-line mode is enalbed in host and slot configuration, driver attempts to set "Bus width" field in "Bus Interface Control" (0x07) register. If that succeeds (which means that slave supports 4-line mode), host is also switched to 4-line mode.
|
||||
3. If high-speed mode is enabled in host configuration, SHS bit is set in "High Speed" (0x13) register.
|
||||
Using API with eMMC chips
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In particular, the driver does not set any of the bits in I/O Enable, Int Enable registers, IO block sizes, etc. Applications can set these by calling :cpp:func:`sdmmc_io_write_byte`.
|
||||
From the protocol layer's perspective, eMMC memory chips behave exactly like SD memory cards. Even though eMMCs are chips and do not have a card form factor, the terminology for SD cards can still be applied to eMMC due to the similarity of the protocol (`sdmmc_card_t`, `sdmmc_card_init`). Note that eMMC chips cannot be used over SPI, which makes them incompatible with the SD SPI host driver.
|
||||
|
||||
For card configuration and data transfer, use one of the following functions:
|
||||
To initialize eMMC memory and perform read/write operations, follow the steps listed for SD cards in the previous section.
|
||||
|
||||
- :cpp:func:`sdmmc_io_read_byte`, :cpp:func:`sdmmc_io_write_byte` — read and write single byte using IO_RW_DIRECT (CMD52).
|
||||
- :cpp:func:`sdmmc_io_read_bytes`, :cpp:func:`sdmmc_io_write_bytes` — read and write multiple bytes using IO_RW_EXTENDED (CMD53), in byte mode.
|
||||
- :cpp:func:`sdmmc_io_read_blocks`, :cpp:func:`sdmmc_io_write_blocks` — read and write blocks of data using IO_RW_EXTENDED (CMD53), in block mode.
|
||||
|
||||
SDIO interrupts can be enabled by the application using :cpp:func:`sdmmc_io_enable_int` function. When using SDIO in 1-line mode, D1 line also needs to be connected to use SDIO interrupts.
|
||||
Using API with SDIO cards
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Initialization and the probing process is the same as with SD memory cards. The only difference is in data transfer commands in SDIO mode.
|
||||
|
||||
During the card initialization and probing, performed with :cpp:func:`sdmmc_card_init`, the driver only configures the following registers of the IO card:
|
||||
|
||||
1. The IO portion of the card is reset by setting RES bit in the I/O Abort (0x06) register.
|
||||
2. If 4-line mode is enabled in host and slot configuration, the driver attempts to set the Bus width field in the Bus Interface Control (0x07) register. If setting the filed is successful, which means that the slave supports 4-line mode, the host is also switched to 4-line mode.
|
||||
3. If high-speed mode is enabled in the host configuration, the SHS bit is set in the High Speed (0x13) register.
|
||||
|
||||
In particular, the driver does not set any bits in (1) I/O Enable and Int Enable registers, (2) I/O block sizes, etc. Applications can set them by calling :cpp:func:`sdmmc_io_write_byte`.
|
||||
|
||||
For card configuration and data transfer, choose the pair of functions relevant to your case from the table below.
|
||||
|
||||
========================================================================= ================================= =================================
|
||||
Action Read Function Write Function
|
||||
========================================================================= ================================= =================================
|
||||
Read and write a single byte using IO_RW_DIRECT (CMD52) :cpp:func:`sdmmc_io_read_byte` :cpp:func:`sdmmc_io_write_byte`
|
||||
Read and write multiple bytes using IO_RW_EXTENDED (CMD53) in byte mode :cpp:func:`sdmmc_io_read_bytes` :cpp:func:`sdmmc_io_write_bytes`
|
||||
Read and write blocks of data using IO_RW_EXTENDED (CMD53) in block mode :cpp:func:`sdmmc_io_read_blocks` :cpp:func:`sdmmc_io_write_blocks`
|
||||
========================================================================= ================================= =================================
|
||||
|
||||
SDIO interrupts can be enabled by the application using the function :cpp:func:`sdmmc_io_enable_int`. When using SDIO in 1-line mode, the D1 line also needs to be connected to use SDIO interrupts.
|
||||
|
||||
If you want the application to wait until the SDIO interrupt occurs, use :cpp:func:`sdmmc_io_wait_int`.
|
||||
|
||||
The application can wait for SDIO interrupt to occur using :cpp:func:`sdmmc_io_wait_int`.
|
||||
|
||||
Combo (memory + IO) cards
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The driver does not support SD combo cards. Combo cards will be treated as IO cards.
|
||||
The driver does not support SD combo cards. Combo cards are treated as IO cards.
|
||||
|
||||
|
||||
Thread safety
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Most applications need to use the protocol layer only in one task; therefore the protocol layer doesn't implement any kind of locking on the :cpp:class:`sdmmc_card_t` structure, or when accessing SDMMC or SD SPI host drivers. Such locking is usually implemented in the higher layer (e.g. in the filesystem driver).
|
||||
Most applications need to use the protocol layer only in one task. For this reason, the protocol layer does not implement any kind of locking on the :cpp:class:`sdmmc_card_t` structure, or when accessing SDMMC or SD SPI host drivers. Such locking is usually implemented on a higher layer, e.g., in the filesystem driver.
|
||||
|
||||
|
||||
API Reference
|
||||
|
||||
@@ -5,7 +5,7 @@ See also
|
||||
|
||||
- :doc:`Partition Table documentation <../../api-guides/partition-tables>`
|
||||
- :doc:`Over The Air Update (OTA) API <../system/ota>` provides high-level API for updating app firmware stored in flash.
|
||||
- :doc:`Non-Volatile Storage (NVS) API <nvs_flash>` provides a structured API for storing small items of data in SPI flash.
|
||||
- :doc:`Non-Volatile Storage (NVS) API <nvs_flash>` provides a structured API for storing small pieces of data in SPI flash.
|
||||
|
||||
|
||||
.. _spi-flash-implementation-details:
|
||||
@@ -13,35 +13,20 @@ See also
|
||||
Implementation details
|
||||
----------------------
|
||||
|
||||
In order to perform some flash operations, we need to make sure both CPUs
|
||||
are not running any code from flash for the duration of the flash operation.
|
||||
In a single-core setup this is easy: we disable interrupts/scheduler and do
|
||||
the flash operation. In the dual-core setup this is slightly more complicated.
|
||||
We need to make sure that the other CPU doesn't run any code from flash.
|
||||
In order to perform some flash operations, it is necessary to make sure that both CPUs are not running any code from flash for the duration of the flash operation:
|
||||
- In a single-core setup, the SDK does it by disabling interrupts/scheduler before performing the flash operation.
|
||||
- In a dual-core setup, this is slightly more complicated as the SDK needs to make sure that the other CPU is not running any code from flash.
|
||||
|
||||
|
||||
When SPI flash API is called on CPU A (can be PRO or APP), we start
|
||||
spi_flash_op_block_func function on CPU B using esp_ipc_call API. This API
|
||||
wakes up high priority task on CPU B and tells it to execute given function,
|
||||
in this case spi_flash_op_block_func. This function disables cache on CPU B and
|
||||
signals that cache is disabled by setting s_flash_op_can_start flag.
|
||||
Then the task on CPU A disables cache as well, and proceeds to execute flash
|
||||
operation.
|
||||
When SPI flash API is called on CPU A (can be PRO or APP), start the spi_flash_op_block_func function on CPU B using the esp_ipc_call API. This API wakes up a high priority task on CPU B and tells it to execute a given function, in this case, spi_flash_op_block_func. This function disables cache on CPU B and signals that the cache is disabled by setting the s_flash_op_can_start flag. Then the task on CPU A disables cache as well and proceeds to execute flash operation.
|
||||
|
||||
While flash operation is running, interrupts can still run on CPUs A and B.
|
||||
We assume that all interrupt code is placed into RAM. Once interrupt allocation
|
||||
API is added, we should add a flag to request interrupt to be disabled for
|
||||
the duration of flash operations.
|
||||
While a flash operation is running, interrupts can still run on CPUs A and B. It is assumed that all interrupt code is placed into RAM. Once the interrupt allocation API is added, a flag should be added to request the interrupt to be disabled for the duration of a flash operations.
|
||||
|
||||
Once flash operation is complete, function on CPU A sets another flag,
|
||||
s_flash_op_complete, to let the task on CPU B know that it can re-enable
|
||||
cache and release the CPU. Then the function on CPU A re-enables the cache on
|
||||
CPU A as well and returns control to the calling code.
|
||||
Once the flash operation is complete, the function on CPU A sets another flag, s_flash_op_complete, to let the task on CPU B know that it can re-enable cache and release the CPU. Then the function on CPU A re-enables the cache on CPU A as well and returns control to the calling code.
|
||||
|
||||
Additionally, all API functions are protected with a mutex (s_flash_op_mutex).
|
||||
|
||||
In a single core environment (:ref:`CONFIG_FREERTOS_UNICORE` enabled), we simply
|
||||
disable both caches, no inter-CPU communication takes place.
|
||||
In a single core environment (:ref:`CONFIG_FREERTOS_UNICORE` enabled), you need to disable both caches, so that no inter-CPU communication can take place.
|
||||
|
||||
API Reference - SPI Flash
|
||||
-------------------------
|
||||
|
||||
@@ -4,15 +4,16 @@ SPIFFS Filesystem
|
||||
Overview
|
||||
--------
|
||||
|
||||
SPIFFS is a file system intended for SPI NOR flash devices on embedded targets.
|
||||
It supports wear leveling, file system consistency checks and more.
|
||||
SPIFFS is a file system intended for SPI NOR flash devices on embedded targets. It supports wear levelling, file system consistency checks, and more.
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- Currently, SPIFFS does not support directories. It produces a flat structure. If SPIFFS is mounted under ``/spiffs``, then creating a file with path ``/spiffs/tmp/myfile.txt`` will create a file called ``/tmp/myfile.txt`` in SPIFFS, instead of ``myfile.txt`` under directory ``/spiffs/tmp``.
|
||||
- It is not a realtime stack. One write operation might last much longer than another.
|
||||
- Currently, it does not detect or handle bad blocks.
|
||||
- Currently, SPIFFS does not support directories, it produces a flat structure. If SPIFFS is mounted under ``/spiffs``, then creating a file with the path ``/spiffs/tmp/myfile.txt`` will create a file called ``/tmp/myfile.txt`` in SPIFFS, instead of ``myfile.txt`` in the directory ``/spiffs/tmp``.
|
||||
- It is not a real-time stack. One write operation might take much longer than another.
|
||||
- For now, it does not detect or handle bad blocks.
|
||||
|
||||
|
||||
Tools
|
||||
-----
|
||||
@@ -21,29 +22,25 @@ spiffsgen.py
|
||||
^^^^^^^^^^^^
|
||||
|
||||
:component_file:`spiffsgen.py<spiffs/spiffsgen.py>` is a write-only Python SPIFFS implementation used to create filesystem
|
||||
images from the contents of a host folder. To use ``spiffsgen.py``, simply invoke it from your favorite terminal::
|
||||
images from the contents of a host folder. To use ``spiffsgen.py``, open Terminal and run::
|
||||
|
||||
python spiffsgen.py <image_size> <base_dir> <output_file>
|
||||
|
||||
- image_size: size of the partition on which the created SPIFFS image will be flashed to
|
||||
- base_dir: directory to create the SPIFFS image of
|
||||
- output_file: SPIFFS image output file
|
||||
The required arguments are as follows:
|
||||
|
||||
Besides the three required arguments: *image_size*, *base_dir* and *output_file*, there are other arguments
|
||||
that control image generation. Documentation on these arguments exist in the tool's help::
|
||||
- **image_size**: size of the partition onto which the created SPIFFS image will be flashed.
|
||||
- **base_dir**: directory for which the SPIFFS image needs to be created.
|
||||
- **output_file**: SPIFFS image output file.
|
||||
|
||||
There are also other arguments that control image generation. Documentation on these arguments can be found in the tool's help::
|
||||
|
||||
python spiffsgen.py --help
|
||||
|
||||
These optional arguments correspond to possible SPIFFS build configuration.
|
||||
User should make sure that the image is generated with the same arguments/configuration as
|
||||
SPIFFS was built with, else the user ends up with an invalid image. As a guide, the help output indicates the SPIFFS
|
||||
build configuration the argument corresponds to. In cases when these arguments
|
||||
are not specified, the default values shown in the help output are used.
|
||||
These optional arguments correspond to a possible SPIFFS build configuration. To generate the right image, please make sure that you use the same arguments/configuration as were used to build SPIFFS. As a guide, the help output indicates the SPIFFS build configuration to which the argument corresponds. In cases when these arguments are not specified, the default values shown in the help output will be used.
|
||||
|
||||
Once the image has been created, it can be flashed using ``esptool.py`` or ``parttool.py``.
|
||||
When the image is created, it can be flashed using ``esptool.py`` or ``parttool.py``.
|
||||
|
||||
Aside from invoking ``spiffsgen.py`` standalone, it is also possible to use it directly from the build system by calling
|
||||
``spiffs_create_partition_image``.
|
||||
Aside from invoking the ``spiffsgen.py`` standalone by manually running it from the command line or a script, it is also possible to invoke ``spiffsgen.py`` directly from the build system by calling ``spiffs_create_partition_image``.
|
||||
|
||||
Make::
|
||||
|
||||
@@ -53,44 +50,42 @@ CMake::
|
||||
|
||||
spiffs_create_partition_image(<partition> <base_dir> [FLASH_IN_PROJECT])
|
||||
|
||||
This is more convenient as the build configuration is automatically passed to the tool,
|
||||
ensuring that the image generated is valid for that build. An example of this is while the *image_size* is required
|
||||
for the standalone invocation, only the *partition* name is required when using ``spiffs_create_partition_image`` --
|
||||
the image size is automatically obtained from the project's partition table.
|
||||
It is important to note that due to the differences in structure between the two build systems,
|
||||
when using Make, ``spiffs_create_partition_image`` must be called from the project Makefile;
|
||||
for CMake, it should be called from one of the component CMakeLists.txt. For both build systems, the image will be created in the build directory
|
||||
with filename *partition*.bin.
|
||||
This is more convenient as the build configuration is automatically passed to the tool, ensuring that the generated image is valid for that build. An example of this is while the *image_size* is required for the standalone invocation, only the *partition* name is required when using ``spiffs_create_partition_image`` -- the image size is automatically obtained from the project's partition table.
|
||||
|
||||
Optionally, user can opt to have the image automatically flashed together with the app binaries, partition tables, etc. on
|
||||
Due to the differences in structure between Make and Cmake, it is important to note that:
|
||||
- for Make ``spiffs_create_partition_image`` must be called from the project Makefile
|
||||
- for CMake ``spiffs_create_partition_image`` must be called from one of the component CMakeLists.txt files
|
||||
|
||||
For both build systems, the image will be created in the build directory with the filename *partition*.bin.
|
||||
|
||||
Optionally, you can opt to have the image automatically flashed together with the app binaries, partition tables, etc., with
|
||||
``idf.py flash`` or ``make flash`` by specifying ``FLASH_IN_PROJECT``. For example::
|
||||
|
||||
spiffs_create_partition_image(my_spiffs_partition my_folder FLASH_IN_PROJECT)
|
||||
|
||||
If FLASH_IN_PROJECT is not specified, the image is still generated,
|
||||
but user has to flash it manually using ``esptool.py``, ``parttool.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``, ``parttool.py``, or a custom build system target.
|
||||
|
||||
For an example, see :example:`examples/storage/spiffsgen>`.
|
||||
+For an example, see :example:`examples/storage/spiffsgen>`.
|
||||
|
||||
|
||||
mkspiffs
|
||||
^^^^^^^^
|
||||
|
||||
Another tool for creating SPIFS partition images is `mkspiffs <https://github.com/igrr/mkspiffs>`_.
|
||||
Like ``spiffsgen.py``, it can be used to create image from a given folder and then flash that image with ``esptool.py``
|
||||
Another tool for creating SPIFFS partition images is `mkspiffs <https://github.com/igrr/mkspiffs>`_.
|
||||
Similar to ``spiffsgen.py``, it can be used to create an image from a given folder and then flash that image using ``esptool.py``
|
||||
|
||||
To do that you need to obtain some parameters:
|
||||
For that, you need to obtain the following parameters:
|
||||
|
||||
- Block Size: 4096 (standard for SPI Flash)
|
||||
- Page Size: 256 (standard for SPI Flash)
|
||||
- Image Size: Size of the partition in bytes (can be obtained from partition table)
|
||||
- Partition Offset: Starting address of the partition (can be obtained from partition table)
|
||||
- **Block Size**: 4096 (standard for SPI Flash)
|
||||
- **Page Size**: 256 (standard for SPI Flash)
|
||||
- **Image Size**: Size of the partition in bytes (can be obtained from a partition table)
|
||||
- **Partition Offset**: Starting address of the partition (can be obtained from a partition table)
|
||||
|
||||
To pack a folder into 1 Megabyte image::
|
||||
To pack a folder into a 1-Megabyte image, run::
|
||||
|
||||
mkspiffs -c [src_folder] -b 4096 -p 256 -s 0x100000 spiffs.bin
|
||||
|
||||
To flash the image to ESP32 at offset 0x110000::
|
||||
To flash the image onto ESP32 at offset 0x110000, run::
|
||||
|
||||
python esptool.py --chip esp32 --port [port] --baud [baud] write_flash -z 0x110000 spiffs.bin
|
||||
|
||||
@@ -98,21 +93,15 @@ To flash the image to ESP32 at offset 0x110000::
|
||||
Notes on which SPIFFS tool to use
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The two tools presented above offer very similar functionality. There are, however, reasons to prefer one
|
||||
over the other depending on the use case.
|
||||
The two tools presented above offer very similar functionality. However, there are reasons to prefer one over the other, depending on the use case.
|
||||
|
||||
If the intent is to simply generate a SPIFFS image during build, ``spiffsgen.py`` makes it very convenient
|
||||
by providing functions/commands from the build system itself. This makes it easy to generate SPIFFS images
|
||||
that match the build configuration and can be flashed together with the application.
|
||||
Another case for choosing ``spiffsgen.py`` is when the host has no C/C++ compiler available, since ``mkspiffs``
|
||||
requires compilation.
|
||||
Use ``spiffsgen.py`` in the following cases:
|
||||
1. If you want to simply generate a SPIFFS image during the build. ``spiffsgen.py`` makes it very convenient by providing functions/commands from the build system itself.
|
||||
2. If the host has no C/C++ compiler available, because ``spiffsgen.py`` does not require compilation.
|
||||
|
||||
On the other hand, ``mkspiffs`` offers unpacking SPIFFS images in addition to image generation. This is not
|
||||
possible with ``spiffsgen.py``, at least not yet. There might also be environments where a Python interpreter
|
||||
is not available, but a host compiler is or a pre-compiled ``mkspiffs`` binary
|
||||
can do the job. However, there is no build system integration for ``mkspiffs`` and the user has to
|
||||
do the corresponding work: compiling ``mkspiffs`` during build (if a pre-compiled binary is not used), creating build rules/targets
|
||||
for the output files, passing proper parameters to the tool, etc.
|
||||
Use ``mkspiffs`` in the following cases:
|
||||
1. If you need to unpack SPIFFS images in addition to image generation. For now, it is not possible with ``spiffsgen.py``.
|
||||
2. If you have an environment where a Python interpreter is not available, but a host compiler is available. Otherwise, a pre-compiled ``mkspiffs`` binary can do the job. However, there is no build system integration for ``mkspiffs`` and the user has to do the corresponding work: compiling ``mkspiffs`` during build (if a pre-compiled binary is not used), creating build rules/targets for the output files, passing proper parameters to the tool, etc.
|
||||
|
||||
|
||||
See also
|
||||
@@ -120,14 +109,14 @@ See also
|
||||
|
||||
- :doc:`Partition Table documentation <../../api-guides/partition-tables>`
|
||||
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
An example for using SPIFFS is provided in :example:`storage/spiffs` directory. This example initializes and mounts SPIFFS partition, and writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information.
|
||||
An example of using SPIFFS is provided in the :example:`storage/spiffs` directory. This example initializes and mounts a SPIFFS partition, then writes and reads data from it using POSIX and C library APIs. See the README.md file in the example directory for more information.
|
||||
|
||||
High level API Reference
|
||||
|
||||
High-level API Reference
|
||||
------------------------
|
||||
|
||||
* :component_file:`spiffs/include/esp_spiffs.h`
|
||||
|
||||
.. include:: /_build/inc/esp_spiffs.inc
|
||||
|
||||
@@ -9,7 +9,7 @@ See also
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
An example which combines wear levelling driver with FATFS library is provided in ``examples/storage/wear_levelling`` directory. This example initializes the wear levelling driver, mounts FATFS partition, and writes and reads data from it using POSIX and C library APIs. See README.md file in the example directory for more information.
|
||||
An example which combines the wear levelling driver with the FATFS library is provided in the :example:`storage/wear_levelling` directory. This example initializes the wear levelling driver, mounts FATFS partition, as well as writes and reads data from it using POSIX and C library APIs. See the :example:`storage/wear_levelling/README.md` file for more information.
|
||||
|
||||
High level API Reference
|
||||
------------------------
|
||||
|
||||
Reference in New Issue
Block a user