From 0e6d3aa9cd9cf5b14e13644637a14f5c83bd1427 Mon Sep 17 00:00:00 2001 From: Armando Date: Sun, 25 Jun 2023 15:22:42 +0800 Subject: [PATCH] spi_flash: fix concurrency issue when calling esp_flash apis under xip_psram or auto_suspen --- components/spi_flash/spi_flash_os_func_app.c | 30 ++++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index 63aa0796b3..352afee455 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/components/spi_flash/spi_flash_os_func_app.c @@ -22,9 +22,13 @@ #include "esp_private/spi_common_internal.h" -#define SPI_FLASH_CACHE_NO_DISABLE (CONFIG_SPI_FLASH_AUTO_SUSPEND || (CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA)) +#define SPI_FLASH_CACHE_NO_DISABLE (CONFIG_SPI_FLASH_AUTO_SUSPEND || (CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA) || CONFIG_APP_BUILD_TYPE_RAM) static const char TAG[] = "spi_flash"; +#if SPI_FLASH_CACHE_NO_DISABLE +static _lock_t s_spi1_flash_mutex; +#endif // #if SPI_FLASH_CACHE_NO_DISABLE + /* * OS functions providing delay service and arbitration among chips, and with the cache. * @@ -55,19 +59,17 @@ static inline void on_spi_acquired(app_func_arg_t* ctx); static inline void on_spi_yielded(app_func_arg_t* ctx); static inline bool on_spi_check_yield(app_func_arg_t* ctx); +#if !SPI_FLASH_CACHE_NO_DISABLE IRAM_ATTR static void cache_enable(void* arg) { -#if !SPI_FLASH_CACHE_NO_DISABLE spi_flash_enable_interrupts_caches_and_other_cpu(); -#endif } IRAM_ATTR static void cache_disable(void* arg) { -#if !SPI_FLASH_CACHE_NO_DISABLE spi_flash_disable_interrupts_caches_and_other_cpu(); -#endif } +#endif //#if !SPI_FLASH_CACHE_NO_DISABLE static IRAM_ATTR esp_err_t spi_start(void *arg) { @@ -102,22 +104,38 @@ static IRAM_ATTR esp_err_t spi23_end(void *arg){ static IRAM_ATTR esp_err_t spi1_start(void *arg) { esp_err_t ret = ESP_OK; + /** + * There are three ways for ESP Flash API lock: + * 1. spi bus lock, this is used when SPI1 is shared with GPSPI Master Driver + * 2. mutex, this is used when the Cache isn't need to be disabled. + * 3. cache lock (from cache_utils.h), this is used when we need to disable Cache to avoid access from SPI0 + * + * From 1 to 3, the lock efficiency decreases. + */ #if CONFIG_SPI_FLASH_SHARE_SPI1_BUS //use the lock to disable the cache and interrupts before using the SPI bus ret = spi_start(arg); +#elif SPI_FLASH_CACHE_NO_DISABLE + _lock_acquire(&s_spi1_flash_mutex); #else //directly disable the cache and interrupts when lock is not used cache_disable(NULL); #endif on_spi_acquired((app_func_arg_t*)arg); - return ESP_OK; + return ret; } static IRAM_ATTR esp_err_t spi1_end(void *arg) { esp_err_t ret = ESP_OK; + + /** + * There are three ways for ESP Flash API lock, see `spi1_start` + */ #if CONFIG_SPI_FLASH_SHARE_SPI1_BUS ret = spi_end(arg); +#elif SPI_FLASH_CACHE_NO_DISABLE + _lock_release(&s_spi1_flash_mutex); #else cache_enable(NULL); #endif