spi_flash: fix concurrency issue when calling esp_flash apis under xip_psram or auto_suspen

This commit is contained in:
Armando 2023-06-25 15:22:42 +08:00
parent d2e8dccd40
commit faa8c2bc8f

View File

@ -22,9 +22,13 @@
#include "esp_private/spi_common_internal.h" #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"; 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. * 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 void on_spi_yielded(app_func_arg_t* ctx);
static inline bool on_spi_check_yield(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) IRAM_ATTR static void cache_enable(void* arg)
{ {
#if !SPI_FLASH_CACHE_NO_DISABLE
spi_flash_enable_interrupts_caches_and_other_cpu(); spi_flash_enable_interrupts_caches_and_other_cpu();
#endif
} }
IRAM_ATTR static void cache_disable(void* arg) IRAM_ATTR static void cache_disable(void* arg)
{ {
#if !SPI_FLASH_CACHE_NO_DISABLE
spi_flash_disable_interrupts_caches_and_other_cpu(); 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) 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) static IRAM_ATTR esp_err_t spi1_start(void *arg)
{ {
esp_err_t ret = ESP_OK; 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 #if CONFIG_SPI_FLASH_SHARE_SPI1_BUS
//use the lock to disable the cache and interrupts before using the SPI bus //use the lock to disable the cache and interrupts before using the SPI bus
ret = spi_start(arg); ret = spi_start(arg);
#elif SPI_FLASH_CACHE_NO_DISABLE
_lock_acquire(&s_spi1_flash_mutex);
#else #else
//directly disable the cache and interrupts when lock is not used //directly disable the cache and interrupts when lock is not used
cache_disable(NULL); cache_disable(NULL);
#endif #endif
on_spi_acquired((app_func_arg_t*)arg); on_spi_acquired((app_func_arg_t*)arg);
return ESP_OK; return ret;
} }
static IRAM_ATTR esp_err_t spi1_end(void *arg) static IRAM_ATTR esp_err_t spi1_end(void *arg)
{ {
esp_err_t ret = ESP_OK; 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 #if CONFIG_SPI_FLASH_SHARE_SPI1_BUS
ret = spi_end(arg); ret = spi_end(arg);
#elif SPI_FLASH_CACHE_NO_DISABLE
_lock_release(&s_spi1_flash_mutex);
#else #else
cache_enable(NULL); cache_enable(NULL);
#endif #endif