SPI Flash API

[English]

概述

SPI Flash 组件提供外部 flash 数据读取、写入、擦除和内存映射相关的 API 函数,同时也提供了更高层级的,面向分区的 API 函数(定义在 分区表 中)。

与 ESP-IDF V4.0 之前的 API 不同,这一版 API 功能并不局限于主 SPI Flash 芯片(即运行程序的 SPI Flash 芯片)。使用不同的芯片指针,您可以通过 SPI0/1 或 HSPI/VSPI 总线访问外部 flash。

注解

ESP-IDF V4.0 之后的 flash API 不再是原子的。因此,如果 flash 操作地址有重叠,且写操作与读操作同时执行,读操作可能会返回一部分写入之前的数据,返回一部分写入之后的数据。

Kconfig 选项 CONFIG_SPI_FLASH_USE_LEGACY_IMPL 可将 spi_flash_* 函数切换至 ESP-IDF V4.0 之前的实现。但是,如果同时使用新旧 API,代码量可能会增多。

即便未启用 CONFIG_SPI_FLASH_USE_LEGACY_IMPL,加密读取和加密写入操作也均使用旧实现。因此,仅有主 flash 芯片支持加密操作,其他不同片选(经 SPI1 访问的 flash 芯片)则不支持加密操作。

初始化 Flash 设备

在使用 esp_flash_* API 之前,您需要在 SPI 总线上初始化芯片。

  1. 调用 spi_bus_initialize() 初始化 SPI 总线,此函数将初始化总线上设备间共享的资源,如 I/O、DMA 及中断等。

  2. 调用 spi_bus_add_flash_device() 将 flash 设备连接到总线上。然后分配内存,填充 esp_flash_t 结构体,同时初始化 CS I/O。

  3. 调用 esp_flash_init() 与芯片进行通信。后续操作会依据芯片类型不同而有差异。

注解

目前,多个 flash 芯片可连接到同一总线。但尚不支持在同一个 SPI 总线上使用 esp_flash_*spi_device_* 设备。

SPI Flash 访问 API

如下所示为处理 flash 中数据的函数集:

一般来说,请尽量避免对主 SPI flash 芯片直接使用原始 SPI flash 函数,如需对主 SPI flash 芯片进行操作,请使用 分区专用函数

SPI Flash 容量

SPI flash 容量存储于引导程序映像头部(烧录偏移量为 0x1000)的一个字段。

默认情况下,引导程序写入 flash 时,esptool.py 将引导程序写入 flash 时,会自动检测 SPI flash 容量,同时使用正确容量更新引导程序的头部。您也可以在工程配置中设置 CONFIG_ESPTOOLPY_FLASHSIZE,生成固定的 flash 容量。

如需在运行时覆盖已配置的 flash 容量,请配置 g_rom_flashchip 结构中的 chip_sizeesp_flash_* 函数使用此容量(于软件和 ROM 中)进行边界检查。

SPI1 Flash 并发约束

由于 SPI1 flash 也被用于执行固件(通过指令 cache 或数据 cache ),因此在执行读取、写入及擦除操作时,必须禁用这些 cache。这意味着在执行 flash 写操作时,两个 CPU 必须从 IRAM 运行代码,且只能从 DRAM 中读取数据。

如果您使用本文档中 API 函数,上述限制将自动生效且透明(无需您额外关注),但这些限制可能会影响系统中的其他任务的性能。

除 SPI0/1 以外的 SPI 总线上的其它 flash 芯片则不受这种限制。

请参阅 应用程序内存分布,查看 IRAM、DRAM 和 flash cache 的区别。

为避免意外读取 flash cache,一个 CPU 在启动 flash 写入或擦除操作时,另一个 CPU 将阻塞,并且在 flash 操作完成前,两个 CPU 上的所有的非 IRAM 安全的中断都会被禁用。

IRAM 安全中断处理程序

如果您需要在 flash 操作期间运行中断处理程序(比如低延迟操作),请在 注册中断处理程序 时设置 ESP_INTR_FLAG_IRAM

请确保中断处理程序访问的所有数据和函数(包括其调用的数据和函数)都存储在 IRAM 或 DRAM 中。

为函数添加 IRAM_ATTR 属性:

#include "esp_attr.h"

void IRAM_ATTR gpio_isr_handler(void* arg)
{
    // ...
}

为常量添加 DRAM_ATTRDRAM_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。

如果函数或符号未被正确放入 IRAM/DRAM 中,当中断处理程序在 flash 操作期间从 flash cache 中读取数据,则会产生非法指令异常(这是因为代码未被正确放入 IRAM)或读取垃圾数据(这是因为常数未被正确放入 DRAM),而导致崩溃。

分区表 API

ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序、各种应用程序二进制文件、数据及文件系统等。请参考 分区表,查看详细信息。

该组件在 esp_partition.h 中声明了一些 API 函数,用以枚举在分区表中找到的分区,并对这些分区执行操作:

注解

请在应用程序代码中使用上述 esp_partition_* API 函数,而非低层级的 spi_flash_* API 函数。分区表 API 函数根据存储在分区表中的数据,进行边界检查并计算在 flash 中的正确偏移量。

SPI Flash 加密

您可以对 SPI flash 内容进行加密,并在硬件层对其进行透明解密。

请参阅 Flash 加密,查看详细信息。

