Merge branch 'bugfix/panic_handler_not_in_iram' into 'master'

panic: handlers can now be placed in flash

Closes IDF-2851

See merge request espressif/esp-idf!12874
This commit is contained in:
Ivan Grokhotkov 2021-04-16 02:47:05 +00:00
commit e6fd582fdf
7 changed files with 32 additions and 23 deletions

View File

@ -394,10 +394,10 @@ menu "ESP System Settings"
automatically re-enable flash cache before running GDB Stub or Core Dump. This adds some minor
risk, if the flash cache status is also corrupted during the crash.
If this option is enabled, the panic handler code is placed in IRAM. This allows the panic
handler to run without needing to re-enable cache first. This may be necessary to debug some
complex issues with crashes while flash cache is disabled (for example, when writing to
SPI flash.)
If this option is enabled, the panic handler code (including required UART functions) is placed
in IRAM. This may be necessary to debug some complex issues with crashes while flash cache is
disabled (for example, when writing to SPI flash) or when flash cache is corrupted when an exception
is triggered.
config ESP_DEBUG_STUBS_ENABLE
bool

View File

@ -1,10 +1,11 @@
[mapping:esp_system]
archive: libesp_system.a
entries:
panic (noflash)
panic_handler (noflash)
panic_arch (noflash)
reset_reason (noflash)
if ESP_PANIC_HANDLER_IRAM = y:
panic (noflash)
panic_handler (noflash)
panic_arch (noflash)
esp_err (noflash)
esp_system:esp_system_abort (noflash)

View File

@ -162,14 +162,6 @@ static void panic_handler(void *frame, bool pseudo_excause)
esp_dport_access_int_abort();
#endif
#if !CONFIG_ESP_PANIC_HANDLER_IRAM
// Re-enable CPU cache for current CPU if it was disabled
if (!spi_flash_cache_enabled()) {
spi_flash_enable_cache(core_id);
panic_print_str("Re-enable cpu cache.\r\n");
}
#endif
if (esp_cpu_in_ocd_debug_mode()) {
#if __XTENSA__
if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(panic_get_address(frame))) && (panic_get_address(frame) & 0xC0000000U))) {
@ -198,8 +190,25 @@ static void panic_handler(void *frame, bool pseudo_excause)
esp_panic_handler(&info);
}
void panicHandler(void *frame)
/**
* This function must always be in IRAM as it is required to
* re-enable the flash cache.
*/
static void IRAM_ATTR panic_enable_cache(void) {
int core_id = cpu_hal_get_core_id();
if (!spi_flash_cache_enabled()) {
#ifdef CONFIG_IDF_TARGET_ESP32
esp_dport_access_int_abort();
#endif
spi_flash_enable_cache(core_id);
}
}
void IRAM_ATTR panicHandler(void *frame)
{
panic_enable_cache();
// This panic handler gets called for when the double exception vector,
// kernel exception vector gets used; as well as handling interrupt-based
// faults cache error, wdt expiry. EXCAUSE register gets written with
@ -207,8 +216,9 @@ void panicHandler(void *frame)
panic_handler(frame, true);
}
void xt_unhandled_exception(void *frame)
void IRAM_ATTR xt_unhandled_exception(void *frame)
{
panic_enable_cache();
panic_handler(frame, false);
}

View File

@ -113,7 +113,7 @@ esp_reset_reason_t IRAM_ATTR esp_reset_reason_get_hint(void)
}
return (esp_reset_reason_t) low;
}
static void esp_reset_reason_clear_hint(void)
static inline void esp_reset_reason_clear_hint(void)
{
REG_WRITE(RTC_RESET_CAUSE_REG, 0);
}

View File

@ -3,7 +3,7 @@ archive: libhal.a
entries:
spi_hal_iram (noflash)
spi_slave_hal_iram (noflash)
if UART_ISR_IN_IRAM = y:
if UART_ISR_IN_IRAM = y || ESP_PANIC_HANDLER_IRAM = y:
uart_hal_iram (noflash)
else:
uart_hal_iram (default)

View File

@ -67,7 +67,7 @@ Behavior of panic handler is affected by two other configuration options.
- If :ref:`CONFIG_ESP_PANIC_HANDLER_IRAM` is disabled (disabled by default), the panic handler code is placed in flash memory not IRAM. This means that if ESP-IDF crashes while flash cache is disabled, the panic handler will automatically re-enable flash cache before running GDB Stub or Core Dump. This adds some minor risk, if the flash cache status is also corrupted during the crash.
If this option is enabled, the panic handler code is placed in IRAM. This allows the panic handler to run without needing to re-enable cache first. This may be necessary to debug some complex issues with crashes while flash cache is disabled (for example, when writing to SPI flash).
If this option is enabled, the panic handler code (including required UART functions) is placed in IRAM. This may be necessary to debug some complex issues with crashes while flash cache is disabled (for example, when writing to SPI flash) or when flash cache is corrupted when an exception is triggered.
The following diagram illustrates panic handler behavior:

View File

@ -73,7 +73,6 @@ def int_wdt_inner(env, test_name):
def int_wdt_cache_disabled_inner(env, test_name):
with get_dut(env, test_name, 'test_int_wdt_cache_disabled', qemu_wdt_enable=True) as dut:
dut.expect('Re-enable cpu cache.')
dut.expect_gme('Interrupt wdt timeout on CPU0')
dut.expect_reg_dump(0)
dut.expect('Backtrace:')
@ -87,7 +86,6 @@ def int_wdt_cache_disabled_inner(env, test_name):
def cache_error_inner(env, test_name):
with get_dut(env, test_name, 'test_cache_error') as dut:
dut.expect('Re-enable cpu cache.')
dut.expect_gme('Cache disabled but cached memory region accessed')
dut.expect_reg_dump(0)
dut.expect_backtrace()