mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
Merge branch 'docs/update_cn_translation_of_16452_and_16658' into 'master'
docs: updated CN translation for !16452 and !16658 Closes DOC-2828 and DOC-2827 See merge request espressif/esp-idf!18007
This commit is contained in:
commit
4ad048f05f
@ -7,17 +7,17 @@ Overview
|
||||
--------
|
||||
The spi_flash component contains API functions related to reading, writing, erasing, memory mapping for data in the external flash. The spi_flash component also has higher-level API functions which work with partitions defined in the :doc:`partition table </api-guides/partition-tables>`.
|
||||
|
||||
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 to external flash chips connected to not only SPI0/1 but also other SPI buses like SPI2.
|
||||
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 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 to not only the main flash, but also external flash.
|
||||
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 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.
|
||||
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 IDF v4.0 are no longer *atomic*. A writing operation during another on-going read operation, on the overlapped flash address, may cause the return data from the read operation to be partly same as before, and partly updated as new written.
|
||||
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).
|
||||
|
||||
|
||||
Kconfig option :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL` can be used to switch ``spi_flash_*`` functions back to the implementation before ESP-IDF v4.0. However, the code size may get bigger if you use the new API and the old API at the same time.
|
||||
@ -27,10 +27,10 @@ Encrypted reads and writes use the old implementation, even if :ref:`CONFIG_SPI_
|
||||
Support for Features of Flash Chips
|
||||
-----------------------------------
|
||||
|
||||
Quad/Dual mode chips
|
||||
Quad/Dual Mode Chips
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Flash features of different vendors are operated in different ways and need special 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.
|
||||
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:
|
||||
|
||||
@ -50,13 +50,13 @@ Optional Features
|
||||
|
||||
spi_flash_optional_feature
|
||||
|
||||
There are some features that are not supported by all flash models, or not supported by all Espressif chips. These features include:
|
||||
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 16MB) that needs longer address to access.
|
||||
- 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
|
||||
|
||||
@ -68,9 +68,9 @@ There are some features that are not supported by all flash models, or not suppo
|
||||
|
||||
- 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, you need to ensure {IDF_TARGET_NAME} supports this feature, and ALL the flash chips in your product have this feature. For more details, refer :doc:`spi_flash_optional_feature`.
|
||||
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`.
|
||||
|
||||
Users can also customize their own flash chip driver, see :doc:`spi_flash_override_driver` for more details.
|
||||
You may also customise your own flash chip driver. See :doc:`spi_flash_override_driver` for more details.
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
@ -80,15 +80,15 @@ Users can also customize their own flash chip driver, see :doc:`spi_flash_overri
|
||||
Initializing a Flash Device
|
||||
---------------------------
|
||||
|
||||
To use ``esp_flash_*`` APIs, you need to have a chip initialized on a certain SPI bus.
|
||||
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 functions initialize the resources (I/O, DMA, interrupts) shared among devices attached to this bus.
|
||||
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 onto the bus. This allocates memory, and fill the members for the ``esp_flash_t`` structure. The CS I/O is also initialized here.
|
||||
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. However, using ``esp_flash_*`` devices and ``spi_device_*`` devices on the same SPI bus is not supported yet.
|
||||
.. note:: Multiple flash chips can be attached to the same bus now.
|
||||
|
||||
SPI Flash Access API
|
||||
--------------------
|
||||
@ -99,7 +99,7 @@ This is the set of API functions for working with data in flash:
|
||||
- :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:`spi_flash_get_chip_size` returns flash chip size, in bytes, as configured in menuconfig
|
||||
- :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>`.
|
||||
|
||||
@ -108,11 +108,11 @@ 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 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` in project configuration.
|
||||
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
|
||||
Concurrency Constraints for Flash on SPI1
|
||||
-----------------------------------------
|
||||
|
||||
.. toctree::
|
||||
@ -129,7 +129,7 @@ Concurrency Constraints for flash on SPI1
|
||||
Partition Table API
|
||||
-------------------
|
||||
|
||||
ESP-IDF projects use a partition table to maintain information about various regions of SPI flash memory (bootloader, various application binaries, data, filesystems). More information on partition tables can be found :doc:`here </api-guides/partition-tables>`.
|
||||
ESP-IDF projects use a partition table to maintain information about various regions of SPI flash memory (bootloader, various application binaries, data, filesystems). More information can be found in :doc:`Partition Tables </api-guides/partition-tables>`.
|
||||
|
||||
This component provides API functions to enumerate partitions found in the partition table and perform operations on them. These functions are declared in ``esp_partition.h``:
|
||||
|
||||
@ -137,7 +137,7 @@ This component provides API functions to enumerate partitions found in the parti
|
||||
- :cpp:func:`esp_partition_get` returns a structure describing the partition for a given iterator.
|
||||
- :cpp:func:`esp_partition_next` shifts the iterator to the next found partition.
|
||||
- :cpp:func:`esp_partition_iterator_release` releases iterator returned by ``esp_partition_find``.
|
||||
- :cpp:func:`esp_partition_find_first` - a convenience function which returns the structure describing the first partition found by ``esp_partition_find``.
|
||||
- :cpp:func:`esp_partition_find_first` is a convenience function which returns the structure describing the first partition found by ``esp_partition_find``.
|
||||
- :cpp:func:`esp_partition_read`, :cpp:func:`esp_partition_write`, :cpp:func:`esp_partition_erase_range` are equivalent to :cpp:func:`spi_flash_read`, :cpp:func:`spi_flash_write`, :cpp:func:`spi_flash_erase_range`, but operate within partition boundaries.
|
||||
|
||||
.. note::
|
||||
@ -173,7 +173,7 @@ Memory mapping API are declared in ``esp_spi_flash.h`` and ``esp_partition.h``:
|
||||
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.
|
||||
- :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.
|
||||
|
||||
@ -194,16 +194,16 @@ 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 can't provide high-speed implementations to some reading commands (So we didn't do it at all). 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.
|
||||
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 to the flash regardless of the low-level hardware.
|
||||
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 after. Some chips need different command or value, or need special communication ways.
|
||||
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.
|
||||
|
||||
@ -222,7 +222,7 @@ The lock (see :ref:`spi_bus_lock`) is used to resolve the conflicts among the ac
|
||||
|
||||
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 requires to use the bus monopolized during a period. (especially when the device doesn't have CS wire, or the wire is controlled by the software like SDSPI driver).
|
||||
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.
|
||||
|
||||
@ -255,8 +255,8 @@ 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 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.
|
||||
- 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.
|
||||
|
||||
@ -287,4 +287,4 @@ API Reference - Partition Table
|
||||
API Reference - Flash Encrypt
|
||||
-----------------------------
|
||||
|
||||
.. include-build-file:: inc/esp_flash_encrypt.inc
|
||||
.. include-build-file:: inc/esp_flash_encrypt.inc
|
@ -35,7 +35,7 @@ Under this condition, all CPUs should always execute code and access data from i
|
||||
|
||||
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`, :ref:`spi_bus_lock`.
|
||||
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.
|
||||
|
||||
@ -55,7 +55,7 @@ If a function or symbol is not correctly put into IRAM/DRAM, and the interrupt h
|
||||
|
||||
.. note::
|
||||
|
||||
When working with string in ISRs, it is not advised to use ``printf`` and other output functions. For debugging purposes, use :c:macro:`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.
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -5,7 +5,7 @@ SPI Flash API
|
||||
|
||||
概述
|
||||
--------
|
||||
Spi_flash 组件提供外部 flash 数据读取、写入、擦除和内存映射相关的 API 函数,同时也提供了更高层级的,面向分区的 API 函数(定义在 :doc:`分区表 </api-guides/partition-tables>` 中)。
|
||||
spi_flash 组件提供外部 flash 数据读取、写入、擦除和内存映射相关的 API 函数,同时也提供了更高层级的、面向分区的 API 函数(定义在 :doc:`分区表 </api-guides/partition-tables>` 中)。
|
||||
|
||||
与 ESP-IDF V4.0 之前的 API 不同,这一版 `esp_flash_*` API 功能并不局限于主 SPI flash 芯片(即运行程序的 SPI flash 芯片)。使用不同的芯片指针,您可以访问连接到 SPI0/1 或 SPI2 总线的外部 flash 芯片。
|
||||
|
||||
@ -17,20 +17,20 @@ Spi_flash 组件提供外部 flash 数据读取、写入、擦除和内存映射
|
||||
|
||||
.. note::
|
||||
|
||||
ESP-IDF V4.0 之后的 flash API 不再是原子的。因此,如果 flash 操作地址有重叠,且写操作与读操作同时执行,读操作可能会返回一部分写入之前的数据和一部分写入之后的数据。
|
||||
ESP-IDF V4.0 之后的 flash API 不再是 *原子* 的。因此,如果读操作执行过程中发生写操作,且读操作和写操作的 flash 地址出现重叠,读操作返回的数据可能会包含旧数据和新数据 (新数据为写操作更新产生的数据)。
|
||||
|
||||
|
||||
Kconfig 选项 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL` 可将 ``spi_flash_*`` 函数切换至 ESP-IDF V4.0 之前的实现。但是,如果同时使用新旧 API,代码量可能会增多。
|
||||
|
||||
即便未启用 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL`,加密读取和加密写入操作也均使用旧实现。因此,仅有主 flash 芯片支持加密操作,外接(经 SPI1 使用其他不同片选访问,或经其它 SPI 总线访问)的 flash 芯片则不支持加密操作。也仅有主 flash 支持从 cache 当中读取,因为这是由硬件决定的。
|
||||
即使未启用 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL`,加密读取和加密写入操作也均使用旧实现。因此,仅有主 flash 芯片支持加密操作,外接(经 SPI1 使用其他不同片选访问,或经其它 SPI 总线访问)的 flash 芯片则不支持加密操作。硬件的限制也决定了仅有主 flash 支持从 cache 当中读取。
|
||||
|
||||
Flash 特性支持情况
|
||||
Flash 功能支持情况
|
||||
-----------------------------------
|
||||
|
||||
支持的 Flash 列表
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
不同厂家的 flash 特性有不同的操作方式,因此需要特殊的驱动支持。当前驱动支持大多数厂家 Flash 24 位地址范围内的快速/慢速读,以及二线模式 (DIO / DOUT),因为他们不需要任何厂家的自定义命令。
|
||||
不同厂家的 flash 特性有不同的操作方式,因此需要特殊的驱动支持。当前驱动支持大多数厂家 flash 24 位地址范围内的快速/慢速读,以及二线模式 (DIO/DOUT),因为他们不需要任何厂家的自定义命令。
|
||||
|
||||
当前驱动支持以下厂家/型号的 flash 的四线模式 (QIO/QOUT):
|
||||
|
||||
@ -62,7 +62,7 @@ Flash 可选的功能
|
||||
|
||||
- 高性能 (HPM) 模式 - 表示 flash 工作频率大于 80MHz 。
|
||||
|
||||
- flash 的私有ID (unique ID) - 表示 flash 支持它自己的 64-bits 独一无二的 ID 。
|
||||
- flash 的私有ID (unique ID) - 表示 flash 支持它自己的 64-bits 独有 ID 。
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
@ -70,7 +70,7 @@ Flash 可选的功能
|
||||
|
||||
如果您想使用这些功能,则需保证 {IDF_TARGET_NAME} 支持这些功能,且产品里所使用的 flash 芯片也要支持这些功能。请参阅 :doc:`spi_flash_optional_feature`,查看更多信息。
|
||||
|
||||
如果有需要,也可以自定义 flash 芯片驱动,参见 :doc:`spi_flash_override_driver` 。
|
||||
您也可以自定义 flash 芯片驱动。请参阅 :doc:`spi_flash_override_driver`,查看详细信息。
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
@ -80,15 +80,15 @@ Flash 可选的功能
|
||||
初始化 Flash 设备
|
||||
---------------------------
|
||||
|
||||
在使用 ``esp_flash_*`` API 之前,您需要在 SPI 总线上初始化芯片。
|
||||
在使用 ``esp_flash_*`` API 之前,您需要在 SPI 总线上初始化芯片,步骤如下:
|
||||
|
||||
1. 调用 :cpp:func:`spi_bus_initialize` 初始化 SPI 总线,此函数将初始化总线上设备间共享的资源,如 I/O、DMA 及中断等。
|
||||
1. 调用 :cpp:func:`spi_bus_initialize` 初始化 SPI 总线。此函数将初始化总线上设备间共享的资源,如 I/O、DMA、中断等。
|
||||
|
||||
2. 调用 :cpp:func:`spi_bus_add_flash_device` 将 flash 设备连接到总线上。然后分配内存,填充 ``esp_flash_t`` 结构体,同时初始化 CS I/O。
|
||||
|
||||
3. 调用 :cpp:func:`esp_flash_init` 与芯片进行通信。后续操作会依据芯片类型不同而有差异。
|
||||
|
||||
.. note:: 当前,多个 flash 芯片可连接到同一总线。但尚不支持在同一个 SPI 总线上使用 ``esp_flash_*`` 和 ``spi_device_*`` 设备。
|
||||
.. note:: 当前,已支持多个 flash 芯片连接到同一总线。
|
||||
|
||||
SPI Flash 访问 API
|
||||
--------------------
|
||||
@ -99,16 +99,16 @@ SPI Flash 访问 API
|
||||
- :cpp:func:`esp_flash_write`:将数据从 RAM 写入到 flash;
|
||||
- :cpp:func:`esp_flash_erase_region`:擦除 flash 中指定区域的数据;
|
||||
- :cpp:func:`esp_flash_erase_chip`:擦除整个 flash;
|
||||
- :cpp:func:`spi_flash_get_chip_size`:返回 menuconfig 中设置的 flash 芯片容量(以字节为单位)。
|
||||
- :cpp:func:`esp_flash_get_chip_size`:返回 menuconfig 中设置的 flash 芯片容量(以字节为单位)。
|
||||
|
||||
一般来说,请尽量避免对主 SPI flash 芯片直接使用原始 SPI flash 函数,如需对主 SPI flash 芯片进行操作,请使用 :ref:`分区专用函数 <flash-partition-apis>`。
|
||||
一般来说,请尽量避免对主 SPI flash 芯片直接使用原始 SPI flash 函数。如需对主 SPI flash 芯片进行操作,请使用 :ref:`分区专用函数 <flash-partition-apis>`。
|
||||
|
||||
SPI Flash 容量
|
||||
--------------
|
||||
|
||||
SPI flash 容量存储于引导程序镜像头部(烧录偏移量为 0x1000)的一个字段。
|
||||
SPI flash 容量由引导加载程序镜像头部(烧录偏移量为 0x1000)的一个字段进行配置。
|
||||
|
||||
默认情况下,引导程序写入 flash 时,esptool.py 将引导程序写入 flash 时,会自动检测 SPI flash 容量,同时使用正确容量更新引导程序的头部。您也可以在工程配置中设置 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。
|
||||
默认情况下,引导程序被写入 flash 时,esptool.py 会自动检测 SPI flash 容量,同时使用正确容量更新引导程序的头部。您也可以在工程配置中设置 :envvar:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。
|
||||
|
||||
如需在运行时覆盖已配置的 flash 容量,请配置 ``g_rom_flashchip`` 结构中的 ``chip_size``。``esp_flash_*`` 函数使用此容量(于软件和 ROM 中)进行边界检查。
|
||||
|
||||
@ -122,19 +122,19 @@ SPI1 Flash 并发约束
|
||||
|
||||
.. attention::
|
||||
|
||||
指令/数据 cache(用以执行固件)与 SPI1 外设(由像 SPI flash 驱动一样的驱动程序控制)共享 SPI0/1 总线。因此,在 SPI1 总线上调用 SPI flash API(包括访问主 flash)会对整个系统造成显著的影响。更多细节,参见 :doc:`spi_flash_concurrency`。
|
||||
指令/数据 cache(用以执行固件)与 SPI1 外设(由像 SPI flash 驱动一样的驱动程序控制)共享 SPI0/1 总线。因此,在 SPI1 总线上调用 SPI flash API(包括访问主 flash)会对整个系统造成显著的影响。请参阅 :doc:`spi_flash_concurrency`,查看详细信息。
|
||||
|
||||
.. _flash-partition-apis:
|
||||
|
||||
分区表 API
|
||||
-------------------
|
||||
|
||||
ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序、各种应用程序二进制文件、数据及文件系统等。请参考 :doc:`here </api-guides/partition-tables>`,查看详细信息。
|
||||
ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序、各种应用程序二进制文件、数据及文件系统等。请参阅 :doc:`分区表 </api-guides/partition-tables>`,查看详细信息。
|
||||
|
||||
该组件在 ``esp_partition.h`` 中声明了一些 API 函数,用以枚举在分区表中找到的分区,并对这些分区执行操作:
|
||||
|
||||
- :cpp:func:`esp_partition_find`:在分区表中查找特定类型的条目,返回一个不透明迭代器;
|
||||
- :cpp:func:`esp_partition_get`:返回一个结构,描述给定迭代器的分区;
|
||||
- :cpp:func:`esp_partition_get`:返回一个结构体,描述给定迭代器的分区;
|
||||
- :cpp:func:`esp_partition_next`:将迭代器移至下一个找到的分区;
|
||||
- :cpp:func:`esp_partition_iterator_release`:释放 ``esp_partition_find`` 中返回的迭代器;
|
||||
- :cpp:func:`esp_partition_find_first`:返回描述 ``esp_partition_find`` 中找到的第一个分区的结构;
|
||||
@ -156,7 +156,7 @@ SPI Flash 加密
|
||||
|
||||
{IDF_TARGET_CACHE_SIZE:default="64 KB"}
|
||||
|
||||
{IDF_TARGET_NAME} 内存硬件可以将 flash 部分区域映射到指令地址空间和数据地址空间,此映射仅用于读操作。不能通过写入 flash 映射的存储区域来改变 flash 中的内容。
|
||||
{IDF_TARGET_NAME} 的内存硬件可以将 flash 部分区域映射到指令地址空间和数据地址空间。此映射仅用于读操作,不能通过写入 flash 映射的存储区域来改变 flash 中的内容。
|
||||
|
||||
Flash 在 {IDF_TARGET_CACHE_SIZE} 页进行映射。内存映射硬件既可将 flash 映射到数据地址空间,也能映射到指令地址空间。请查看技术参考手册,了解内存映射硬件的详细信息及有关限制。
|
||||
|
||||
@ -183,7 +183,7 @@ Flash 在 {IDF_TARGET_CACHE_SIZE} 页进行映射。内存映射硬件既可将
|
||||
SPI Flash 实现
|
||||
--------------
|
||||
|
||||
``esp_flash_t`` 结构包含芯片数据和该 API 的三个重要部分:
|
||||
``esp_flash_t`` 结构体包含芯片数据和该 API 的三个重要部分:
|
||||
|
||||
1. 主机驱动,为访问芯片提供硬件支持;
|
||||
2. 芯片驱动,为不同芯片提供兼容性服务;
|
||||
@ -214,11 +214,11 @@ SPI Flash 实现
|
||||
OS 函数
|
||||
^^^^^^^^^^^^
|
||||
|
||||
OS 函数层目前提供访问锁和延迟的方法。
|
||||
OS 函数层目前支持访问锁和延迟的方法。
|
||||
|
||||
锁(见 :ref:`spi_bus_lock`)用于解决同一 SPI 总线上的设备访问和 SPI flash 芯片访问之间的冲突。例如:
|
||||
|
||||
1. 经 SPI1 总线访问 flash 芯片时,应当禁用 cache(平时用于取代码和 PSRAM 数据)。
|
||||
1. 经 SPI1 总线访问 flash 芯片时,应当禁用 cache(平时用于获取代码和 PSRAM 数据)。
|
||||
|
||||
2. 经其他总线访问 flash 芯片时,应当禁用 flash 上 SPI 主驱动器注册的 ISR 以避免冲突。
|
||||
|
||||
@ -228,6 +228,18 @@ OS 函数层目前提供访问锁和延迟的方法。
|
||||
|
||||
顶层 API 将芯片驱动和 OS 函数封装成一个完整的组件,并提供参数检查。
|
||||
|
||||
使用 OS 函数还可以在一定程度上避免在擦除大块 flash 区域时出现看门狗超时的情况。在这段时间内,CPU 将被 flash 擦除任务占用,从而阻止其他任务的执行,包括为看门狗定时器 (WDT) 供电的空闲任务。若已选中配置选项 :ref:`CONFIG_ESP_TASK_WDT_PANIC`,并且 flash 操作时间长于看门狗的超时时间,系统将重新启动。
|
||||
|
||||
不过,由于不同的 flash 芯片擦除时间不同,flash 驱动几乎无法兼容,很难完全规避超时的风险。因此,您需要格外注意这一点。请遵照以下指南:
|
||||
|
||||
1. 建议启用 :ref:`CONFIG_SPI_FLASH_YIELD_DURING_ERASE` 选项,允许调度器在擦除 flash 时进行重新调度。此外,还可以使用下列参数。
|
||||
|
||||
- 在 menuconfig 中增加 :ref:`CONFIG_SPI_FLASH_ERASE_YIELD_TICKS` 或减少 :ref:`CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS` 的时间。
|
||||
- 您也可以在 menuconfig 中增加 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 的时间以设置更长的看门狗超时周期。然而,看门狗超时周期拉长后,可能无法再检测到以前可检测到的超时。
|
||||
|
||||
2. 请注意,在进行长时间的 SPI flash 操作时,启用 :ref:`CONFIG_ESP_TASK_WDT_PANIC` 选项将会在超时时触发恐慌处理程序。不过,启用该选项也可以帮助处理应用程序中的意外异常,您可以根据实际情况决定是否需要启用这个选项。
|
||||
|
||||
3. 在开发过程中,请根据项目对擦除 flash 的具体要求和时间限制,谨慎进行 flash 操作。在配置 flash 擦除超时周期时,请在实际产品要求的基础上留出合理的冗余时间,从而提高产品的可靠性。
|
||||
|
||||
另请参考
|
||||
------------
|
||||
@ -244,7 +256,7 @@ OS 函数层目前提供访问锁和延迟的方法。
|
||||
|
||||
必须确保操作期间,两个 CPU 均未从 flash 运行代码,实现细节如下:
|
||||
- 单核模式下,SDK 在执行 flash 操作前将禁用中断或调度算法。
|
||||
- 双核模式下,实现细节较为复杂,SDK 需确保两个 CPU 均未运行 flash 代码。
|
||||
- 双核模式下,SDK 需确保两个 CPU 均未运行 flash 代码。
|
||||
|
||||
如果有 SPI flash API 在 CPU A(PRO 或 APP)上调用,它使用 ``esp_ipc_call`` API 在 CPU B 上运行 ``spi_flash_op_block_func`` 函数。``esp_ipc_call`` API 会在 CPU B 上唤醒一个高优先级任务,即运行 ``spi_flash_op_block_func`` 函数。运行该函数将禁用 CPU B 上的 cache,并使用 ``s_flash_op_can_start`` 旗帜来标志 cache 已禁用。然后,CPU A 上的任务也会禁用 cache 并继续执行 flash 操作。
|
||||
|
||||
@ -275,4 +287,4 @@ SPI Flash API 参考
|
||||
Flash 加密 API 参考
|
||||
-----------------------------
|
||||
|
||||
.. include-build-file:: inc/esp_flash_encrypt.inc
|
||||
.. include-build-file:: inc/esp_flash_encrypt.inc
|
@ -7,30 +7,40 @@ SPI1 Flash 并发约束
|
||||
|
||||
.. only:: not esp32c3
|
||||
|
||||
在 {IDF_TARGET_NAME} 上, flash 读取/写入/擦除时 cache 必须被禁用。
|
||||
在 {IDF_TARGET_NAME} 上,flash 读取/写入/擦除时 cache 必须被禁用。
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
在 {IDF_TARGET_NAME} 上,默认启用的配置选项 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 允许 flash / PSRAM 的 cache 访问和 SPI1 的操作存并发地执行。更多详情,参见 :ref:`auto-suspend` 。
|
||||
在 {IDF_TARGET_NAME} 上,默认启用的配置选项 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 允许 flash/PSRAM 的 cache 访问和 SPI1 的操作存并发地执行。请参阅 :ref:`auto-suspend`,查看详细信息。
|
||||
|
||||
在该选项被禁用的情况下,读取/写入/擦除 flash 时,cache 必须被禁用。使用驱动访问 SPI1 的相关约束参见 :ref:`impact_disabled_cache`。这些约束会带来更多的 IRAM/DRAM 消耗。
|
||||
|
||||
然而当该选项被禁用时,读取/写入/擦除 flash 时, cache 必须被禁用。使用驱动访问 SPI1 的相关约束参见 :ref:`impact_disabled_cache` 。这些约束会带来更多的 IRAM / DRAM 消耗。
|
||||
|
||||
.. _impact_disabled_cache:
|
||||
|
||||
当 cache 被禁用时
|
||||
----------------------------
|
||||
|
||||
这意味着当 flash 擦写操作发生时,所有的 CPU 都只能执行 IRAM 中的代码,而且必须从 DRAM 中读取数据。如果您使用本文档中 API 函数,上述限制将自动生效且透明(无需您额外关注),但这些限制可能会影响系统中的其他任务的性能。
|
||||
此时,在 flash 擦写操作中,所有的 CPU 都只能执行 IRAM 中的代码,而且必须从 DRAM 中读取数据。如果您使用本文档中 API 函数,上述限制将自动生效且透明(无需您额外关注),但这些限制可能会影响系统中的其他任务的性能。
|
||||
|
||||
除 SPI0/1 以外的 SPI 总线上的其它 flash 芯片则不受这种限制。
|
||||
.. only:: esp32c3
|
||||
|
||||
请参阅 :ref:`应用程序内存分布 <memory-layout>`,查看 IRAM、DRAM 和 flash cache 的区别。
|
||||
然而,启用 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 时,cache 不会被禁用,其中的操作将通过硬件来协调。
|
||||
|
||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||
|
||||
为避免意外读取 flash cache,一个 CPU 在启动 flash 写入或擦除操作时,另一个 CPU 将阻塞,并且在 flash 操作完成前,所有 CPU 上,所有的非 IRAM 安全的中断都会被禁用。
|
||||
为避免意外读取 flash cache,一个 CPU 在启动 flash 写入或擦除操作时,另一个 CPU 将阻塞。在 flash 操作完成前,所有 CPU 上,所有的非 IRAM 安全的中断都会被禁用。
|
||||
|
||||
.. only:: CONFIG_FREERTOS_UNICORE
|
||||
|
||||
为避免意外读取 flash cache,在 flash 操作完成前,所有 CPU 上,所有的非 IRAM 安全的中断都会被禁用。
|
||||
|
||||
另请参阅 :ref:`esp_flash_os_func` 和 :ref:`spi_bus_lock`。
|
||||
|
||||
除 SPI0/1 以外,SPI 总线上的其它 flash 芯片则不受这种限制。
|
||||
|
||||
请参阅 :ref:`应用程序内存分布 <memory-layout>`,查看内部 RAM(如 IRAM、DRAM)和 flash cache 的区别。
|
||||
|
||||
另请参阅 :ref:`esp_flash_os_func` 和 :ref:`spi_bus_lock` 。
|
||||
|
||||
.. _iram-safe-interrupt-handlers:
|
||||
|
||||
@ -39,37 +49,19 @@ IRAM 安全中断处理程序
|
||||
|
||||
如果您需要在 flash 操作期间运行中断处理程序(比如低延迟操作),请在 :doc:`注册中断处理程序 </api-reference/system/intr_alloc>` 时设置 ``ESP_INTR_FLAG_IRAM``。
|
||||
|
||||
请确保中断处理程序访问的所有数据和函数(包括其调用的数据和函数)都存储在 IRAM 或 DRAM 中。有两种方法可供使用:
|
||||
请确保中断处理程序访问的所有数据和函数(包括其调用的数据和函数)都存储在 IRAM 或 DRAM 中。参见 :ref:`how-to-place-code-in-iram`。
|
||||
|
||||
使用属性宏
|
||||
""""""""""""""""""""
|
||||
在函数或符号未被正确放入 IRAM/DRAM 的情况下,中断处理程序在 flash 操作期间从 flash cache 中读取数据时,会导致程序崩溃。这可能是因为代码未被正确放入 IRAM 而产生非法指令异常,也可能是因为常数未被正确放入 DRAM 而读取到垃圾数据。
|
||||
|
||||
为函数添加 ``IRAM_ATTR`` 属性::
|
||||
.. note::
|
||||
|
||||
#include "esp_attr.h"
|
||||
在 ISRs 中处理字符串时,不建议使用 `printf` 和其他输出函数。为了方便调试,在从 ISRs 中获取数据时,请使用 :cpp:func:`ESP_DRAM_LOGE` 和类似的宏。请确保 ``TAG`` 和格式字符串都放置于 ``DRAM`` 中。
|
||||
|
||||
void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
非 IRAM 安全中断处理程序
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
如果在注册时没有设置 `ESP_INTR_FLAG_IRAM` 标志,当 cache 被禁用时,将不会执行中断处理程序。一旦 cache 恢复,非 IRAM 安全的中断将重新启用,中断处理程序随即再次正常运行。这意味着,只要 cache 被禁用,将不会发生相应的硬件事件。
|
||||
|
||||
为常量添加 ``DRAM_ATTR`` 和 ``DRAM_STR`` 属性::
|
||||
|
||||
void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||
{
|
||||
const static DRAM_ATTR uint8_t INDEX_DATA[] = { 45, 33, 12, 0 };
|
||||
const static char *MSG = DRAM_STR("I am a string stored in RAM");
|
||||
}
|
||||
|
||||
辨别哪些数据应标记为 ``DRAM_ATTR`` 可能会比较困难,除非明确标记为 ``DRAM_ATTR``,否则编译器依然可能将某些变量或表达式当做常量(即便没有 ``const`` 标记),并将其放入 flash。
|
||||
|
||||
使用链接脚本
|
||||
""""""""""""""""""""""
|
||||
|
||||
参见 :doc:`/api-guides/linker-script-generation`。
|
||||
|
||||
如果函数或符号未被正确放入 IRAM/DRAM 中,当中断处理程序在 flash 操作期间从 flash cache 中读取数据,则会产生非法指令异常(这是因为代码未被正确放入 IRAM)或读取垃圾数据(这是因为常数未被正确放入 DRAM),而导致崩溃。
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user