内存映射 API

ESP32 内存硬件可以将 flash 部分区域映射到指令地址空间和数据地址空间,此映射仅用于读操作。不能通过写入 flash 映射的存储区域来改变 flash 中内容。

Flash 以 64 KB 页为单位进行地址映射。内存映射硬件最多可将 4 MB flash 映射到数据地址空间,将 16 MB flash 映射到指令地址空间。请参考《ESP32 技术参考手册》查看内存映射硬件的详细信息。

请注意,有些 64 KB 页还用于将应用程序映射到内存中,因此实际可用的 64 KB 页会更少一些。

Flash 加密 启用时,使用内存映射区域从 flash 读取数据是解密 flash 的唯一方法,解密需在硬件层进行。

内存映射 API 在 esp_spi_flash.hesp_partition.h 中声明:

  • spi_flash_mmap():将 flash 物理地址区域映射到 CPU 指令空间或数据空间;

  • spi_flash_munmap():取消上述区域的映射;

  • esp_partition_mmap():将分区的一部分映射至 CPU 指令空间或数据空间;

spi_flash_mmap()esp_partition_mmap() 的区别如下:

  • spi_flash_mmap():需要给定一个 64 KB 对齐的物理地址;

  • esp_partition_mmap():给定分区内任意偏移量即可,此函数根据需要将返回的指针调整至指向映射内存。

内存映射在 64 KB 块中进行,如果分区已传递给 esp_partition_mmap,则可读取分区外数据。

实现

esp_flash_t 结构包含芯片数据和该 API 的三个重要部分:

  1. 主机驱动,为访问芯片提供硬件支持;

  2. 芯片驱动,为不同芯片提供兼容性服务;

  3. OS 函数,在不同阶段(一级或二级 Boot 或者应用程序阶段)为部分 OS 函数提供支持(如一些锁、延迟)。

主机驱动

主机驱动依赖 soc/include/hal 文件夹下 spi_flash_host_drv.h 定义的 spi_flash_host_driver_t 接口。该接口提供了一些与芯片通信常用的函数。

在 SPI HAL 文件中,有些函数是基于现有的 ESP32 memory-spi 来实现的。但是,由于 ESP32 速度限制,HAL 层无法提供某些读命令的高速实现(所以这些命令根本没有在 HAL 的文件中被实现)。memspi_host_driver.h.c 文件使用 HAL 提供的 common_command 函数实现上述读命令的高速版本,并将所有它实现的及 HAL 函数封装为 spi_flash_host_driver_t 供更上层调用。

您也可以实现自己的主机驱动,甚至只通过简单的 GPIO。只要实现了 spi_flash_host_driver_t 中所有函数,不管底层硬件是什么,esp_flash API 都可以访问 flash。

芯片驱动

芯片驱动在 spi_flash_chip_driver.h 中进行定义,并将主机驱动提供的基本函数进行封装以供 API 层使用。

有些操作需在执行前先发送命令,或在执行后读取状态,因此有些芯片需要不同的命令或值以及通信方式。

generic chip 芯片代表了常见的 flash 芯片,其他芯片驱动可以在通用芯片的基础上进行开发。

芯片驱动依赖主机驱动。

OS 函数

OS 函数层提供访问锁和延迟的方法。

该锁定用于解决 SPI Flash 芯片访问和其他函数之间的冲突。例如,经 SPI0/1 访问 flash 芯片时,应当禁用 cache(平时用于取代码和 PSRAM 数据)。另一种情况是,一些没有 CS 线或者 CS 线受软件控制的设备(如通过 SPI 接口的 SD 卡控制)需要在一段时间内独占总线。

延时则用于某些长时操作,需要主机处于等待状态或执行轮询。

顶层 API 将芯片驱动和 OS 函数封装成一个完整的组件,并提供参数检查。

另请参考

  • 分区表

  • OTA API 提供了高层 API 用于更新存储在 flash 中的 app 固件。

  • NVS API 提供了结构化 API 用于存储 SPI flash 中的碎片数据。

实现细节

必须确保操作期间,两个 CPU 均未从 flash 运行代码,实现细节如下:

  • 单核模式下,SDK 在执行 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 操作。

执行 flash 操作时,CPU A 和 CPU B 仍然可以执行中断操作。默认中断代码均存储于 RAM 中,如果新添加了中断分配 API,则应添加一个标志位以请求在 flash 操作期间禁用该新分配的中断。

Flash 操作完成后,CPU A 上的函数将设置另一标志位,即 s_flash_op_complete,用以通知 CPU B 上的任务可以重新启用 cache 并释放 CPU。接着,CPU A 上的函数也重新启用 cache,并将控制权返还给调用者。

另外,所有 API 函数均受互斥量 s_flash_op_mutex 保护。

在单核环境中(启用 CONFIG_FREERTOS_UNICORE),您需要禁用上述两个 cache 以防发生 CPU 间通信。

SPI Flash API 参考

Functions

esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_device_config_t *config)

Add a SPI Flash device onto the SPI bus.

The bus should be already initialized by spi_bus_initialization.

Return

  • ESP_ERR_INVALID_ARG: out_chip is NULL, or some field in the config is invalid.

  • ESP_ERR_NO_MEM: failed to allocate memory for the chip structures.

  • ESP_OK: success.

