mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
Merge branch 'bugfix/fix_spi_flash_api_concurrency_issue_v4.4' into 'release/v4.4'
spi_flash: fix concurrency issue when concurrently calling esp_flash apis (v4.4) See merge request espressif/esp-idf!24514
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -21,9 +21,13 @@
|
|||||||
|
|
||||||
#include "driver/spi_common_internal.h"
|
#include "driver/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_ELF_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.
|
||||||
*
|
*
|
||||||
@ -58,21 +62,19 @@ static inline IRAM_ATTR void on_spi1_acquired(spi1_app_func_arg_t* ctx);
|
|||||||
static inline IRAM_ATTR void on_spi1_yielded(spi1_app_func_arg_t* ctx);
|
static inline IRAM_ATTR void on_spi1_yielded(spi1_app_func_arg_t* ctx);
|
||||||
static inline IRAM_ATTR bool on_spi1_check_yield(spi1_app_func_arg_t* ctx);
|
static inline IRAM_ATTR bool on_spi1_check_yield(spi1_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
|
|
||||||
g_flash_guard_default_ops.end();
|
g_flash_guard_default_ops.end();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IRAM_ATTR static void cache_disable(void* arg)
|
IRAM_ATTR static void cache_disable(void* arg)
|
||||||
{
|
{
|
||||||
#if !SPI_FLASH_CACHE_NO_DISABLE
|
|
||||||
g_flash_guard_default_ops.start();
|
g_flash_guard_default_ops.start();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif //#if !SPI_FLASH_CACHE_NO_DISABLE
|
||||||
|
|
||||||
static IRAM_ATTR esp_err_t spi_start(void *arg)
|
static IRAM_ATTR esp_err_t acquire_spi_bus_lock(void *arg)
|
||||||
{
|
{
|
||||||
spi_bus_lock_dev_handle_t dev_lock = ((app_func_arg_t *)arg)->dev_lock;
|
spi_bus_lock_dev_handle_t dev_lock = ((app_func_arg_t *)arg)->dev_lock;
|
||||||
|
|
||||||
@ -85,29 +87,46 @@ static IRAM_ATTR esp_err_t spi_start(void *arg)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IRAM_ATTR esp_err_t spi_end(void *arg)
|
static IRAM_ATTR esp_err_t release_spi_bus_lock(void *arg)
|
||||||
{
|
{
|
||||||
return spi_bus_lock_acquire_end(((app_func_arg_t *)arg)->dev_lock);
|
return spi_bus_lock_acquire_end(((app_func_arg_t *)arg)->dev_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
return spi_start(arg);
|
ret = acquire_spi_bus_lock(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);
|
||||||
on_spi1_acquired((spi1_app_func_arg_t*)arg);
|
|
||||||
return ESP_OK;
|
|
||||||
#endif
|
#endif
|
||||||
|
on_spi1_acquired((spi1_app_func_arg_t*)arg);
|
||||||
|
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 = release_spi_bus_lock(arg);
|
||||||
|
#elif SPI_FLASH_CACHE_NO_DISABLE
|
||||||
|
_lock_release(&s_spi1_flash_mutex);
|
||||||
#else
|
#else
|
||||||
cache_enable(NULL);
|
cache_enable(NULL);
|
||||||
#endif
|
#endif
|
||||||
@ -201,8 +220,8 @@ static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functi
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
|
static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
|
||||||
.start = spi_start,
|
.start = acquire_spi_bus_lock,
|
||||||
.end = spi_end,
|
.end = release_spi_bus_lock,
|
||||||
.delay_us = delay_us,
|
.delay_us = delay_us,
|
||||||
.get_temp_buffer = get_buffer_malloc,
|
.get_temp_buffer = get_buffer_malloc,
|
||||||
.release_temp_buffer = release_buffer_malloc,
|
.release_temp_buffer = release_buffer_malloc,
|
||||||
|
Reference in New Issue
Block a user