# SPI0/1 上 Flash 的并发约束

[中文]

SPI0/1 总线在缓存和 SPI1 外设（由包括此 SPI Flash 驱动在内的驱动程序控制）之间共享。对 SPI1 的操作可能会对缓存以及整个系统造成重大影响。连接到其他 SPI 总线的 flash 芯片没有此类约束和影响，不在本文档的讨论范围中。

SPI0/1 总线上可能发生三种活动：

- Flash 写入操作（通过 SPI1）。例如，擦除、页面编程或状态寄存器写入命令（例如，`SE`、`PP` 和 `WRSR`）。在这些命令期间，flash 处于不可读状态。CPU 和缓存必须等待直到写入命令完成。以下 API 可以触发写入命令：

  > - 调用非加密 SPI flash 写入 API（`esp_flash_write()`、`esp_flash_erase_region()` 等）

  > - 调用 `esp_flash_write_encrypted()`

- 短操作（通过 SPI1，包括非写入 flash 命令）。以下 API 可以触发短操作：

  > - 调用非加密 SPI flash 读取 API（`esp_flash_read()` 等）

  > - 或 SPI1 总线上的其他驱动程序用于用户定义的 SPI 操作（启用实验性功能 CONFIG_SPI_FLASH_SHARE_SPI1_BUS）

- 缓存读取（通过 SPI0）。以下 API 和操作可以触发缓存读取：

  > - 从 SPI Flash 或 PSRAM 执行代码

  > - 从 SPI Flash 或 PSRAM 获取 .data/.rodata/.bss 段的静态数据

  > - 通过堆或 esp_himem 对 PSRAM 的所有其他读/写操作

  > - 从映射到 SPI Flash 的区域读取，包括：

  >   > - 类似 mmap 的函数：`spi_flash_mmap()`、`spi_flash_mmap_pages()`、`esp_mmu_map()`、`bootloader_mmap()` 和 `esp_partition_mmap()`。

  >   > - 依赖 `spi_flash_mmap()` 的函数：`esp_partition_find()`、`esp_partition_register_external()`。

  >   > - 加密 flash 读/写 API：`esp_flash_read_encrypted()` 和 `esp_flash_write_encrypted()` （在 esp32 上，或用于数据验证）。

在所有 SPI1 操作期间缓存会被禁用，因此无法访问 Flash/PSRAM，大多数任务将被禁用。有关更多详细信息，请参阅 缓存禁用（默认）。

有关软件实现的详细信息，请参阅 OS 函数 和 SPI 总线锁。

## 缓存禁用（默认）

在 SPI1 操作期间缓存会被禁用。所有 SPI1 操作将自动透明地禁用缓存。

当禁用缓存时，所有非 IRAM 安全的中断将被禁用，所有其他任务将被暂停。另一个核心将在一个忙循环中空转。只有 IRAM 安全的中断处理程序将被执行。这些将在 Flash 操作完成时恢复。

有关如何在禁用缓存时防止中断处理程序被禁用的信息，请参阅 IRAM 安全中断处理程序。

当禁用缓存时，所有 CPU 应该只从内部 RAM 执行代码和访问数据。有关内部 RAM（例如，IRAM、DRAM）和 flash 缓存之间的差异，请参阅 应用程序内存布局 文档。

### IRAM 安全中断处理程序

如果需要在 flash 操作期间运行中断处理程序（比如低延迟操作），请在 注册中断处理程序 时设置 `ESP_INTR_FLAG_IRAM`。

请确保中断处理程序访问的所有数据和函数（包括其调用的数据和函数）都存储在 IRAM 或 DRAM 中。参见 如何将代码放入 IRAM。

在未将函数或符号正确放入 IRAM/DRAM 的情况下，在 flash 操作期间，中断处理程序从 flash cache 中读取数据时，会导致程序崩溃。这可能是因为代码未正确放入 IRAM，产生了非法指令异常，也可能是因为常数未正确放入 DRAM，读取到了垃圾数据。

备注

在 ISRs 中处理字符串时，不建议使用 `printf` 和其他输出函数。为了方便调试，在从 ISRs 中获取数据时，请使用 `ESP_DRAM_LOGE()` 和类似的宏。请确保 `TAG` 和格式字符串都放置于 `DRAM` 中。

### 非 IRAM 安全中断处理程序

如果在注册时没有设置 `ESP_INTR_FLAG_IRAM` 标志，当禁用 cache 时，将不会执行中断处理程序。一旦 cache 恢复，非 IRAM 安全的中断将重新启用，中断处理程序随即再次正常运行。这意味着，只要禁用了 cache，就不会发生相应的硬件事件。

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。