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.

On ESP32-S2, the config options CONFIG_SPIRAM_FETCH_INSTRUCTIONS (disabled by default) and CONFIG_SPIRAM_RODATA (disabled by default) allow the cache to read/write PSRAM concurrently with SPI1 operations. See XIP from PSRAM Feature 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 When the Caches Are Disabled. These constraints will cause more IRAM/DRAM usages.

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.

Note

When CONFIG_SPIRAM_FETCH_INSTRUCTIONS and CONFIG_SPIRAM_RODATA are both enabled, these APIs won’t disable the caches.

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 OS Functions and 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 application memory layout documentation.

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 interrupt handler is registered.

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 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 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.

XIP from PSRAM Feature

If CONFIG_SPIRAM_FETCH_INSTRUCTIONS is enabled, the flash .text sections (used for instructions) will be placed in PSRAM.

If 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.