官方文档翻译-ESP32-SPI Flash
SPI Flash
概述
The spi_flash component contains APIs related to reading, writing, erasing, memory mapping data in the external SPI flash. It also has higher-level APIs which work with partitions defined in the partition table.
spi_flash組件包含與外部SPI flash中的數據讀取,寫入,擦除和存儲器映射有關的API。它還具有更高級別的API,定義于分區表 中的高級別API可用于分區。
Note that all the functionality is limited to the “main” SPI flash chip, the same SPI flash chip from which program runs. For spi_flash_* functions, this is a software limitation. The underlying ROM functions which work with SPI flash do not have provisions for working with flash chips attached to SPI peripherals other than SPI0.
請注意,所有功能僅限于“主”SPI flash芯片,即與其運行程序相同的SPI flash 芯片。對于spi_flash_* 的功能,這是一個軟件限制。與SPI flash 配合使用的底層ROM函數沒有規定與SPI0外的其他SPI外設一起使用 flash 芯片。
SPI flash 訪問API
This is the set of APIs for working with data in flash:
這是用于處理Flash中數據的一組API:
-
spi_flash_read() used to read data from flash to RAM
-
spi_flash_write() used to write data from RAM to flash
-
spi_flash_erase_sector() used to erase individual sectors of flash
-
spi_flash_erase_range() used to erase range of addresses in flash
-
spi_flash_get_chip_size() returns flash chip size, in bytes, as configured in menuconfig
?
-
spi_flash_read() 用于從flash讀取數據到RAM
- spi_flash_write() 用于將數據從RAM寫入到flash
- spi_flash_erase_sector() 用于擦除 flash 的各個部分
- spi_flash_erase_range() 用于擦除指定地址范圍的flash
- spi_flash_get_chip_size() 返回 flash 芯片大小,以字節為單位,如menuconfig中配置
Generally, try to avoid using the raw SPI flash functions in favour of partition-specific functions.
一般來說,盡量避免使用原始的SPI flash 功能,以支持特定分區的功能。
SPI flash 大小
The SPI flash size is configured by writing a field in the software bootloader image header, flashed at offset 0x1000.
通過在軟件bootloader映像頭中寫入一個字段來配置SPI flash 大小, flash 位于偏移量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 ESPTOOLPY_FLASHSIZE in make menuconfig.
默認情況下,當將此bootloader 寫入 flash 時,esptool.py會檢測到SPI flash 大小,并使用正確的大小更新標頭。此外,可以通過在make menuconfig設置 ESPTOOLPY_FLASHSIZE 選項來修改flash大小.
If it is necessary to override the configured flash size at runtime, is is possible to set the chip_sizemember of g_rom_flashchip structure. This size is used by spi_flash_* functions (in both software & ROM) for bounds checking.
如果需要在運行時修改配置的 flash 大小,則可以設置g_rom_flashchip結構體的chip_size成員。這個大小被spi_flash_*函數(在軟件和ROM中)用于邊界檢查。
并發約束
Because the SPI flash is also used for firmware execution (via the instruction & data caches), these caches must be disabled while reading/writing/erasing. This means that both CPUs must be running code from IRAM and only reading data from DRAM while flash write operations occur.
由于SPI flash 也用于固件執行(通過指令和數據高速緩存),因此在讀/寫/擦除時必須禁用這些高速緩存。這意味著兩個CPU必須運行IRAM中的代碼,并且只能在 flash 寫操作發生時從DRAM讀取數據。
If you use the APIs documented here, then this happens automatically and transparently. However note that it will have some performance impact on other tasks in the system.
如果您使用這里記錄的API,那么這會自動地發生。但請注意,它會對系統中的其他任務產生一些性能影響。
Refer to the application memory layout documentation for an explanation of the differences between IRAM, DRAM and flash cache.
有關IRAM,DRAM和 flash 緩存之間差異的說明,請參閱應用程序內存布局文檔。
To avoid reading flash cache accidentally, when one CPU commences a flash write or erase operation the other CPU is put into a blocked state and all non-IRAM-safe interrupts are disabled on both CPUs, until the flash operation completes.
為避免意外讀取 flash 緩存,當一個CPU開始 flash 寫入或擦除操作時,另一個CPU將進入阻塞狀態,并且在兩個CPU上禁用所有非IRAM安全(non-IRAM-safe)的中斷,直到 flash 操作完成。
IRAM安全(IRAM-Safe)中斷處理程序
If you have an interrupt handler that you want to execute even when a flash operation is in progress (for example, for low latency operations), set the ESP_INTR_FLAG_IRAM flag when the interrupt handler is registered.
如果您有一個即使在進行 flash 操作時也要執行的中斷處理程序(例如,需要低延遲的操作),請在注冊中斷處理程序時設置ESP_INTR_FLAG_IRAM標志。
You must ensure all data and functions accessed by these interrupt handlers are located in IRAM or DRAM. This includes any functions that the handler calls.
您必須確保這些中斷處理程序訪問的所有數據和功能位于IRAM或DRAM中。這包括處理程序調用的任何函數。
Use the IRAM_ATTR attribute for functions:
使用該IRAM_ATTR屬性的功能:
#include "esp_attr.h"void IRAM_ATTR gpio_isr_handler(void* arg) {// ... }- 1
- 2
- 3
- 4
- 5
- 6
- 7
Use the DRAM_ATTR and DRAM_STR attributes for constant data:
使用常量數據的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"); }- 1
- 2
- 3
- 4
- 5
- 6
Note that knowing which data should be marked with DRAM_ATTR can be hard, the compiler will sometimes recognise that a variable or expression is constant (even if it is not marked const) and optimise it into flash, unless it is marked with DRAM_ATTR.
請注意,知道應該標記哪些數據為DRAM_ATTR可能很難,編譯器有時會認為變量或表達式是恒定(constant )的(即使未標記const),并將其優化為Flash,除非標記為DRAM_ATTR。
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).
如果函數或符號未正確放入IRAM / DRAM中并且中斷處理程序在 flash 操作期間從 flash 緩存中讀取,則會由于非法指令異常(對于應該在IRAM中的代碼)或讀取垃圾數據(對于應該在DRAM中的常數數據)而導致崩潰。
分區表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 about partition tables can be found here.
ESP-IDF項目使用分區表來維護有關SPI flash 各個區域(bootloader ,各種應用程序二進制文件,數據,文件系統)的信息。有關分區表的更多信息可以在這里找到。
This component provides APIs to enumerate partitions found in the partition table and perform operations on them. These functions are declared in esp_partition.h:
該組件提供了API來枚舉在分區表中找到的分區并對它們執行操作。這些函數聲明于esp_partition.h:
- esp_partition_find() used to search partition table for entries with specific type, returns an opaque iterator
- esp_partition_get() returns a structure describing the partition, for the given iterator
- esp_partition_next() advances iterator to the next partition found
- esp_partition_iterator_release() releases iterator returned by esp_partition_find
- esp_partition_find_first() is a convenience function which returns structure describing the first partition found by esp_partition_find
-
esp_partition_read(), esp_partition_write(), esp_partition_erase_range() are equivalent to spi_flash_read(), spi_flash_write(), spi_flash_erase_range(), but operate within partition boundaries
-
esp_partition_find() 用于在分區表中搜索具有特定類型的條目,并返回一個不透明的迭代器
- esp_partition_get() 返回給定迭代器的描述的分區結構
- esp_partition_next() 獲取下一個分區
- esp_partition_iterator_release() 釋放由 esp_partition_find返回的迭代器
- esp_partition_find_first() 是一個方便的函數,它返回 esp_partition_find 找到的第一個分區的結構描述
- esp_partition_read(),esp_partition_write(),esp_partition_erase_range() 等同于spi_flash_read(),spi_flash_write(), spi_flash_erase_range(),但在分區邊界內操作
注意
Most application code should use these esp_partition_* APIs instead of lower level spi_flash_*APIs. Partition APIs do bounds checking and calculate correct offsets in flash based on data stored in partition table.
大多數應用程序代碼應該使用這些esp_partition_*API而不是較低級別的 spi_flash_*API。分區(Partition )API根據存儲在分區表中的數據進行邊界檢查并計算 flash 中的正確偏移量。
SPI Flash加密
It is possible to encrypt SPI flash contents, and have it transparenlty decrypted by hardware.
可以對SPI flash 內容進行加密,并通過硬件進行透明解密。
Refer to the Flash Encryption documentation for more details.
有關更多詳細信息,請參閱Flash Encryption文檔。
內存映射API
ESP32 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 mapped memory region. Mapping happens in 64KB pages. Memory mapping hardware can map up to 4 megabytes of flash into data address space, and up to 16 megabytes of flash into instruction address space. See the technical reference manual for more details about memory mapping hardware.
ESP32具有內存硬件,可以將 flash 區域映射到指令和數據地址空間。此映射僅適用于讀取操作,不可能通過寫入映射的內存區域來修改 flash 的內容。映射發生在64KB頁面中。內存映射硬件可以將最多4兆字節的 flash 映射到數據地址空間,并將最多16兆字節的 flash 映射到指令地址空間。有關內存映射硬件的更多詳細信息,請參閱技術參考手冊。
Note that some number of 64KB pages is used to map the application itself into memory, so the actual number of available 64KB pages may be less.
請注意,一些64KB頁面用于將應用程序本身映射到內存中,因此可用64KB頁面的實際數量可能會更少。
Reading data from flash using a memory mapped region is the only way to decrypt contents of flash when flash encryption is enabled. Decryption is performed at hardware level.
使用內存映射區從 flash 讀取數據是啟用 flash 加密時解密 flash 內容的唯一方法。解密是在硬件級別執行的。
Memory mapping APIs are declared in esp_spi_flash.h and esp_partition.h:
內存映射API在esp_spi_flash.h和esp_partition.h中聲明:
- spi_flash_mmap() maps a region of physical flash addresses into instruction space or data space of the CPU
- spi_flash_munmap() unmaps previously mapped region
-
esp_partition_mmap() maps part of a partition into the instruction space or data space of the CPU
-
spi_flash_mmap() 將物理 flash 地址的區域映射到CPU的指令空間或數據空間
- spi_flash_munmap() 取消映射先前映射的區域
- esp_partition_mmap() 將分區的一部分映射到CPU的指令空間或數據空間
Differences between spi_flash_mmap() and esp_partition_mmap() are as follows:
spi_flash_mmap()和esp_partition_mmap()之間的差異如下:
- spi_flash_mmap() must be given a 64KB aligned physical address
-
esp_partition_mmap() may be given any arbitrary offset within the partition, it will adjust returned pointer to mapped memory as necessary
-
spi_flash_mmap() 必須給予一個64KB的對齊物理地址
- esp_partition_mmap() 可能會在分區內給出任意偏移量,它會根據需要調整返回的指向映射內存的指針
Note that because memory mapping happens in 64KB blocks, it may be possible to read data outside of the partition provided to esp_partition_mmap.
請注意,由于內存映射發生在64KB塊中,因此可能會讀取esp_partition_mmap提供的分區以外的數據。
也可以看看
- Partition Table documentation
- Over The Air Update (OTA) API provides high-level API for updating app firmware stored in flash.
-
Non-Volatile Storage (NVS) API provides a structured API for storing small items of data in SPI flash.
-
分區表文檔
- Over The Air Update(OTA)API提供了用于更新存儲在 flash 中的應用程序固件的高級API。
- 非易失性存儲(NVS)API提供了一個結構化API,用于在SPI flash 中存儲小數據。
細節實現
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.
為了執行一些 flash 操作,我們需要確保兩個CPU在 flash 操作期間沒有從 flash 中運行任何代碼。在單核設置中,這很簡單:我們禁用中斷/調度程序并執行 flash 操作。在雙核心設置中,這稍微復雜一些。我們需要確保另一個CPU不會從 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.
當在CPU A上調用SPI Flash API(可以是PRO或APP)時,我們使用 esp_ipc_call API在CPU B上啟動 spi_flash_op_block_func 函數。這個API喚醒了CPU B的高優先級任務,并告訴它執行給定的函數,在這種情況下是執行 spi_flash_op_block_func 。此功能禁用CPU B上的高速緩存,并通過設置 s_flash_op_can_start 標志指示緩存被禁用。然后,CPU A上的任務也會禁用緩存,然后繼續執行Flash操作。
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.
在 flash 操作正在運行時,中斷仍然可以在CPU A和B上運行。我們假定所有的中斷代碼都被放入RAM中。一旦添加了中斷分配API,我們應該添加一個標志來請求在 flash 操作期間禁用中斷。
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.
一旦 flash 操作完成,CPU A上的功能會設置另一個標志 s_flash_op_complete ,讓CPU B上的任務知道它可以重新啟用緩存并釋放CPU。然后,CPU A上的功能也重新啟用CPU A上的緩存,并將控制權返回給調用代碼。
Additionally, all API functions are protected with a mutex (s_flash_op_mutex).
此外,所有的API函數都被一個互斥鎖保護(s_flash_op_mutex)。
In a single core environment (CONFIG_FREERTOS_UNICORE enabled), we simply disable both caches, no inter-CPU communication takes place.
在單核心環境中(啟用 CONFIG_FREERTOS_UNICORE ),我們只需禁用兩個高速緩存,就不會發生CPU間通信。
API參考 - SPI Flash
頭文件
- spi_flash /包含/ esp_spi_flash.h
此文翻譯自:http://esp-idf.readthedocs.io/en/latest/api-reference/storage/spi_flash.html
內容參照google翻譯,有些部分翻譯不準確請參照原文理解
?
總結
以上是生活随笔為你收集整理的官方文档翻译-ESP32-SPI Flash的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 官方文档翻译-ESP32-High Re
- 下一篇: ESP8266/ESP32 NVS 基本