Parameters
  • out_chip: Pointer to hold the initialized chip.

  • config: Configuration of the chips to initialize.

esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip)

Remove a SPI Flash device from the SPI bus.

Return

  • ESP_ERR_INVALID_ARG: The chip is invalid.

  • ESP_OK: success.

Parameters
  • chip: The flash device to remove.

Structures

struct esp_flash_spi_device_config_t

Configurations for the SPI Flash to init.

Public Members

spi_host_device_t host_id

Bus to use.

int cs_io_num

GPIO pin to output the CS signal.

esp_flash_io_mode_t io_mode

IO mode to read from the Flash.

esp_flash_speed_t speed

Speed of the Flash clock.

int input_delay_ns

Input delay of the data pins, in ns. Set to 0 if unknown.

int cs_id

CS line ID, ignored when not host_id is not SPI1_HOST, or CONFIG_SPI_FLASH_SHARE_SPI1_BUS is enabled. In this case, the CS line used is automatically assigned by the SPI bus lock.

Functions

esp_err_t esp_flash_init(esp_flash_t *chip)

Initialise SPI flash chip interface.

This function must be called before any other API functions are called for this chip.

Note

Only the host and read_mode fields of the chip structure must be initialised before this function is called. Other fields may be auto-detected if left set to zero or NULL.

Note

If the chip->drv pointer is NULL, chip chip_drv will be auto-detected based on its manufacturer & product IDs. See esp_flash_registered_flash_drivers pointer for details of this process.

Return

ESP_OK on success, or a flash error code if initialisation fails.

Parameters
  • chip: Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.

bool esp_flash_chip_driver_initialized(const esp_flash_t *chip)

Check if appropriate chip driver is set.

Return

true if set, otherwise false.

Parameters
  • chip: Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.

esp_err_t esp_flash_read_id(esp_flash_t *chip, uint32_t *out_id)

Read flash ID via the common “RDID” SPI flash command.

ID is a 24-bit value. Lower 16 bits of ‘id’ are the chip ID, upper 8 bits are the manufacturer ID.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • [out] out_id: Pointer to receive ID value.

Return

ESP_OK on success, or a flash error code if operation failed.

esp_err_t esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size)

Detect flash size based on flash ID.

Note

Most flash chips use a common format for flash ID, where the lower 4 bits specify the size as a power of 2. If the manufacturer doesn’t follow this convention, the size may be incorrectly detected.

Return

ESP_OK on success, or a flash error code if operation failed.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • [out] out_size: Detected size in bytes.

esp_err_t esp_flash_erase_chip(esp_flash_t *chip)

Erase flash chip contents.

Return

ESP_OK on success, or a flash error code if operation failed.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

esp_err_t esp_flash_erase_region(esp_flash_t *chip, uint32_t start, uint32_t len)

Erase a region of the flash chip.

Sector size is specifyed in chip->drv->sector_size field (typically 4096 bytes.) ESP_ERR_INVALID_ARG will be returned if the start & length are not a multiple of this size.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • start: Address to start erasing flash. Must be sector aligned.

  • len: Length of region to erase. Must also be sector aligned.

Erase is performed using block (multi-sector) erases where possible (block size is specified in chip->drv->block_erase_size field, typically 65536 bytes). Remaining sectors are erased using individual sector erase commands.

Return

ESP_OK on success, or a flash error code if operation failed.

esp_err_t esp_flash_get_chip_write_protect(esp_flash_t *chip, bool *write_protected)

Read if the entire chip is write protected.

Note

A correct result for this flag depends on the SPI flash chip model and chip_drv in use (via the ‘chip->drv’ field).

Return

ESP_OK on success, or a flash error code if operation failed.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • [out] write_protected: Pointer to boolean, set to the value of the write protect flag.

esp_err_t esp_flash_set_chip_write_protect(esp_flash_t *chip, bool write_protect)

Set write protection for the SPI flash chip.

Some SPI flash chips may require a power cycle before write protect status can be cleared. Otherwise, write protection can be removed via a follow-up call to this function.

Note

Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the ‘chip->drv’ field).

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • write_protect: Boolean value for the write protect flag

Return

ESP_OK on success, or a flash error code if operation failed.

esp_err_t esp_flash_get_protectable_regions(const esp_flash_t *chip, const esp_flash_region_t **out_regions, uint32_t *out_num_regions)

Read the list of individually protectable regions of this SPI flash chip.

Note

Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the ‘chip->drv’ field).

Return

ESP_OK on success, or a flash error code if operation failed.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • [out] out_regions: Pointer to receive a pointer to the array of protectable regions of the chip.

  • [out] out_num_regions: Pointer to an integer receiving the count of protectable regions in the array returned in ‘regions’.

esp_err_t esp_flash_get_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool *out_protected)

Detect if a region of the SPI flash chip is protected.

Note

It is possible for this result to be false and write operations to still fail, if protection is enabled for the entire chip.

Note

Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the ‘chip->drv’ field).

Return

ESP_OK on success, or a flash error code if operation failed.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • region: Pointer to a struct describing a protected region. This must match one of the regions returned from esp_flash_get_protectable_regions(…).

  • [out] out_protected: Pointer to a flag which is set based on the protected status for this region.

esp_err_t esp_flash_set_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool protect)

Update the protected status for a region of the SPI flash chip.

