diff --git a/src/cortexm.c b/src/cortexm.c index 98707ce..0cab4cf 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -173,6 +173,11 @@ const struct command_s cortexm_cmd_list[] = { #define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0) #define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0) +/* Signals returned by cortexm_halt_wait() */ +#define SIGINT 2 +#define SIGTRAP 5 +#define SIGSEGV 11 + static void cortexm_attach(struct target_s *target); static void cortexm_detach(struct target_s *target); @@ -320,7 +325,6 @@ cortexm_probe(struct target_s *target) target->halt_request = cortexm_halt_request; target->halt_wait = cortexm_halt_wait; target->halt_resume = cortexm_halt_resume; - target->fault_unwind = cortexm_fault_unwind; target->regs_size = sizeof(regnum_cortex_m); /* XXX: detect FP extension */ target_add_commands(target, cortexm_cmd_list, cortexm_driver_str); @@ -535,19 +539,37 @@ cortexm_halt_request(struct target_s *target) CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN); } +/* FIXME: static here must go! */ +static uint8_t old_step = 0; + static int cortexm_halt_wait(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); + if (!(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT)) + return 0; + + /* We've halted. Let's find out why. */ + uint32_t dfsr = adiv5_ap_mem_read(ap, CORTEXM_DFSR); + adiv5_ap_mem_write(ap, CORTEXM_DFSR, dfsr); /* write back to reset */ + + if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(target)) + return SIGSEGV; + + if (dfsr & (CORTEXM_DFSR_BKPT | CORTEXM_DFSR_DWTTRAP)) + return SIGTRAP; + + if (dfsr & CORTEXM_DFSR_HALTED) + return old_step ? SIGTRAP : SIGINT; + + return SIGTRAP; - return adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT; } static void cortexm_halt_resume(struct target_s *target, uint8_t step) { ADIv5_AP_t *ap = adiv5_target_ap(target); - static uint8_t old_step = 0; uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN; if(step) dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS; @@ -564,15 +586,13 @@ cortexm_halt_resume(struct target_s *target, uint8_t step) static int cortexm_fault_unwind(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t dfsr = adiv5_ap_mem_read(ap, CORTEXM_DFSR); uint32_t hfsr = adiv5_ap_mem_read(ap, CORTEXM_HFSR); uint32_t cfsr = adiv5_ap_mem_read(ap, CORTEXM_CFSR); - adiv5_ap_mem_write(ap, CORTEXM_DFSR, dfsr);/* write back to reset */ adiv5_ap_mem_write(ap, CORTEXM_HFSR, hfsr);/* write back to reset */ adiv5_ap_mem_write(ap, CORTEXM_CFSR, cfsr);/* write back to reset */ /* We check for FORCED in the HardFault Status Register or * for a configurable fault to avoid catching core resets */ - if((dfsr & CORTEXM_DFSR_VCATCH) && ((hfsr & CORTEXM_HFSR_FORCED) || cfsr)) { + if((hfsr & CORTEXM_HFSR_FORCED) || cfsr) { /* Unwind exception */ uint32_t regs[target->regs_size]; uint32_t stack[8]; diff --git a/src/gdb_main.c b/src/gdb_main.c index c2adba9..58ad223 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -153,8 +153,8 @@ gdb_main(void) case '?': { /* '?': Request reason for target halt */ /* This packet isn't documented as being mandatory, * but GDB doesn't work without it. */ - int sent_int = 0; - uint32_t watch_addr; + uint32_t watch_addr; + int sig; if(!cur_target) { /* Report "target exited" if no target */ @@ -163,26 +163,19 @@ gdb_main(void) } /* Wait for target halt */ - while(!target_halt_wait(cur_target)) { + while(!(sig = target_halt_wait(cur_target))) { unsigned char c = gdb_if_getchar_to(0); if((c == '\x03') || (c == '\x04')) { target_halt_request(cur_target); - sent_int = 1; } } - SET_RUN_STATE(0); /* Report reason for halt */ if(target_check_hw_wp(cur_target, &watch_addr)) { /* Watchpoint hit */ - gdb_putpacket_f("T05watch:%08X;", watch_addr); - } else if(target_fault_unwind(cur_target)) { - gdb_putpacketz("T0b"); - } else if(sent_int) { - /* Target interrupted */ - gdb_putpacketz("T02"); + gdb_putpacket_f("T%02Xwatch:%08X;", sig, watch_addr); } else { - gdb_putpacketz("T05"); + gdb_putpacket_f("T%02X", sig); } break; } diff --git a/src/include/target.h b/src/include/target.h index 4a702a1..d2af706 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -88,9 +88,6 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); #define target_halt_resume(target, step) \ (target)->halt_resume((target), (step)) -#define target_fault_unwind(target) \ - ((target)->fault_unwind?(target)->fault_unwind((target)):0) - /* Break-/watchpoint functions */ #define target_set_hw_bp(target, addr) \ (target)->set_hw_bp((target), (addr)) @@ -152,7 +149,6 @@ struct target_s { void (*halt_request)(struct target_s *target); int (*halt_wait)(struct target_s *target); void (*halt_resume)(struct target_s *target, uint8_t step); - int (*fault_unwind)(struct target_s *target); /* Break-/watchpoint functions */ int (*set_hw_bp)(struct target_s *target, uint32_t addr);