mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(esp_system/panic): ensure breakpoint set from panic handler gets hit afterwards
This commit is contained in:
@@ -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 {
|
||||
@@ -151,7 +151,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 {
|
||||
@@ -174,7 +174,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 {
|
||||
|
||||
@@ -394,6 +394,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");
|
||||
|
||||
// Trigger early breakpoint handlers before returning to debugger.
|
||||
@@ -404,7 +410,13 @@ void esp_panic_handler(panic_info_t *info)
|
||||
esp_panic_trigger_event(ESP_SYS_EVENT_PANIC_EARLY_BREAK, &panic_ctx);
|
||||
|
||||
panic_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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -63,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, XT_REG_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 */
|
||||
|
||||
Reference in New Issue
Block a user