Note

It is possible for the region protection flag to be cleared and write operations to still fail, if protection is enabled for the entire chip.

Note

Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the ‘chip->drv’ field).

Return

ESP_OK on success, or a flash error code if operation failed.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • region: Pointer to a struct describing a protected region. This must match one of the regions returned from esp_flash_get_protectable_regions(…).

  • protect: Write protection flag to set.

esp_err_t esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length)

Read data from the SPI flash chip.

There are no alignment constraints on buffer, address or length.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • buffer: Pointer to a buffer where the data will be read. To get better performance, this should be in the DRAM and word aligned.

  • address: Address on flash to read from. Must be less than chip->size field.

  • length: Length (in bytes) of data to read.

Note

If on-chip flash encryption is used, this function returns raw (ie encrypted) data. Use the flash cache to transparently decrypt data.

Return

  • ESP_OK: success

  • ESP_ERR_NO_MEM: Buffer is in external PSRAM which cannot be concurrently accessed, and a temporary internal buffer could not be allocated.

  • or a flash error code if operation failed.

esp_err_t esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)

Write data to the SPI flash chip.

There are no alignment constraints on buffer, address or length.

Parameters
  • chip: Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()

  • address: Address on flash to write to. Must be previously erased (SPI NOR flash can only write bits 1->0).

  • buffer: Pointer to a buffer with the data to write. To get better performance, this should be in the DRAM and word aligned.

  • length: Length (in bytes) of data to write.

Return

ESP_OK on success, or a flash error code if operation failed.

esp_err_t esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length)

Encrypted and write data to the SPI flash chip using on-chip hardware flash encryption.

Note

Both address & length must be 16 byte aligned, as this is the encryption block size

Return

  • ESP_OK: on success

  • ESP_ERR_NOT_SUPPORTED: encrypted write not supported for this chip.

  • ESP_ERR_INVALID_ARG: Either the address, buffer or length is invalid.

  • or other flash error code from spi_flash_write_encrypted().

Parameters
  • chip: Pointer to identify flash chip. Must be NULL (the main flash chip). For other chips, encrypted write is not supported.

  • address: Address on flash to write to. 16 byte aligned. Must be previously erased (SPI NOR flash can only write bits 1->0).

  • buffer: Pointer to a buffer with the data to write.

  • length: Length (in bytes) of data to write. 16 byte aligned.

esp_err_t esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address, void *out_buffer, uint32_t length)

Read and decrypt data from the SPI flash chip using on-chip hardware flash encryption.

Return

  • ESP_OK: on success

  • ESP_ERR_NOT_SUPPORTED: encrypted read not supported for this chip.

  • or other flash error code from spi_flash_read_encrypted().

Parameters
  • chip: Pointer to identify flash chip. Must be NULL (the main flash chip). For other chips, encrypted read is not supported.

  • address: Address on flash to read from.

  • out_buffer: Pointer to a buffer for the data to read to.

  • length: Length (in bytes) of data to read.

static bool esp_flash_is_quad_mode(const esp_flash_t *chip)

Returns true if chip is configured for Quad I/O or Quad Fast Read.

Return

true if flash works in quad mode, otherwise false

Parameters
  • chip: Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.

Structures

struct esp_flash_region_t

Structure for describing a region of flash.

Public Members

uint32_t offset

Start address of this region.

uint32_t size

Size of the region.

struct esp_flash_os_functions_t

OS-level integration hooks for accessing flash chips inside a running OS.

It’s in the public header because some instances should be allocated statically in the startup code. May be updated according to hardware version and new flash chip feature requirements, shouldn’t be treated as public API.

For advanced developers, you may replace some of them with your implementations at your own risk.

Public Members

esp_err_t (*start)(void *arg)

Called before commencing any flash operation. Does not need to be recursive (ie is called at most once for each call to ‘end’).

esp_err_t (*end)(void *arg)

Called after completing any flash operation.

esp_err_t (*region_protected)(void *arg, size_t start_addr, size_t size)

Called before any erase/write operations to check whether the region is limited by the OS

esp_err_t (*delay_us)(void *arg, uint32_t us)

Delay for at least ‘us’ microseconds. Called in between ‘start’ and ‘end’.

void *(*get_temp_buffer)(void *arg, size_t reqest_size, size_t *out_size)

Called for get temp buffer when buffer from application cannot be directly read into/write from.

void (*release_temp_buffer)(void *arg, void *temp_buf)

Called for release temp buffer.

esp_err_t (*yield)(void *arg)

Yield to other tasks. Called during erase operations.

struct esp_flash_t

Structure to describe a SPI flash chip connected to the system.

Structure must be initialized before use (passed to esp_flash_init()). It’s in the public header because some instances should be allocated statically in the startup code. May be updated according to hardware version and new flash chip feature requirements, shouldn’t be treated as public API.

For advanced developers, you may replace some of them with your implementations at your own risk.

Public Members

spi_flash_host_inst_t *host

Pointer to hardware-specific “host_driver” structure. Must be initialized before used.

const spi_flash_chip_t *chip_drv

Pointer to chip-model-specific “adapter” structure. If NULL, will be detected during initialisation.

const esp_flash_os_functions_t *os_func

Pointer to os-specific hook structure. Call esp_flash_init_os_functions() to setup this field, after the host is properly initialized.

