diff --git a/components/esp_hw_support/cpu.c b/components/esp_hw_support/cpu.c index 6d6790b7e1b..bfb40993ed7 100644 --- a/components/esp_hw_support/cpu.c +++ b/components/esp_hw_support/cpu.c @@ -89,7 +89,7 @@ esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr) */ long args[] = {true, bp_num, (long)bp_addr}; int ret = semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_BREAKPOINT_SET, args); - if (ret == 0) { + if (ret != 0) { return ESP_ERR_INVALID_RESPONSE; } } else { @@ -112,7 +112,7 @@ esp_err_t esp_cpu_clear_breakpoint(int bp_num) // See description in esp_cpu_set_breakpoint() long args[] = {false, bp_num}; int ret = semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_BREAKPOINT_SET, args); - if (ret == 0) { + if (ret != 0) { return ESP_ERR_INVALID_RESPONSE; } } else { @@ -154,7 +154,7 @@ esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, e (long)((on_read ? ESP_SEMIHOSTING_WP_FLG_RD : 0) | (on_write ? ESP_SEMIHOSTING_WP_FLG_WR : 0)) }; int ret = semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_WATCHPOINT_SET, args); - if (ret == 0) { + if (ret != 0) { return ESP_ERR_INVALID_RESPONSE; } } else { @@ -177,7 +177,7 @@ esp_err_t esp_cpu_clear_watchpoint(int wp_num) // See description in esp_cpu_dbgr_is_attached() long args[] = {false, wp_num}; int ret = semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_WATCHPOINT_SET, args); - if (ret == 0) { + if (ret != 0) { return ESP_ERR_INVALID_RESPONSE; } } else { diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index b0912dacbf5..dbe8993f036 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -364,6 +364,12 @@ void esp_panic_handler(panic_info_t *info) } panic_print_str("Setting breakpoint at 0x"); panic_print_hex((uint32_t)info->addr); +#if __riscv + // Interrupts can trigger before the breakpoint is hit, + // so disable them on global level to avoid any further execution. + RV_CLEAR_CSR(mstatus, MSTATUS_MPIE | MSTATUS_SPIE | MSTATUS_UPIE); + panic_print_str(", disabling global interrupts,"); +#endif panic_print_str(" and returning...\r\n"); #if CONFIG_APPTRACE_ENABLE #if CONFIG_APPTRACE_SV_ENABLE @@ -375,7 +381,13 @@ void esp_panic_handler(panic_info_t *info) #endif disable_all_wdts(); - esp_cpu_set_breakpoint(0, info->addr); // use breakpoint 0 + // use breakpoint 0 + if (esp_cpu_set_breakpoint(0, info->addr) != ESP_OK) { +#if __riscv + // Halt here if unable to set a breakpoint. + asm("ebreak"); +#endif + } return; } #endif //CONFIG_ESP_DEBUG_OCDAWARE diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index 60518cc5659..4b9ce366c40 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -314,6 +314,8 @@ void panic_soc_fill_info(void *f, panic_info_t *info) info->details = print_cache_err_details; } } + + info->addr = (void *)frame->pc; } uint32_t panic_get_address(const void *f) diff --git a/components/esp_system/port/arch/xtensa/panic_handler_asm.S b/components/esp_system/port/arch/xtensa/panic_handler_asm.S index a452c5f6a19..4364dc681a8 100644 --- a/components/esp_system/port/arch/xtensa/panic_handler_asm.S +++ b/components/esp_system/port/arch/xtensa/panic_handler_asm.S @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "freertos/xtensa_rtos.h" #include "esp_private/panic_reason.h" #include "soc/soc.h" @@ -58,4 +63,15 @@ _xt_panic: mov a6,sp call4 panicHandler - ret + /* When panicHandler returns, resume at the crashing PC so the breakpoint is hit there. + * Restore the interrupted GPRs/SP from the frame (EXCSAVE_1/EPC_1 may have + * been clobbered by windowed C calls). Do not restore PS: it was sampled at + * the panic interrupt level, and restoring DEBUGLEVEL would mask IBREAK. + */ + call0 _xt_context_restore + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove exception frame */ + rsync /* ensure EPC written */ + rfe /* PS.EXCM is cleared */