spi: implement yield for spi2 and spi3

add: yield functions for spi2 and spi3
add: spi23 start and end functions
change: function names with spi1 that were not specific to spi1
change: chip data for spi2 and spi3 increased for timestamps
change: merge spi_app_func_arg_t into app_func_arg_t
change: moved os_func_data allocation before host check
This commit is contained in:
Matus Fabo
2022-07-25 04:21:02 +02:00
committed by BOT
parent c948a70895
commit 1b747867bd

View File

@@ -32,10 +32,6 @@ static const char TAG[] = "spi_flash";
* into the IRAM,and their data should be put into the DRAM. * into the IRAM,and their data should be put into the DRAM.
*/ */
typedef struct {
spi_bus_lock_dev_handle_t dev_lock;
} app_func_arg_t;
/* /*
* Time yield algorithm: * Time yield algorithm:
* Every time spi_flash_os_check_yield() is called: * Every time spi_flash_os_check_yield() is called:
@@ -48,16 +44,16 @@ typedef struct {
* counter mentioned in #2, but still be counted into the time mentioned in #2. * counter mentioned in #2, but still be counted into the time mentioned in #2.
*/ */
typedef struct { typedef struct {
app_func_arg_t common_arg; //shared args, must be the first item spi_bus_lock_dev_handle_t dev_lock;
bool no_protect; //to decide whether to check protected region (for the main chip) or not. bool no_protect; //to decide whether to check protected region (for the main chip) or not.
uint32_t acquired_since_us; // Time since last explicit yield() uint32_t acquired_since_us; // Time since last explicit yield()
uint32_t released_since_us; // Time since last end() (implicit yield) uint32_t released_since_us; // Time since last end() (implicit yield)
} spi1_app_func_arg_t; } app_func_arg_t;
static inline void on_spi1_released(spi1_app_func_arg_t* ctx); static inline void on_spi_released(app_func_arg_t* ctx);
static inline void on_spi1_acquired(spi1_app_func_arg_t* ctx); static inline void on_spi_acquired(app_func_arg_t* ctx);
static inline void on_spi1_yielded(spi1_app_func_arg_t* ctx); static inline void on_spi_yielded(app_func_arg_t* ctx);
static inline bool on_spi1_check_yield(spi1_app_func_arg_t* ctx); static inline bool on_spi_check_yield(app_func_arg_t* ctx);
IRAM_ATTR static void cache_enable(void* arg) IRAM_ATTR static void cache_enable(void* arg)
{ {
@@ -91,6 +87,18 @@ static IRAM_ATTR esp_err_t spi_end(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 spi23_start(void *arg){
esp_err_t ret = spi_start(arg);
on_spi_acquired((app_func_arg_t*)arg);
return ret;
}
static IRAM_ATTR esp_err_t spi23_end(void *arg){
esp_err_t ret = spi_end(arg);
on_spi_released((app_func_arg_t*)arg);
return ret;
}
static IRAM_ATTR esp_err_t spi1_start(void *arg) static IRAM_ATTR esp_err_t spi1_start(void *arg)
{ {
#if CONFIG_SPI_FLASH_SHARE_SPI1_BUS #if CONFIG_SPI_FLASH_SHARE_SPI1_BUS
@@ -99,7 +107,7 @@ static IRAM_ATTR esp_err_t spi1_start(void *arg)
#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); on_spi_acquired((app_func_arg_t*)arg);
return ESP_OK; return ESP_OK;
#endif #endif
} }
@@ -112,17 +120,17 @@ static IRAM_ATTR esp_err_t spi1_end(void *arg)
#else #else
cache_enable(NULL); cache_enable(NULL);
#endif #endif
on_spi1_released((spi1_app_func_arg_t*)arg); on_spi_released((app_func_arg_t*)arg);
return ret; return ret;
} }
static IRAM_ATTR esp_err_t spi1_flash_os_check_yield(void *arg, uint32_t chip_status, uint32_t* out_request) static IRAM_ATTR esp_err_t spi_flash_os_check_yield(void *arg, uint32_t chip_status, uint32_t* out_request)
{ {
assert (chip_status == 0); //TODO: support suspend assert (chip_status == 0); //TODO: support suspend
esp_err_t ret = ESP_ERR_TIMEOUT; //Nothing happened esp_err_t ret = ESP_ERR_TIMEOUT; //Nothing happened
uint32_t request = 0; uint32_t request = 0;
if (on_spi1_check_yield((spi1_app_func_arg_t *)arg)) { if (on_spi_check_yield((app_func_arg_t *)arg)) {
request = SPI_FLASH_YIELD_REQ_YIELD; request = SPI_FLASH_YIELD_REQ_YIELD;
ret = ESP_OK; ret = ESP_OK;
} }
@@ -132,7 +140,7 @@ static IRAM_ATTR esp_err_t spi1_flash_os_check_yield(void *arg, uint32_t chip_st
return ret; return ret;
} }
static IRAM_ATTR esp_err_t spi1_flash_os_yield(void *arg, uint32_t* out_status) static IRAM_ATTR esp_err_t spi_flash_os_yield(void *arg, uint32_t* out_status)
{ {
if (likely(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)) { if (likely(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)) {
#ifdef CONFIG_SPI_FLASH_ERASE_YIELD_TICKS #ifdef CONFIG_SPI_FLASH_ERASE_YIELD_TICKS
@@ -141,7 +149,7 @@ static IRAM_ATTR esp_err_t spi1_flash_os_yield(void *arg, uint32_t* out_status)
vTaskDelay(1); vTaskDelay(1);
#endif #endif
} }
on_spi1_yielded((spi1_app_func_arg_t*)arg); on_spi_yielded((app_func_arg_t*)arg);
return ESP_OK; return ESP_OK;
} }
@@ -179,7 +187,7 @@ static IRAM_ATTR void release_buffer_malloc(void* arg, void *temp_buf)
static IRAM_ATTR esp_err_t main_flash_region_protected(void* arg, size_t start_addr, size_t size) static IRAM_ATTR esp_err_t main_flash_region_protected(void* arg, size_t start_addr, size_t size)
{ {
if (((spi1_app_func_arg_t*)arg)->no_protect || esp_partition_main_flash_region_safe(start_addr, size)) { if (((app_func_arg_t*)arg)->no_protect || esp_partition_main_flash_region_safe(start_addr, size)) {
//ESP_OK = 0, also means protected==0 //ESP_OK = 0, also means protected==0
return ESP_OK; return ESP_OK;
} else { } else {
@@ -194,7 +202,7 @@ static IRAM_ATTR void main_flash_op_status(uint32_t op_status)
spi_flash_set_erasing_flag(is_erasing); spi_flash_set_erasing_flag(is_erasing);
} }
static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {}; static DRAM_ATTR app_func_arg_t main_flash_arg = {};
//for SPI1, we have to disable the cache and interrupts before using the SPI bus //for SPI1, we have to disable the cache and interrupts before using the SPI bus
static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functions = { static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functions = {
@@ -204,8 +212,8 @@ static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functi
.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,
.check_yield = spi1_flash_os_check_yield, .check_yield = spi_flash_os_check_yield,
.yield = spi1_flash_os_yield, .yield = spi_flash_os_yield,
#if CONFIG_SPI_FLASH_BROWNOUT_RESET #if CONFIG_SPI_FLASH_BROWNOUT_RESET
.set_flash_op_status = main_flash_op_status, .set_flash_op_status = main_flash_op_status,
#else #else
@@ -214,14 +222,14 @@ 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 = spi23_start,
.end = spi_end, .end = spi23_end,
.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,
.region_protected = NULL, .region_protected = NULL,
.check_yield = NULL, .check_yield = spi_flash_os_check_yield,
.yield = NULL, .yield = spi_flash_os_yield,
.set_flash_op_status = NULL, .set_flash_op_status = NULL,
}; };
@@ -243,22 +251,16 @@ esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id, spi_bus_lo
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
switch (host_id) chip->os_func_data = heap_caps_malloc(sizeof(app_func_arg_t),
{
case SPI1_HOST:
//SPI1
chip->os_func = &esp_flash_spi1_default_os_functions;
chip->os_func_data = heap_caps_malloc(sizeof(spi1_app_func_arg_t),
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (chip->os_func_data == NULL) { if (chip->os_func_data == NULL) {
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
*(spi1_app_func_arg_t*) chip->os_func_data = (spi1_app_func_arg_t) {
.common_arg = { switch (host_id) {
.dev_lock = dev_handle, case SPI1_HOST:
}, //SPI1
.no_protect = true, chip->os_func = &esp_flash_spi1_default_os_functions;
};
break; break;
case SPI2_HOST: case SPI2_HOST:
#if SOC_SPI_PERIPH_NUM > 2 #if SOC_SPI_PERIPH_NUM > 2
@@ -266,17 +268,16 @@ esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id, spi_bus_lo
#endif #endif
//SPI2, SPI3 //SPI2, SPI3
chip->os_func = &esp_flash_spi23_default_os_functions; chip->os_func = &esp_flash_spi23_default_os_functions;
chip->os_func_data = heap_caps_malloc(sizeof(app_func_arg_t), break;
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); default:
if (chip->os_func_data == NULL) { return ESP_ERR_INVALID_ARG;
return ESP_ERR_NO_MEM; break;
} }
*(app_func_arg_t*) chip->os_func_data = (app_func_arg_t) { *(app_func_arg_t*) chip->os_func_data = (app_func_arg_t) {
.dev_lock = dev_handle, .dev_lock = dev_handle,
.no_protect = true, // This is OK because this code path isn't used for the main flash chip which requires `no_protect = false`
}; };
break;
default: return ESP_ERR_INVALID_ARG;
}
return ESP_OK; return ESP_OK;
} }
@@ -314,10 +315,8 @@ esp_err_t esp_flash_init_main_bus_lock(void)
esp_err_t esp_flash_app_enable_os_functions(esp_flash_t* chip) esp_err_t esp_flash_app_enable_os_functions(esp_flash_t* chip)
{ {
main_flash_arg = (spi1_app_func_arg_t) { main_flash_arg = (app_func_arg_t) {
.common_arg = { .dev_lock = g_spi_lock_main_flash_dev,
.dev_lock = g_spi_lock_main_flash_dev, //for SPI1,
},
.no_protect = false, .no_protect = false,
}; };
chip->os_func = &esp_flash_spi1_default_os_functions; chip->os_func = &esp_flash_spi1_default_os_functions;
@@ -331,11 +330,11 @@ esp_err_t esp_flash_app_enable_os_functions(esp_flash_t* chip)
// Valid task execution interval: continuous time with the cache enabled, which is longer than // Valid task execution interval: continuous time with the cache enabled, which is longer than
// CONFIG_SPI_FLASH_ERASE_YIELD_TICKS. Yield time shorter than CONFIG_SPI_FLASH_ERASE_YIELD_TICKS is // CONFIG_SPI_FLASH_ERASE_YIELD_TICKS. Yield time shorter than CONFIG_SPI_FLASH_ERASE_YIELD_TICKS is
// not treated as valid interval. // not treated as valid interval.
static inline IRAM_ATTR bool on_spi1_check_yield(spi1_app_func_arg_t* ctx) static inline IRAM_ATTR bool on_spi_check_yield(app_func_arg_t* ctx)
{ {
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
uint32_t time = esp_system_get_time(); uint32_t time = esp_system_get_time();
// We handle the reset here instead of in `on_spi1_acquired()`, when acquire() and release() is // We handle the reset here instead of in `on_spi_acquired()`, when acquire() and release() is
// larger than CONFIG_SPI_FLASH_ERASE_YIELD_TICKS, to save one `esp_system_get_time()` call // larger than CONFIG_SPI_FLASH_ERASE_YIELD_TICKS, to save one `esp_system_get_time()` call
if ((time - ctx->released_since_us) >= CONFIG_SPI_FLASH_ERASE_YIELD_TICKS * portTICK_PERIOD_MS * 1000) { if ((time - ctx->released_since_us) >= CONFIG_SPI_FLASH_ERASE_YIELD_TICKS * portTICK_PERIOD_MS * 1000) {
// Reset the acquired time as if the yield has just happened. // Reset the acquired time as if the yield has just happened.
@@ -346,22 +345,22 @@ static inline IRAM_ATTR bool on_spi1_check_yield(spi1_app_func_arg_t* ctx)
#endif #endif
return false; return false;
} }
static inline IRAM_ATTR void on_spi1_released(spi1_app_func_arg_t* ctx) static inline IRAM_ATTR void on_spi_released(app_func_arg_t* ctx)
{ {
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
ctx->released_since_us = esp_system_get_time(); ctx->released_since_us = esp_system_get_time();
#endif #endif
} }
static inline IRAM_ATTR void on_spi1_acquired(spi1_app_func_arg_t* ctx) static inline IRAM_ATTR void on_spi_acquired(app_func_arg_t* ctx)
{ {
// Ideally, when the time after `on_spi1_released()` before this function is called is larger // Ideally, when the time after `on_spi_released()` before this function is called is larger
// than CONFIG_SPI_FLASH_ERASE_YIELD_TICKS, the acquired time should be reset. We assume the // than CONFIG_SPI_FLASH_ERASE_YIELD_TICKS, the acquired time should be reset. We assume the
// time after `on_spi1_check_yield()` before this function is so short that we can do the reset // time after `on_spi_check_yield()` before this function is so short that we can do the reset
// in that function instead. // in that function instead.
} }
static inline IRAM_ATTR void on_spi1_yielded(spi1_app_func_arg_t* ctx) static inline IRAM_ATTR void on_spi_yielded(app_func_arg_t* ctx)
{ {
uint32_t time = esp_system_get_time(); uint32_t time = esp_system_get_time();
ctx->acquired_since_us = time; ctx->acquired_since_us = time;