void *os_func_data

Pointer to argument for os-specific hooks. Left NULL and will be initialized with os_func.

esp_flash_io_mode_t read_mode

Configured SPI flash read mode. Set before esp_flash_init is called.

uint32_t size

Size of SPI flash in bytes. If 0, size will be detected during initialisation.

uint32_t chip_id

Detected chip id.

Type Definitions

typedef struct spi_flash_chip_t spi_flash_chip_t
typedef struct esp_flash_t esp_flash_t

Structures

struct spi_flash_trans_t

Definition of a common transaction. Also holds the return value.

Public Members

uint8_t command

Command to send, always 8bits.

uint8_t mosi_len

Output data length, in bytes.

uint8_t miso_len

Input data length, in bytes.

uint8_t address_bitlen

Length of address in bits, set to 0 if command does not need an address.

uint32_t address

Address to perform operation on.

const uint8_t *mosi_data

Output data to salve.

uint8_t *miso_data

[out] Input data from slave, little endian

struct spi_flash_host_inst_t

SPI Flash Host driver instance

Public Members

const struct spi_flash_host_driver_s *driver

Pointer to the implementation function table.

struct spi_flash_host_driver_s

Host driver configuration and context structure.

Public Members

esp_err_t (*dev_config)(spi_flash_host_inst_t *host)

Configure the device-related register before transactions. This saves some time to re-configure those registers when we send continuously

esp_err_t (*common_command)(spi_flash_host_inst_t *host, spi_flash_trans_t *t)

Send an user-defined spi transaction to the device.

esp_err_t (*read_id)(spi_flash_host_inst_t *host, uint32_t *id)

Read flash ID.

void (*erase_chip)(spi_flash_host_inst_t *host)

Erase whole flash chip.

void (*erase_sector)(spi_flash_host_inst_t *host, uint32_t start_address)

Erase a specific sector by its start address.

void (*erase_block)(spi_flash_host_inst_t *host, uint32_t start_address)

Erase a specific block by its start address.

esp_err_t (*read_status)(spi_flash_host_inst_t *host, uint8_t *out_sr)

Read the status of the flash chip.

esp_err_t (*set_write_protect)(spi_flash_host_inst_t *host, bool wp)

Disable write protection.

void (*program_page)(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)

Program a page of the flash. Check max_write_bytes for the maximum allowed writing length.

bool (*supports_direct_write)(spi_flash_host_inst_t *host, const void *p)

Check whether given buffer can be directly used to write

int (*write_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size)

Slicer for write data. The program_page should be called iteratively with the return value of this function.

Return

Length that can be actually written in one program_page call

Parameters
  • address: Beginning flash address to write

  • len: Length request to write

  • align_addr: Output of the aligned address to write to

  • page_size: Physical page size of the flash chip

esp_err_t (*read)(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)

Read data from the flash. Check max_read_bytes for the maximum allowed reading length.

bool (*supports_direct_read)(spi_flash_host_inst_t *host, const void *p)

Check whether given buffer can be directly used to read

int (*read_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size)

Slicer for read data. The read should be called iteratively with the return value of this function.

Return

Length that can be actually read in one read call

Parameters
  • address: Beginning flash address to read

  • len: Length request to read

  • align_addr: Output of the aligned address to read

  • page_size: Physical page size of the flash chip

bool (*host_idle)(spi_flash_host_inst_t *host)

Check whether the host is idle to perform new operations.

esp_err_t (*configure_host_io_mode)(spi_flash_host_inst_t *host, uint32_t command, uint32_t addr_bitlen, int dummy_bitlen_base, esp_flash_io_mode_t io_mode)

Configure the host to work at different read mode. Responsible to compensate the timing and set IO mode.

void (*poll_cmd_done)(spi_flash_host_inst_t *host)

Internal use, poll the HW until the last operation is done.

esp_err_t (*flush_cache)(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size)

For some host (SPI1), they are shared with a cache. When the data is modified, the cache needs to be flushed. Left NULL if not supported.

Macros

ESP_FLASH_SPEED_MIN

Lowest speed supported by the driver, currently 5 MHz.

SPI_FLASH_READ_MODE_MIN

Slowest io mode supported by ESP32, currently SlowRd.

Type Definitions

typedef struct spi_flash_host_driver_s spi_flash_host_driver_t

Enumerations

enum esp_flash_speed_t

SPI flash clock speed values, always refer to them by the enum rather than the actual value (more speed may be appended into the list).

A strategy to select the maximum allowed speed is to enumerate from the ESP_FLSH_SPEED_MAX-1 or highest frequency supported by your flash, and decrease the speed until the probing success.

Values:

ESP_FLASH_5MHZ = 0

The flash runs under 5MHz.

ESP_FLASH_10MHZ

The flash runs under 10MHz.

ESP_FLASH_20MHZ

The flash runs under 20MHz.

ESP_FLASH_26MHZ

The flash runs under 26MHz.

ESP_FLASH_40MHZ

The flash runs under 40MHz.

ESP_FLASH_80MHZ

The flash runs under 80MHz.

ESP_FLASH_SPEED_MAX

The maximum frequency supported by the host is ESP_FLASH_SPEED_MAX-1.

enum esp_flash_io_mode_t

Mode used for reading from SPI flash.

Values:

