docs: split spi_flash api-reference documents to peripherals folder

This commit is contained in:
Michael (XIAO Xufeng)
2022-11-23 16:48:17 +08:00
parent 8a095a74d4
commit daa4af1b1f
26 changed files with 142 additions and 85 deletions
@@ -29,6 +29,7 @@ Peripherals API
sdspi_host
:SOC_SDIO_SLAVE_SUPPORTED: sdio_slave
:SOC_SDM_SUPPORTED: sdm
spi_flash/spi_flash
spi_master
spi_slave
:esp32: secure_element
@@ -0,0 +1,37 @@
.. _auto-suspend:
Flash Auto Suspend Feature
--------------------------
.. important::
1. The flash chip you are using should have a suspend/resume feature.
2. The MSPI hardware should support the auto-suspend feature (hardware can send suspend command automatically).
If you use suspend feature on an unsupported chip, it may cause a severe crash. Therefore, we strongly suggest you reading the flash chip datasheets first. Ensure the flash chip satisfies the following conditions at minimum.
1. SUS bit in status registers should in SR2 bit7 (or SR bit15)(This is caused by the restriction of out software implementation).
2. Suspend command is 75H, resume command is 7AH(This is caused by the restriction of out software implementation).
3. When the flash is successfully suspended, all address of the flash, except from the section/block being erased, can be read correctly. And resume can be sent immediately at this state.
4. When the flash is successfully resumed, another suspend can be sent immediately at this state.
When :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` is enabled, the caches will be kept enabled (they would be disabled if :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` is disabled). The hardware handles the arbitration between SPI0 and SPI1. If SPI1 operation is short (like reading operation), the CPU and the cache will wait until the SPI1 operation is done. However, if it is erasing, page programming or status register writing (e.g. `SE`, `PP` and `WRSR`), an auto suspend will happen, interrupting the ongoing flash operation, making the CPU able to read from cache and flash in limited time.
This way some code/variables can be put into the flash/psram instead of IRAM/DRAM, while still able to be executed during flash erasing. This reduces the some usage of IRAM/DRAM.
Please note this feature has the overhead of the flash suspend/resume. The flash erasing can be extremely long if the erasing is interrupted too often. Use FreeRTOS task priorities to ensure that only real-time critical tasks are executed at higher priority than flash erase, to allow the flash erase to complete in reasonable time.
In other words, there are three kinds of code:
1. Critical code: inside IRAM/DRAM. This kind of code usually has high performance requirements, related to cache/flash/psram, or called very often.
2. Cached code: inside flash/psram. This kind of code has lower performance requirements or called less often. They will execute during erasing, with some overhead.
3. Low priority code: inside flash/psram and disabled during erasing. This kind of code should be forbidden from executed to avoid affecting the flash erasing, by setting a lower task priority than the erasing task.
Regarding the flash suspend feature usage, and corresponding response time delay, please also see this example :example:`system/flash_suspend` .
@@ -0,0 +1,261 @@
SPI Flash API
=============
:link_to_translation:`zh_CN:[中文]`
Overview
--------
The spi_flash component contains API functions related to reading, writing, erasing, memory mapping for data in the external flash.
For higher-level API functions which work with partitions defined in the :doc:`partition table </api-guides/partition-tables>`, see :doc:`/api-reference/storage/partition`
.. note::
``esp_partition_*`` APIs are recommended to be used instead of the lower level ``esp_flash_*`` API functions when accessing the main SPI Flash chip, since they do bounds checking and are guaranteed to calculate correct offsets in flash based on the information in the partition table. ``esp_flash_*`` functions can still be used directly when accessing an external (secondary) SPI flash chip.
Different from the API before IDF v4.0, the functionality of ``esp_flash_*`` APIs is not limited to the "main" SPI flash chip (the same SPI flash chip from which program runs). With different chip pointers, you can access external flash chips connected to not only SPI0/1 but also other SPI buses like SPI2.
.. note::
Instead of going through the cache connected to the SPI0 peripheral, most ``esp_flash_*`` APIs go through other SPI peripherals like SPI1, SPI2, etc. This makes them able to access not only the main flash, but also external (secondary) flash.
However, due to limitations of the cache, operations through the cache are limited to the main flash. The address range limitation for these operations are also on the cache side. The cache is not able to access external flash chips or address range above its capabilities. These cache operations include: mmap, encrypted read/write, executing code or access to variables in the flash.
.. note::
Flash APIs after ESP-IDF v4.0 are no longer *atomic*. If a write operation occurs during another on-going read operation, and the flash addresses of both operations overlap, the data returned from the read operation may contain both old data and new data (that was updated written by the write operation).
.. note::
Encrypted flash operations are only supported with the main flash chip (and not with other flash chips, that is on SPI1 with different CS, or on other SPI buses). Reading through cache is only supported on the main flash, which is determined by the HW.
Support for Features of Flash Chips
-----------------------------------
Quad/Dual Mode Chips
^^^^^^^^^^^^^^^^^^^^
Features of different flashes are implemented in different ways and thus need speical support. The fast/slow read and Dual mode (DOUT/DIO) of almost all 24-bits address flash chips are supported, because they don't need any vendor-specific commands.
Quad mode (QIO/QOUT) is supported on following chip types:
1. ISSI
2. GD
3. MXIC
4. FM
5. Winbond
6. XMC
7. BOYA
Optional Features
^^^^^^^^^^^^^^^^^
.. toctree::
:hidden:
spi_flash_optional_feature
There are some features that are not supported by all flash chips, or not supported by all Espressif chips. These features include:
.. only:: esp32s3
- OPI flash - means that flash supports octal mode.
- 32-bit address flash - usually means that the flash has higher capacity (equal to or larger than 16 MB) that needs longer addresses.
.. only:: esp32s3
- High performance mode (HPM) - means that flash works under high frequency which is higher than 80MHz.
- Flash unique ID - means that flash supports its unique 64-bits ID.
.. only:: esp32c3
- Suspend & Resume - means that flash can accept suspend/resume command during its writing/erasing. The {IDF_TARGET_NAME} may keep the cache on when the flash is being written/erased and suspend it to read its contents randomly.
If you want to use these features, please ensure both {IDF_TARGET_NAME} and ALL flash chips in your product support these features. For more details, refer to :doc:`spi_flash_optional_feature`.
You may also customise your own flash chip driver. See :doc:`spi_flash_override_driver` for more details.
.. toctree::
:hidden:
Custom Flash Driver <spi_flash_override_driver>
Initializing a Flash Device
---------------------------
To use the ``esp_flash_*`` APIs, you need to initialise a flash chip on a certain SPI bus, as shown below:
1. Call :cpp:func:`spi_bus_initialize` to properly initialize an SPI bus. This function initializes the resources (I/O, DMA, interrupts) shared among devices attached to this bus.
2. Call :cpp:func:`spi_bus_add_flash_device` to attach the flash device to the bus. This function allocates memory and fills the members for the ``esp_flash_t`` structure. The CS I/O is also initialized here.
3. Call :cpp:func:`esp_flash_init` to actually communicate with the chip. This will also detect the chip type, and influence the following operations.
.. note:: Multiple flash chips can be attached to the same bus now.
SPI Flash Access API
--------------------
This is the set of API functions for working with data in flash:
- :cpp:func:`esp_flash_read` reads data from flash to RAM
- :cpp:func:`esp_flash_write` writes data from RAM to flash
- :cpp:func:`esp_flash_erase_region` erases specific region of flash
- :cpp:func:`esp_flash_erase_chip` erases the whole flash
- :cpp:func:`esp_flash_get_chip_size` returns flash chip size, in bytes, as configured in menuconfig
Generally, try to avoid using the raw SPI flash functions to the "main" SPI flash chip in favour of :ref:`partition-specific functions <flash-partition-apis>`.
SPI Flash Size
--------------
The SPI flash size is configured by writing a field in the software bootloader image header, flashed at offset 0x1000.
By default, the SPI flash size is detected by esptool.py when this bootloader is written to flash, and the header is updated with the correct size. Alternatively, it is possible to generate a fixed flash size by setting :envvar:`CONFIG_ESPTOOLPY_FLASHSIZE` in the project configuration.
If it is necessary to override the configured flash size at runtime, it is possible to set the ``chip_size`` member of the ``g_rom_flashchip`` structure. This size is used by ``esp_flash_*`` functions (in both software & ROM) to check the bounds.
Concurrency Constraints for Flash on SPI1
-----------------------------------------
.. toctree::
:hidden:
spi_flash_concurrency
.. attention::
The SPI0/1 bus is shared between the instruction & data cache (for firmware execution) and the SPI1 peripheral (controlled by the drivers including this SPI flash driver). Hence, calling SPI Flash API on SPI1 bus (including the main flash) will cause significant influence to the whole system. See :doc:`spi_flash_concurrency` for more details.
SPI Flash Encryption
--------------------
It is possible to encrypt the contents of SPI flash and have it transparently decrypted by hardware.
Refer to the :doc:`Flash Encryption documentation </security/flash-encryption>` for more details.
Memory Mapping API
------------------
{IDF_TARGET_CACHE_SIZE:default="64 KB",esp32c2=16~64 KB}
{IDF_TARGET_NAME} features memory hardware which allows regions of flash memory to be mapped into instruction and data address spaces. This mapping works only for read operations. It is not possible to modify contents of flash memory by writing to a mapped memory region.
Mapping happens in {IDF_TARGET_CACHE_SIZE} pages. Memory mapping hardware can map flash into the data address space and the instruction address space. See the technical reference manual for more details and limitations about memory mapping hardware.
Note that some pages are used to map the application itself into memory, so the actual number of available pages may be less than the capability of the hardware.
Reading data from flash using a memory mapped region is the only way to decrypt contents of flash when :doc:`flash encryption </security/flash-encryption>` is enabled. Decryption is performed at the hardware level.
Memory mapping API are declared in ``spi_flash_mmap.h`` and ``esp_partition.h``:
- :cpp:func:`spi_flash_mmap` maps a region of physical flash addresses into instruction space or data space of the CPU.
- :cpp:func:`spi_flash_munmap` unmaps previously mapped region.
- :cpp:func:`esp_partition_mmap` maps part of a partition into the instruction space or data space of the CPU.
Differences between :cpp:func:`spi_flash_mmap` and :cpp:func:`esp_partition_mmap` are as follows:
- :cpp:func:`spi_flash_mmap` must be given a {IDF_TARGET_CACHE_SIZE} aligned physical address.
- :cpp:func:`esp_partition_mmap` may be given any arbitrary offset within the partition. It will adjust the returned pointer to mapped memory as necessary.
Note that since memory mapping happens in pages, it may be possible to read data outside of the partition provided to ``esp_partition_mmap``, regardless of the partition boundary.
.. note::
mmap is supported by cache, so it can only be used on main flash.
SPI Flash Implementation
------------------------
The ``esp_flash_t`` structure holds chip data as well as three important parts of this API:
1. The host driver, which provides the hardware support to access the chip;
2. The chip driver, which provides compatibility service to different chips;
3. The OS functions, provide support of some OS functions (e.g. lock, delay) in different stages (1st/2nd boot, or the app).
Host driver
^^^^^^^^^^^
The host driver relies on an interface (``spi_flash_host_driver_t``) defined in the ``spi_flash_types.h`` (in the ``hal/include/hal`` folder). This interface provides some common functions to communicate with the chip.
In other files of the SPI HAL, some of these functions are implemented with existing {IDF_TARGET_NAME} memory-spi functionalities. However, due to the speed limitations of {IDF_TARGET_NAME}, the HAL layer cannot provide high-speed implementations to some reading commands (so the support for it was dropped). The files (``memspi_host_driver.h`` and ``.c``) implement the high-speed version of these commands with the ``common_command`` function provided in the HAL, and wrap these functions as ``spi_flash_host_driver_t`` for upper layer to use.
You can also implement your own host driver, even with the GPIO. As long as all the functions in the ``spi_flash_host_driver_t`` are implemented, the esp_flash API can access the flash regardless of the low-level hardware.
Chip Driver
^^^^^^^^^^^
The chip driver, defined in ``spi_flash_chip_driver.h``, wraps basic functions provided by the host driver for the API layer to use.
Some operations need some commands to be sent first, or read some status afterwards. Some chips need different commands or values, or need special communication ways.
There is a type of chip called ``generic chip`` which stands for common chips. Other special chip drivers can be developed on the base of the generic chip.
The chip driver relies on the host driver.
.. _esp_flash_os_func:
OS Functions
^^^^^^^^^^^^
Currently the OS function layer provides entries of a lock and delay.
The lock (see :ref:`spi_bus_lock`) is used to resolve the conflicts among the access of devices on the same SPI bus, and the SPI Flash chip access. E.g.
1. On SPI1 bus, the cache (used to fetch the data (code) in the Flash and PSRAM) should be disabled when the flash chip on the SPI0/1 is being accessed.
2. On the other buses, the flash driver needs to disable the ISR registered by SPI Master driver, to avoid conflicts.
3. Some devices of SPI Master driver may require to use the bus monopolized during a period (especially when the device doesn't have a CS wire, or the wire is controlled by software like SDSPI driver).
The delay is used by some long operations which requires the master to wait or polling periodically.
The top API wraps these the chip driver and OS functions into an entire component, and also provides some argument checking.
OS functions can also help to avoid a watchdog timeout when erasing large flash areas. During this time, the CPU is occupied with the flash erasing task. This stops other tasks from being executed. Among these tasks is the idle task to feed the watchdog timer (WDT). If the configuration option :ref:`CONFIG_ESP_TASK_WDT_PANIC` is selected and the flash operation time is longer than the watchdog timeout period, the system will reboot.
It's pretty hard to totally eliminate this risk, because the erasing time varies with different flash chips, making it hard to be compatible in flash drivers. Therefore, users need to pay attention to it. Please use the following guidelines:
1. It is recommended to enable the :ref:`CONFIG_SPI_FLASH_YIELD_DURING_ERASE` option to allow the scheduler to re-schedule during erasing flash memory. Besides, following parameters can also be used.
- Increase :ref:`CONFIG_SPI_FLASH_ERASE_YIELD_TICKS` or decrease :ref:`CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS` in menuconfig.
- You can also increase :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` in menuconfig for a larger watchdog timeout period. However, with larger watchdog timeout period, previously detected timeouts may no longer be detected.
2. Please be aware of the consequences of enabling the :ref:`CONFIG_ESP_TASK_WDT_PANIC` option when doing long-running SPI flash operations which will trigger the panic handler when it times out. However, this option can also help dealing with unexpected exceptions in your application. Please decide whether this is needed to be enabled according to actual condition.
3. During your development, please carefully review the actual flash operation according to the specific requirements and time limits on erasing flash memory of your projects. Always allow reasonable redundancy based on your specific product requirements when configuring the flash erasing timeout threshold, thus improving the reliability of your product.
.. _spi-flash-implementation-details:
Implementation Details
----------------------
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 needs to disable interrupts or scheduler before performing the flash operation.
- In a dual-core setup, the SDK needs to make sure that both CPUs are not running any code from flash.
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 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 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), you need to disable both caches, so that no inter-CPU communication can take place.
API Reference - SPI Flash
-------------------------
.. include-build-file:: inc/esp_flash_spi_init.inc
.. include-build-file:: inc/esp_flash.inc
.. include-build-file:: inc/spi_flash_mmap.inc
.. include-build-file:: inc/spi_flash_types.inc
.. include-build-file:: inc/esp_flash_err.inc
API Reference - Flash Encrypt
-----------------------------
.. include-build-file:: inc/esp_flash_encrypt.inc
@@ -0,0 +1,85 @@
.. _concurrency-constraints-flash:
Concurrency Constraints for Flash on SPI1
=========================================
The SPI0/1 bus is shared between the instruction & data cache (for firmware execution) and the SPI1 peripheral (controlled by the drivers including this SPI Flash driver). Hence, operations to SPI1 will cause significant influence to the whole system. This kind of operations include calling SPI Flash API or other drivers on SPI1 bus, any operations like read/write/erase or other user defined SPI operations, regardless to the main flash or other SPI slave devices.
.. only:: not (esp32c3 or SOC_SPIRAM_XIP_SUPPORTED)
On {IDF_TARGET_NAME}, these caches must be disabled while reading/writing/erasing.
.. only:: esp32c3
On {IDF_TARGET_NAME}, the config option :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` (enabled by default) allows the cache to read flash concurrently with SPI1 operations. See :ref:`auto-suspend` for more details.
If this option is disabled, the caches must be disabled while reading/writing/erasing operations. There are some constraints using driver on the SPI1 bus, see :ref:`impact_disabled_cache`. These constraints will cause more IRAM/DRAM usages.
.. only:: SOC_SPIRAM_XIP_SUPPORTED
On {IDF_TARGET_NAME}, the config options :ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` (disabled by default) and :ref:`CONFIG_SPIRAM_RODATA` (disabled by default) allow the cache to read/write PSRAM concurrently with SPI1 operations. See :ref:`xip_from_psram` for more details.
If these options are disabled, the caches must be disabled while reading/writing/erasing operations. There are some constraints using driver on the SPI1 bus, see :ref:`impact_disabled_cache`. These constraints will cause more IRAM/DRAM usages.
.. _impact_disabled_cache:
When the Caches Are Disabled
----------------------------
Under this condition, all CPUs should always execute code and access data from internal RAM. The APIs documented in this file will disable the caches automatically and transparently.
.. only:: esp32c3
.. note::
When :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` is enabled, these APIs won't disable the caches. The hardware will handle the arbitration between them.
.. only:: SOC_SPIRAM_XIP_SUPPORTED
.. note::
When :ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` and :ref:`CONFIG_SPIRAM_RODATA` are both enabled, these APIs won't disable the caches.
.. only:: not CONFIG_FREERTOS_UNICORE
The way that these APIs disable the caches will suspend all the other tasks. Besides, all non-IRAM-safe interrupts will be disabled. The other core will be polling in a busy loop. These will be restored until the Flash operation completes.
.. only:: CONFIG_FREERTOS_UNICORE
The way that these APIs disable the caches will also disable non-IRAM-safe interrupts. These will be restored until the Flash operation completes.
See also :ref:`esp_flash_os_func` and :ref:`spi_bus_lock`.
There are no such constraints and impacts for flash chips on other SPI buses than SPI0/1.
For differences between internal RAM (e.g. IRAM, DRAM) and flash cache, please refer to the :ref:`application memory layout <memory-layout>` documentation.
.. _iram-safe-interrupt-handlers:
IRAM-Safe Interrupt Handlers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For interrupt handlers which need to execute when the cache is disabled (e.g., for low latency operations), set the ``ESP_INTR_FLAG_IRAM`` flag when the :doc:`interrupt handler is registered </api-reference/system/intr_alloc>`.
You must ensure that all data and functions accessed by these interrupt handlers, including the ones that handlers call, are located in IRAM or DRAM. See :ref:`how-to-place-code-in-iram`.
If a function or symbol is not correctly put into IRAM/DRAM, and the interrupt handler reads from the flash cache during a flash operation, it will cause a crash due to Illegal Instruction exception (for code which should be in IRAM) or garbage data to be read (for constant data which should be in DRAM).
.. note::
When working with strings in ISRs, it is not advised to use ``printf`` and other output functions. For debugging purposes, use :cpp:func:`ESP_DRAM_LOGE` and similar macros when logging from ISRs. Make sure that both ``TAG`` and format string are placed into ``DRAM`` in that case.
Non-IRAM-Safe Interrupt Handlers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If the ``ESP_INTR_FLAG_IRAM`` flag is not set when registering, the interrupt handler will not get executed when the caches are disabled. Once the caches are restored, the non-IRAM-safe interrupts will be re-enabled. After this moment, the interrupt handler will run normally again. This means that as long as caches are disabled, users won't see the corresponding hardware event happening.
.. only:: esp32c3
.. include:: auto_suspend.inc
.. only:: SOC_SPIRAM_XIP_SUPPORTED
.. include:: xip_from_psram.inc
@@ -0,0 +1,117 @@
Optional features for flash
===========================
Some features are not supported on all ESP chips and Flash chips. You can check the list below for more information.
- `Auto Suspend & Resume <#auto-suspend-&-resume>`__
- `Flash unique ID <#flash-unique-id>`__
- `High performance mode <#high-performance-mode>`__
- `OPI flash support <#opi-flash-support>`__
- `32-bit Address Flash Chips <#32-bit-address-flash-chips>`__
.. note::
- The features listed above needs to be supported by both esp chips and flash chips.
- If you are using an official Espressif modules/SiP. Some of the modules/SiPs always support the feature, in this case you can see these features listed in the datasheet. Otherwise please contact `Espressif's business team <https://www.espressif.com/en/contact-us/sales-questions>`_ to know if we can supply such products for you.
- If you are making your own modules with your own bought flash chips, and you need features listed above. Please contact your vendor if they support the those features, and make sure that the chips can be supplied continuously.
.. attention::
This document only shows that IDF code has supported the features of those flash chips. It's not a list of stable flash chips certified by Espressif. If you build your own hardware from flash chips with your own brought flash chips (even with flash listed in this page), you need to validate the reliability of flash chips yourself.
Auto Suspend & Resume
---------------------
.. only:: esp32c3
You can refer to :ref:`auto-suspend` for more information about this feature. The support list is as follows.
ESP Chips List:
1. ESP32C3
Flash Chips List:
1. XM25QxxC series.
Flash unique ID
---------------
Unique ID is not flash id, which means flash has 64-Bit unique ID for each device. The instruction to read the unique ID (4Bh) accesses a factory-set read-only 64-bit number that is unique to each flash device. This ID number helps you to recognize each single device. Not all flash vendors support this feature. If you try to read the unique ID on a chip which does not have this feature, the behavior is not determined. The support list is as follows.
ESP Chips Lists:
ALL
Flash Chips List:
1. ISSI
2. GD
3. TH
4. FM
5. Winbond
6. XMC
7. BOYA
High performance mode
---------------------
.. note::
This section is provided for Dual mode (DOUT/DIO) and Quad mode (QIO/QOUT) flash chips. Octal flash used on ESP-chips support High performance mode by default so far, you can refer to the octal flash support list below.
High performance mode (HPM) means that the SPI1 and flash chip works under high frequency. Usually, when the operating frequency of the flash is greater than 80MHz, it is considered that the flash works under HPM. As far as we acknowledged, flash chips have more than two different coping strategies when flash work under HPM. For some flash chips, HPM is controlled by high performance flag (HPF) in status register and for some flash chips, HPM is controlled by dummy cycle bit.
For following conditions IDF start code deals with HPM internally.
ESP Chips List:
1. ESP32S3
Flash Chips (name & ID) List:
1. GD25Q64C (ID: 0xC84017)
2. GD25Q32C (ID: 0xC84016)
.. attention::
It is hard to create several strategies to cover all situations, so all flash chips using HPM need to be supported explicitly. Therefore, if you try to use a flash not listed as supported under high performance mode, it might cause some error. So, when you try to use the flash chip beyond supported list, please test properly.
OPI flash support
-----------------
OPI flash means that the flash chip supports octal peripheral interface, which has octal I/O pins. Different octal flash has different configurations and different commands. Hence, it is necessary to carefully check the support list.
.. only:: esp32s3
.. note::
To know how to configure menuconfig for a board with different Flash and PSRAM, please refer to the :ref:`SPI Flash and External SPI RAM Configuration <flash-psram-configuration>`
ESP Chips List:
1. ESP32S3
Flash Chips List:
1. MX25UM25645G
32-bit Address Flash Chips
--------------------------
Most NOR flash chips used by Espressif chips use 24-bits address, which can cover 16 MBytes memory. However, for larger memory (usually equal to or larger than 16 MBytes), flash uses a 32-bits address to address larger memory. Regretfully, 32-bits address chips have vendor-specific commands, so we need to support the chips one by one.
ESP Chips List:
ALL ESP Chips support this.
Flash Chips List:
1. W25Q256
2. GD25Q256
@@ -0,0 +1,83 @@
Overriding Default Chip Drivers
===============================
.. warning::
Customizing SPI Flash Chip Drivers is considered an "expert" feature. Users should only do so at their own risk. (See the notes below)
During the SPI Flash driver's initialization (i.e., :cpp:func:`esp_flash_init`), there is a chip detection step during which the driver will iterate through a Default Chip Driver List and determine which chip driver can properly support the currently connected flash chip. The Default Chip Drivers are provided by the IDF, thus are updated in together with each IDF version. However IDF also allows users to customize their own chip drivers.
Users should note the following when customizing chip drivers:
1. You may need to rely on some non-public IDF functions, which have slight possibility to change between IDF versions. On the one hand, these changes may be useful bug fixes for your driver, on the other hand, they may also be breaking changes (i.e., breaks your code).
2. Some IDF bug fixes to other chip drivers will not be automatically applied to your own custom chip drivers.
3. If the protection of flash is not handled properly, there may be some random reliability issues.
4. If you update to a newer IDF version that has support for more chips, you will have to manually add those new chip drivers into your custom chip driver list. Otherwise the driver will only search for the drivers in custom list you provided.
Steps For Creating Custom Chip Drivers and Overriding the IDF Default Driver List
---------------------------------------------------------------------------------
.. highlight: cmake
1. Enable the :ref:`CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST` config option. This will prevent compilation and linking of the Default Chip Driver List (`default_registered_chips`) provided by IDF. Instead, the linker will search for the structure of the same name (`default_registered_chips`) that must be provided by the user.
2. Add a new component in your project, e.g. `custom_chip_driver`.
3. Copy the necessary chip driver files from the `spi_flash` component in IDF. This may include:
- `spi_flash_chip_drivers.c` (to provide the `default_registered_chips` structure)
- Any of the `spi_flash_chip_*.c` files that matches your own flash model best
- `CMakeLists.txt` and `linker.lf` files
Modify the files above properly. Including:
- Change the ``default_registered_chips`` variable to non-static and remove the #ifdef logic around it.
- Update `linker.lf` file to rename the fragment header and the library name to match the new component.
- If reusing other drivers, some header names need prefixing with ``spi_flash/`` when included from outside spi_flash component.
.. note::
- When writing your own flash chip driver, you can set your flash chip capabilities through `spi_flash_chip_***(vendor)_get_caps` and points the function pointer `get_chip_caps` for protection to the `spi_flash_chip_***_get_caps` function. The steps are as follows.
1. Please check whether your flash chip have the capabilities listed in `spi_flash_caps_t` by checking the flash datasheet.
2. Write a function named `spi_flash_chip_***(vendor)_get_caps`. Take the example below as a reference. (if the flash support `suspend` and `read unique id`).
3. Points the pointer `get_chip_caps` (in `spi_flash_chip_t`) to the function mentioned above.
.. code-block:: c
spi_flash_caps_t spi_flash_chip_***(vendor)_get_caps(esp_flash_t *chip)
{
spi_flash_caps_t caps_flags = 0;
// 32-bit-address flash is not supported
flash-suspend is supported
caps_flags |= SPI_FLAHS_CHIP_CAP_SUSPEND;
// flash read unique id.
caps_flags |= SPI_FLASH_CHIP_CAP_UNIQUE_ID;
return caps_flags;
}
.. code-block:: c
const spi_flash_chip_t esp_flash_chip_eon = {
// Other function pointers
.get_chip_caps = spi_flash_chip_eon_get_caps,
};
- You also can see how to implement this in the example :example:`storage/custom_flash_driver`.
4. Write a new `CMakeLists.txt` file for the `custom_chip_driver` component, including an additional line to add a linker dependency from `spi_flash` to `custom_chip_driver`::
idf_component_register(SRCS "spi_flash_chip_drivers.c"
"spi_flash_chip_mychip.c" # modify as needed
REQUIRES hal
PRIV_REQUIRES spi_flash
LDFRAGMENTS linker.lf)
idf_component_add_link_dependency(FROM spi_flash)
- An example of this component CMakeLists.txt can be found in :example_file:`storage/custom_flash_driver/components/custom_chip_driver/CMakeLists.txt`
5. The `linker.lf` is used to put every chip driver that you are going to use whilst cache is disabled into internal RAM. See :doc:`/api-guides/linker-script-generation` for more details. Make sure this file covers all the source files that you add.
6. Build your project, and you will see the new flash driver is used.
Example
-------
See also :example:`storage/custom_flash_driver`.
@@ -0,0 +1,12 @@
.. _xip_from_psram:
XIP from PSRAM Feature
----------------------
If :ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` is enabled, the flash ``.text`` sections (used for instructions) will be placed in PSRAM.
If :ref:`CONFIG_SPIRAM_RODATA` is enabled, the flash ``.rodata`` sections (used for read only data) will be placed in PSRAM.
The corresponding virtual memory range will be re-mapped to PSRAM.
If both of the above options are enabled, the Cache won't be disabled during an SPI1 Flash operation. You don't need to make sure ISRs, ISR callbacks and involved data are placed in internal RAM.