Merge branch 'bugfix/spi_flash_yield_coredump' into 'master'
fixes for core dump regressions See merge request espressif/esp-idf!8978
This commit is contained in:
commit
61ab64439b
|
@ -181,11 +181,14 @@ int xt_clock_freq(void) __attribute__((deprecated));
|
||||||
#define configMAX_PRIORITIES ( 25 )
|
#define configMAX_PRIORITIES ( 25 )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_APPTRACE_ENABLE
|
#if defined(CONFIG_APPTRACE_ENABLE)
|
||||||
#define configMINIMAL_STACK_SIZE 768
|
|
||||||
#else
|
|
||||||
/* apptrace module requires at least 2KB of stack per task */
|
/* apptrace module requires at least 2KB of stack per task */
|
||||||
#define configMINIMAL_STACK_SIZE 2048
|
#define configMINIMAL_STACK_SIZE 2048
|
||||||
|
#elif defined(CONFIG_COMPILER_OPTIMIZATION_NONE)
|
||||||
|
/* with optimizations disabled, scheduler uses additional stack */
|
||||||
|
#define configMINIMAL_STACK_SIZE 1024
|
||||||
|
#else
|
||||||
|
#define configMINIMAL_STACK_SIZE 768
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef configIDLE_TASK_STACK_SIZE
|
#ifndef configIDLE_TASK_STACK_SIZE
|
||||||
|
|
|
@ -144,7 +144,7 @@ static inline uint32_t xPortGetCoreID(void);
|
||||||
// They can be called from interrupts too.
|
// They can be called from interrupts too.
|
||||||
// WARNING: Only applies to current CPU. See notes above.
|
// WARNING: Only applies to current CPU. See notes above.
|
||||||
static inline unsigned portENTER_CRITICAL_NESTED(void) {
|
static inline unsigned portENTER_CRITICAL_NESTED(void) {
|
||||||
unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
|
unsigned state = XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL);
|
||||||
portbenchmarkINTERRUPT_DISABLE();
|
portbenchmarkINTERRUPT_DISABLE();
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
|
||||||
uint32_t core_id, other_core_id;
|
uint32_t core_id, other_core_id;
|
||||||
|
|
||||||
assert(lock);
|
assert(lock);
|
||||||
irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
|
irq_status = XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL);
|
||||||
|
|
||||||
if(timeout != SPINLOCK_WAIT_FOREVER){
|
if(timeout != SPINLOCK_WAIT_FOREVER){
|
||||||
RSR(CCOUNT, ccount_start);
|
RSR(CCOUNT, ccount_start);
|
||||||
|
@ -139,7 +139,7 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l
|
||||||
uint32_t core_id;
|
uint32_t core_id;
|
||||||
|
|
||||||
assert(lock);
|
assert(lock);
|
||||||
irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
|
irq_status = XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL);
|
||||||
|
|
||||||
RSR(PRID, core_id);
|
RSR(PRID, core_id);
|
||||||
assert(core_id == lock->owner); // This is a mutex we didn't lock, or it's corrupt
|
assert(core_id == lock->owner); // This is a mutex we didn't lock, or it's corrupt
|
||||||
|
|
|
@ -372,7 +372,9 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui
|
||||||
no_yield_time_us += (esp_timer_get_time() - start_time_us);
|
no_yield_time_us += (esp_timer_get_time() - start_time_us);
|
||||||
if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
|
if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
|
||||||
no_yield_time_us = 0;
|
no_yield_time_us = 0;
|
||||||
vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
|
if (chip->os_func->yield) {
|
||||||
|
chip->os_func->yield(chip->os_func_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ static spi_flash_counters_t s_flash_stats;
|
||||||
|
|
||||||
static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc);
|
static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc);
|
||||||
static bool is_safe_write_address(size_t addr, size_t size);
|
static bool is_safe_write_address(size_t addr, size_t size);
|
||||||
|
static void spi_flash_os_yield(void);
|
||||||
|
|
||||||
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
|
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
|
||||||
.start = spi_flash_disable_interrupts_caches_and_other_cpu,
|
.start = spi_flash_disable_interrupts_caches_and_other_cpu,
|
||||||
|
@ -89,18 +90,20 @@ const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
|
||||||
.op_lock = spi_flash_op_lock,
|
.op_lock = spi_flash_op_lock,
|
||||||
.op_unlock = spi_flash_op_unlock,
|
.op_unlock = spi_flash_op_unlock,
|
||||||
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
|
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
|
||||||
.is_safe_write_address = is_safe_write_address
|
.is_safe_write_address = is_safe_write_address,
|
||||||
#endif
|
#endif
|
||||||
|
.yield = spi_flash_os_yield,
|
||||||
};
|
};
|
||||||
|
|
||||||
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
|
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
|
||||||
.start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
|
.start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
|
||||||
.end = spi_flash_enable_interrupts_caches_no_os,
|
.end = spi_flash_enable_interrupts_caches_no_os,
|
||||||
.op_lock = 0,
|
.op_lock = NULL,
|
||||||
.op_unlock = 0,
|
.op_unlock = NULL,
|
||||||
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
|
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
|
||||||
.is_safe_write_address = 0
|
.is_safe_write_address = NULL,
|
||||||
#endif
|
#endif
|
||||||
|
.yield = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const spi_flash_guard_funcs_t *s_flash_guard_ops;
|
static const spi_flash_guard_funcs_t *s_flash_guard_ops;
|
||||||
|
@ -185,6 +188,13 @@ static inline void IRAM_ATTR spi_flash_guard_op_unlock(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void IRAM_ATTR spi_flash_os_yield(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||||
static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock(void)
|
static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock(void)
|
||||||
{
|
{
|
||||||
|
@ -263,7 +273,9 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_addr, size_t size)
|
||||||
no_yield_time_us += (esp_timer_get_time() - start_time_us);
|
no_yield_time_us += (esp_timer_get_time() - start_time_us);
|
||||||
if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
|
if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
|
||||||
no_yield_time_us = 0;
|
no_yield_time_us = 0;
|
||||||
vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
|
if (s_flash_guard_ops && s_flash_guard_ops->yield) {
|
||||||
|
s_flash_guard_ops->yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ typedef struct {
|
||||||
|
|
||||||
/** Delay for at least 'us' microseconds. Called in between 'start' and 'end'. */
|
/** Delay for at least 'us' microseconds. Called in between 'start' and 'end'. */
|
||||||
esp_err_t (*delay_us)(void *arg, unsigned us);
|
esp_err_t (*delay_us)(void *arg, unsigned us);
|
||||||
|
|
||||||
|
/** Yield to other tasks. Called during erase operations. */
|
||||||
|
esp_err_t (*yield)(void *arg);
|
||||||
} esp_flash_os_functions_t;
|
} esp_flash_os_functions_t;
|
||||||
|
|
||||||
/** @brief Structure to describe a SPI flash chip connected to the system.
|
/** @brief Structure to describe a SPI flash chip connected to the system.
|
||||||
|
|
|
@ -341,6 +341,10 @@ typedef void (*spi_flash_op_unlock_func_t)(void);
|
||||||
* @brief Function to protect SPI flash critical regions corruption.
|
* @brief Function to protect SPI flash critical regions corruption.
|
||||||
*/
|
*/
|
||||||
typedef bool (*spi_flash_is_safe_write_address_t)(size_t addr, size_t size);
|
typedef bool (*spi_flash_is_safe_write_address_t)(size_t addr, size_t size);
|
||||||
|
/**
|
||||||
|
* @brief Function to yield to the OS during erase operation.
|
||||||
|
*/
|
||||||
|
typedef void (*spi_flash_os_yield_t)(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure holding SPI flash access critical sections management functions.
|
* Structure holding SPI flash access critical sections management functions.
|
||||||
|
@ -381,6 +385,7 @@ typedef struct {
|
||||||
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
|
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
|
||||||
spi_flash_is_safe_write_address_t is_safe_write_address; /**< checks flash write addresses.*/
|
spi_flash_is_safe_write_address_t is_safe_write_address; /**< checks flash write addresses.*/
|
||||||
#endif
|
#endif
|
||||||
|
spi_flash_os_yield_t yield; /**< yield to the OS during flash erase */
|
||||||
} spi_flash_guard_funcs_t;
|
} spi_flash_guard_funcs_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "esp_spi_flash.h" //for ``g_flash_guard_default_ops``
|
#include "esp_spi_flash.h" //for ``g_flash_guard_default_ops``
|
||||||
#include "esp_flash.h"
|
#include "esp_flash.h"
|
||||||
#include "esp_flash_partitions.h"
|
#include "esp_flash_partitions.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
#include "hal/spi_types.h"
|
#include "hal/spi_types.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
@ -101,6 +103,14 @@ static IRAM_ATTR esp_err_t delay_us(void *arg, unsigned us)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR esp_err_t spi_flash_os_yield(void *arg)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
|
||||||
|
#endif
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
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 (((spi1_app_func_arg_t*)arg)->no_protect || esp_partition_main_flash_region_safe(start_addr, size)) {
|
||||||
|
@ -117,14 +127,16 @@ static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {};
|
||||||
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 = {
|
||||||
.start = spi1_start,
|
.start = spi1_start,
|
||||||
.end = spi1_end,
|
.end = spi1_end,
|
||||||
.delay_us = delay_us,
|
|
||||||
.region_protected = main_flash_region_protected,
|
.region_protected = main_flash_region_protected,
|
||||||
|
.delay_us = delay_us,
|
||||||
|
.yield = spi_flash_os_yield,
|
||||||
};
|
};
|
||||||
|
|
||||||
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 = spi_start,
|
||||||
.end = spi_end,
|
.end = spi_end,
|
||||||
.delay_us = delay_us,
|
.delay_us = delay_us,
|
||||||
|
.yield = spi_flash_os_yield
|
||||||
};
|
};
|
||||||
|
|
||||||
static spi_bus_lock_dev_handle_t register_dev(int host_id)
|
static spi_bus_lock_dev_handle_t register_dev(int host_id)
|
||||||
|
|
|
@ -76,6 +76,7 @@ const DRAM_ATTR esp_flash_os_functions_t esp_flash_noos_functions = {
|
||||||
.end = end,
|
.end = end,
|
||||||
.delay_us = delay_us,
|
.delay_us = delay_us,
|
||||||
.region_protected = NULL,
|
.region_protected = NULL,
|
||||||
|
.yield = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
esp_err_t IRAM_ATTR esp_flash_app_disable_os_functions(esp_flash_t* chip)
|
esp_err_t IRAM_ATTR esp_flash_app_disable_os_functions(esp_flash_t* chip)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=n
|
|
@ -128,6 +128,22 @@ def test_coredump_uart_abort(env, extra_data):
|
||||||
# TODO: check the contents of core dump output
|
# TODO: check the contents of core dump output
|
||||||
|
|
||||||
|
|
||||||
|
@panic_test()
|
||||||
|
def test_coredump_uart_int_wdt(env, extra_data):
|
||||||
|
with get_dut(env, "coredump_uart", "test_int_wdt") as dut:
|
||||||
|
dut.expect_gme("Interrupt wdt timeout on CPU0")
|
||||||
|
dut.expect_reg_dump(0)
|
||||||
|
dut.expect("Backtrace:")
|
||||||
|
dut.expect_none("CORRUPTED", "Guru Meditation")
|
||||||
|
dut.expect_reg_dump(1)
|
||||||
|
dut.expect("Backtrace:")
|
||||||
|
dut.expect_elf_sha256()
|
||||||
|
dut.expect_none("CORRUPTED", "Guru Meditation")
|
||||||
|
dut.expect("Rebooting...")
|
||||||
|
dut.process_coredump_uart()
|
||||||
|
# TODO: check the contents of core dump output
|
||||||
|
|
||||||
|
|
||||||
@panic_test()
|
@panic_test()
|
||||||
def test_coredump_flash_abort(env, extra_data):
|
def test_coredump_flash_abort(env, extra_data):
|
||||||
with get_dut(env, "coredump_flash", "test_abort") as dut:
|
with get_dut(env, "coredump_flash", "test_abort") as dut:
|
||||||
|
@ -140,5 +156,21 @@ def test_coredump_flash_abort(env, extra_data):
|
||||||
# TODO: check the contents of core dump output
|
# TODO: check the contents of core dump output
|
||||||
|
|
||||||
|
|
||||||
|
@panic_test()
|
||||||
|
def test_coredump_flash_int_wdt(env, extra_data):
|
||||||
|
with get_dut(env, "coredump_flash", "test_int_wdt") as dut:
|
||||||
|
dut.expect_gme("Interrupt wdt timeout on CPU0")
|
||||||
|
dut.expect_reg_dump(0)
|
||||||
|
dut.expect("Backtrace:")
|
||||||
|
dut.expect_none("CORRUPTED", "Guru Meditation")
|
||||||
|
dut.expect_reg_dump(1)
|
||||||
|
dut.expect("Backtrace:")
|
||||||
|
dut.expect_elf_sha256()
|
||||||
|
dut.expect_none("CORRUPTED", "Guru Meditation")
|
||||||
|
dut.expect("Rebooting...")
|
||||||
|
dut.process_coredump_flash()
|
||||||
|
# TODO: check the contents of core dump output
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
run_all(__file__)
|
run_all(__file__)
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||||
|
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
|
||||||
|
|
Loading…
Reference in a new issue