SPI_FLASH_SLOWRD = 0

Data read using single I/O, some limits on speed.

SPI_FLASH_FASTRD

Data read using single I/O, no limit on speed.

SPI_FLASH_DOUT

Data read using dual I/O.

SPI_FLASH_DIO

Both address & data transferred using dual I/O.

SPI_FLASH_QOUT

Data read using quad I/O.

SPI_FLASH_QIO

Both address & data transferred using quad I/O.

SPI_FLASH_READ_MODE_MAX

The fastest io mode supported by the host is ESP_FLASH_READ_MODE_MAX-1.

分区表 API 参考

Functions

esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_partition_subtype_t subtype, const char *label)

Find partition based on one or more parameters.

Return

iterator which can be used to enumerate all the partitions found, or NULL if no partitions were found. Iterator obtained through this function has to be released using esp_partition_iterator_release when not used any more.

Parameters
  • type: Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer

  • subtype: Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer. To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.

  • label: (optional) Partition label. Set this value if looking for partition with a specific name. Pass NULL otherwise.

const esp_partition_t *esp_partition_find_first(esp_partition_type_t type, esp_partition_subtype_t subtype, const char *label)

Find first partition based on one or more parameters.

Return

pointer to esp_partition_t structure, or NULL if no partition is found. This pointer is valid for the lifetime of the application.

Parameters
  • type: Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer

  • subtype: Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.

  • label: (optional) Partition label. Set this value if looking for partition with a specific name. Pass NULL otherwise.

const esp_partition_t *esp_partition_get(esp_partition_iterator_t iterator)

Get esp_partition_t structure for given partition.

Return

pointer to esp_partition_t structure. This pointer is valid for the lifetime of the application.

Parameters
  • iterator: Iterator obtained using esp_partition_find. Must be non-NULL.

esp_partition_iterator_t esp_partition_next(esp_partition_iterator_t iterator)

Move partition iterator to the next partition found.

Any copies of the iterator will be invalid after this call.

Return

NULL if no partition was found, valid esp_partition_iterator_t otherwise.

Parameters
  • iterator: Iterator obtained using esp_partition_find. Must be non-NULL.

void esp_partition_iterator_release(esp_partition_iterator_t iterator)

Release partition iterator.

Parameters
  • iterator: Iterator obtained using esp_partition_find. Must be non-NULL.

const esp_partition_t *esp_partition_verify(const esp_partition_t *partition)

Verify partition data.

Given a pointer to partition data, verify this partition exists in the partition table (all fields match.)

This function is also useful to take partition data which may be in a RAM buffer and convert it to a pointer to the permanent partition data stored in flash.

Pointers returned from this function can be compared directly to the address of any pointer returned from esp_partition_get(), as a test for equality.

Return

  • If partition not found, returns NULL.

  • If found, returns a pointer to the esp_partition_t structure in flash. This pointer is always valid for the lifetime of the application.

Parameters
  • partition: Pointer to partition data to verify. Must be non-NULL. All fields of this structure must match the partition table entry in flash for this function to return a successful match.

esp_err_t esp_partition_read(const esp_partition_t *partition, size_t src_offset, void *dst, size_t size)

Read data from the partition.

Partitions marked with an encryption flag will automatically be be read and decrypted via a cache mapping.

Return

ESP_OK, if data was read successfully; ESP_ERR_INVALID_ARG, if src_offset exceeds partition size; ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition; or one of error codes from lower-level flash driver.

Parameters
  • partition: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.

  • dst: Pointer to the buffer where data should be stored. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.

  • src_offset: Address of the data to be read, relative to the beginning of the partition.

  • size: Size of data to be read, in bytes.

esp_err_t esp_partition_write(const esp_partition_t *partition, size_t dst_offset, const void *src, size_t size)

Write data to the partition.

Before writing data to flash, corresponding region of flash needs to be erased. This can be done using esp_partition_erase_range function.

Partitions marked with an encryption flag will automatically be written via the spi_flash_write_encrypted() function. If writing to an encrypted partition, all write offsets and lengths must be multiples of 16 bytes. See the spi_flash_write_encrypted() function for more details. Unencrypted partitions do not have this restriction.

Note

Prior to writing to flash memory, make sure it has been erased with esp_partition_erase_range call.

Return

ESP_OK, if data was written successfully; ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size; ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition; or one of error codes from lower-level flash driver.

Parameters
  • partition: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.

  • dst_offset: Address where the data should be written, relative to the beginning of the partition.

  • src: Pointer to the source buffer. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.

  • size: Size of data to be written, in bytes.

esp_err_t esp_partition_read_raw(const esp_partition_t *partition, size_t src_offset, void *dst, size_t size)

Read data from the partition.

Note

This function is essentially the same as esp_partition_write() above. It just never decrypts data but returns it as is.

Return

ESP_OK, if data was read successfully; ESP_ERR_INVALID_ARG, if src_offset exceeds partition size; ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition; or one of error codes from lower-level flash driver.

Parameters
  • partition: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.

  • dst: Pointer to the buffer where data should be stored. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.

  • src_offset: Address of the data to be read, relative to the beginning of the partition.

  • size: Size of data to be read, in bytes.

esp_err_t esp_partition_write_raw(const esp_partition_t *partition, size_t dst_offset, const void *src, size_t size)

Write data to the partition without any transformation/encryption.

Before writing data to flash, corresponding region of flash needs to be erased. This can be done using esp_partition_erase_range function.

Note

This function is essentially the same as esp_partition_write() above. It just never encrypts data but writes it as is.

Note

Prior to writing to flash memory, make sure it has been erased with esp_partition_erase_range call.

Return

ESP_OK, if data was written successfully; ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size; ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition; or one of the error codes from lower-level flash driver.

Parameters
  • partition: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.

  • dst_offset: Address where the data should be written, relative to the beginning of the partition.

  • src: Pointer to the source buffer. Pointer must be non-NULL and buffer must be at least ‘size’ bytes long.

  • size: Size of data to be written, in bytes.

esp_err_t esp_partition_erase_range(const esp_partition_t *partition, size_t offset, size_t size)

Erase part of the partition.

Return

ESP_OK, if the range was erased successfully; ESP_ERR_INVALID_ARG, if iterator or dst are NULL; ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition; or one of error codes from lower-level flash driver.

Parameters
  • partition: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.

  • offset: Offset from the beginning of partition where erase operation should start. Must be aligned to 4 kilobytes.

  • size: Size of the range which should be erased, in bytes. Must be divisible by 4 kilobytes.

esp_err_t esp_partition_mmap(const esp_partition_t *partition, size_t offset, size_t size, spi_flash_mmap_memory_t memory, const void **out_ptr, spi_flash_mmap_handle_t *out_handle)

Configure MMU to map partition into data memory.

Unlike spi_flash_mmap function, which requires a 64kB aligned base address, this function doesn’t impose such a requirement. If offset results in a flash address which is not aligned to 64kB boundary, address will be rounded to the lower 64kB boundary, so that mapped region includes requested range. Pointer returned via out_ptr argument will be adjusted to point to the requested offset (not necessarily to the beginning of mmap-ed region).

To release mapped memory, pass handle returned via out_handle argument to spi_flash_munmap function.

Return

ESP_OK, if successful

Parameters
  • partition: Pointer to partition structure obtained using esp_partition_find_first or esp_partition_get. Must be non-NULL.

  • offset: Offset from the beginning of partition where mapping should start.

  • size: Size of the area to be mapped.

  • memory: Memory space where the region should be mapped

  • out_ptr: Output, pointer to the mapped memory region

  • out_handle: Output, handle which should be used for spi_flash_munmap call

esp_err_t esp_partition_get_sha256(const esp_partition_t *partition, uint8_t *sha_256)

Get SHA-256 digest for required partition.

For apps with SHA-256 appended to the app image, the result is the appended SHA-256 value for the app image content. The hash is verified before returning, if app content is invalid then the function returns ESP_ERR_IMAGE_INVALID. For apps without SHA-256 appended to the image, the result is the SHA-256 of all bytes in the app image. For other partition types, the result is the SHA-256 of the entire partition.

Return

  • ESP_OK: In case of successful operation.

  • ESP_ERR_INVALID_ARG: The size was 0 or the sha_256 was NULL.

  • ESP_ERR_NO_MEM: Cannot allocate memory for sha256 operation.

  • ESP_ERR_IMAGE_INVALID: App partition doesn’t contain a valid app image.

  • ESP_FAIL: An allocation error occurred.

Parameters
  • [in] partition: Pointer to info for partition containing app or data. (fields: address, size and type, are required to be filled).

  • [out] sha_256: Returned SHA-256 digest for a given partition.

bool esp_partition_check_identity(const esp_partition_t *partition_1, const esp_partition_t *partition_2)

Check for the identity of two partitions by SHA-256 digest.

Return

  • True: In case of the two firmware is equal.

  • False: Otherwise

Parameters
  • [in] partition_1: Pointer to info for partition 1 containing app or data. (fields: address, size and type, are required to be filled).

  • [in] partition_2: Pointer to info for partition 2 containing app or data. (fields: address, size and type, are required to be filled).

esp_err_t esp_partition_register_external(esp_flash_t *flash_chip, size_t offset, size_t size, const char *label, esp_partition_type_t type, esp_partition_subtype_t subtype, const esp_partition_t **out_partition)

Register a partition on an external flash chip.

This API allows designating certain areas of external flash chips (identified by the esp_flash_t structure) as partitions. This allows using them with components which access SPI flash through the esp_partition API.

Return

  • ESP_OK on success

  • ESP_ERR_NOT_SUPPORTED if CONFIG_CONFIG_SPI_FLASH_USE_LEGACY_IMPL is enabled

  • ESP_ERR_NO_MEM if memory allocation has failed

  • ESP_ERR_INVALID_ARG if the new partition overlaps another partition on the same flash chip

  • ESP_ERR_INVALID_SIZE if the partition doesn’t fit into the flash chip size

Parameters
  • flash_chip: Pointer to the structure identifying the flash chip

  • offset: Address in bytes, where the partition starts

  • size: Size of the partition in bytes

  • label: Partition name

  • type: One of the partition types (ESP_PARTITION_TYPE_*), or an integer. Note that applications can not be booted from external flash chips, so using ESP_PARTITION_TYPE_APP is not supported.

  • subtype: One of the partition subtypes (ESP_PARTITION_SUBTYPE_*), or an integer.

  • [out] out_partition: Output, if non-NULL, receives the pointer to the resulting esp_partition_t structure

esp_err_t esp_partition_deregister_external(const esp_partition_t *partition)

Deregister the partition previously registered using esp_partition_register_external.

Return

  • ESP_OK on success

  • ESP_ERR_NOT_FOUND if the partition pointer is not found

  • ESP_ERR_INVALID_ARG if the partition comes from the partition table

  • ESP_ERR_INVALID_ARG if the partition was not registered using esp_partition_register_external function.

Parameters
  • partition: pointer to the partition structure obtained from esp_partition_register_external,

Structures

struct esp_partition_t

partition information structure

This is not the format in flash, that format is esp_partition_info_t.

However, this is the format used by this API.

Public Members

esp_flash_t *flash_chip

SPI flash chip on which the partition resides

esp_partition_type_t type

partition type (app/data)

esp_partition_subtype_t subtype

partition subtype

uint32_t address

starting address of the partition in flash

uint32_t size

size of the partition, in bytes

char label[17]

partition label, zero-terminated ASCII string

bool encrypted

flag is set to true if partition is encrypted

Macros

ESP_PARTITION_SUBTYPE_OTA(i)

Convenience macro to get esp_partition_subtype_t value for the i-th OTA partition.

Type Definitions

typedef struct esp_partition_iterator_opaque_ *esp_partition_iterator_t

Opaque partition iterator type.

Enumerations

enum esp_partition_type_t

Partition type.

Note

Partition types with integer value 0x00-0x3F are reserved for partition types defined by ESP-IDF. Any other integer value 0x40-0xFE can be used by individual applications, without restriction.

Values:

ESP_PARTITION_TYPE_APP = 0x00

Application partition type.

ESP_PARTITION_TYPE_DATA = 0x01

Data partition type.

enum esp_partition_subtype_t

Partition subtype.

Application-defined partition types (0x40-0xFE) can set any numeric subtype value.

Note

These ESP-IDF-defined partition subtypes apply to partitions of type ESP_PARTITION_TYPE_APP and ESP_PARTITION_TYPE_DATA.

Values:

ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00

Factory application partition.

ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10

Base for OTA partition subtypes.

ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0

OTA partition 0.

ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1

OTA partition 1.

ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2

OTA partition 2.

ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3

OTA partition 3.

ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4

OTA partition 4.

ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5

OTA partition 5.

ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6

OTA partition 6.

ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7

OTA partition 7.

ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8

OTA partition 8.

ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9

OTA partition 9.

ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10

OTA partition 10.

ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11

OTA partition 11.

ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12

OTA partition 12.

ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13

OTA partition 13.

ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14

OTA partition 14.

ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15

OTA partition 15.

ESP_PARTITION_SUBTYPE_APP_OTA_MAX = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16

Max subtype of OTA partition.

ESP_PARTITION_SUBTYPE_APP_TEST = 0x20

Test application partition.

ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00

OTA selection partition.

ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01

PHY init data partition.

ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02

NVS partition.

ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03

COREDUMP partition.

ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04

Partition for NVS keys.

ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM = 0x05

Partition for emulate eFuse bits.

ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80

ESPHTTPD partition.

ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81

FAT partition.

ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82

SPIFFS partition.

ESP_PARTITION_SUBTYPE_ANY = 0xff

Used to search for partitions with any subtype.

Flash 加密 API 参考

Functions

static bool esp_flash_encryption_enabled(void)

Is flash encryption currently enabled in hardware?

Flash encryption is enabled if the FLASH_CRYPT_CNT efuse has an odd number of bits set.

Return

true if flash encryption is enabled.

esp_err_t esp_flash_encrypt_check_and_update(void)
esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)

Encrypt-in-place a block of flash sectors.

Note

This function resets RTC_WDT between operations with sectors.

Return

ESP_OK if all operations succeeded, ESP_ERR_FLASH_OP_FAIL if SPI flash fails, ESP_ERR_FLASH_OP_TIMEOUT if flash times out.

Parameters
  • src_addr: Source offset in flash. Should be multiple of 4096 bytes.

  • data_length: Length of data to encrypt in bytes. Will be rounded up to next multiple of 4096 bytes.

void esp_flash_write_protect_crypt_cnt(void)

Write protect FLASH_CRYPT_CNT.

Intended to be called as a part of boot process if flash encryption is enabled but secure boot is not used. This should protect against serial re-flashing of an unauthorised code in absence of secure boot.

Note

On ESP32 V3 only, write protecting FLASH_CRYPT_CNT will also prevent disabling UART Download Mode. If both are wanted, call esp_efuse_disable_rom_download_mode() before calling this function.

esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)

Return the flash encryption mode.

The API is called during boot process but can also be called by application to check the current flash encryption mode of ESP32

Return

void esp_flash_encryption_init_checks(void)

Check the flash encryption mode during startup.

Verifies the flash encryption config during startup:

Note

This function is called automatically during app startup, it doesn’t need to be called from the app.

  • Correct any insecure flash encryption settings if hardware Secure Boot is enabled.

  • Log warnings if the efuse config doesn’t match the project config in any way

Enumerations

enum esp_flash_enc_mode_t

Values:

ESP_FLASH_ENC_MODE_DISABLED
ESP_FLASH_ENC_MODE_DEVELOPMENT
ESP_FLASH_ENC_MODE_RELEASE