Signal on halt is now returned by target_halt_wait().
Fault unwinding is now handled internally in target implementation. GDB server doesn't need to know about it.
This commit is contained in:
parent
53af978295
commit
d64cec686a
|
@ -173,6 +173,11 @@ const struct command_s cortexm_cmd_list[] = {
|
||||||
#define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0)
|
#define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0)
|
||||||
#define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 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_attach(struct target_s *target);
|
||||||
static void cortexm_detach(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_request = cortexm_halt_request;
|
||||||
target->halt_wait = cortexm_halt_wait;
|
target->halt_wait = cortexm_halt_wait;
|
||||||
target->halt_resume = cortexm_halt_resume;
|
target->halt_resume = cortexm_halt_resume;
|
||||||
target->fault_unwind = cortexm_fault_unwind;
|
|
||||||
target->regs_size = sizeof(regnum_cortex_m); /* XXX: detect FP extension */
|
target->regs_size = sizeof(regnum_cortex_m); /* XXX: detect FP extension */
|
||||||
|
|
||||||
target_add_commands(target, cortexm_cmd_list, cortexm_driver_str);
|
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);
|
CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: static here must go! */
|
||||||
|
static uint8_t old_step = 0;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cortexm_halt_wait(struct target_s *target)
|
cortexm_halt_wait(struct target_s *target)
|
||||||
{
|
{
|
||||||
ADIv5_AP_t *ap = adiv5_target_ap(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
|
static void
|
||||||
cortexm_halt_resume(struct target_s *target, uint8_t step)
|
cortexm_halt_resume(struct target_s *target, uint8_t step)
|
||||||
{
|
{
|
||||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||||
static uint8_t old_step = 0;
|
|
||||||
uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN;
|
uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN;
|
||||||
|
|
||||||
if(step) dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS;
|
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)
|
static int cortexm_fault_unwind(struct target_s *target)
|
||||||
{
|
{
|
||||||
ADIv5_AP_t *ap = adiv5_target_ap(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 hfsr = adiv5_ap_mem_read(ap, CORTEXM_HFSR);
|
||||||
uint32_t cfsr = adiv5_ap_mem_read(ap, CORTEXM_CFSR);
|
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_HFSR, hfsr);/* write back to reset */
|
||||||
adiv5_ap_mem_write(ap, CORTEXM_CFSR, cfsr);/* 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
|
/* We check for FORCED in the HardFault Status Register or
|
||||||
* for a configurable fault to avoid catching core resets */
|
* 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 */
|
/* Unwind exception */
|
||||||
uint32_t regs[target->regs_size];
|
uint32_t regs[target->regs_size];
|
||||||
uint32_t stack[8];
|
uint32_t stack[8];
|
||||||
|
|
|
@ -153,8 +153,8 @@ gdb_main(void)
|
||||||
case '?': { /* '?': Request reason for target halt */
|
case '?': { /* '?': Request reason for target halt */
|
||||||
/* This packet isn't documented as being mandatory,
|
/* This packet isn't documented as being mandatory,
|
||||||
* but GDB doesn't work without it. */
|
* but GDB doesn't work without it. */
|
||||||
int sent_int = 0;
|
uint32_t watch_addr;
|
||||||
uint32_t watch_addr;
|
int sig;
|
||||||
|
|
||||||
if(!cur_target) {
|
if(!cur_target) {
|
||||||
/* Report "target exited" if no target */
|
/* Report "target exited" if no target */
|
||||||
|
@ -163,26 +163,19 @@ gdb_main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for target halt */
|
/* 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);
|
unsigned char c = gdb_if_getchar_to(0);
|
||||||
if((c == '\x03') || (c == '\x04')) {
|
if((c == '\x03') || (c == '\x04')) {
|
||||||
target_halt_request(cur_target);
|
target_halt_request(cur_target);
|
||||||
sent_int = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_RUN_STATE(0);
|
SET_RUN_STATE(0);
|
||||||
/* Report reason for halt */
|
/* Report reason for halt */
|
||||||
if(target_check_hw_wp(cur_target, &watch_addr)) {
|
if(target_check_hw_wp(cur_target, &watch_addr)) {
|
||||||
/* Watchpoint hit */
|
/* Watchpoint hit */
|
||||||
gdb_putpacket_f("T05watch:%08X;", watch_addr);
|
gdb_putpacket_f("T%02Xwatch:%08X;", sig, watch_addr);
|
||||||
} else if(target_fault_unwind(cur_target)) {
|
|
||||||
gdb_putpacketz("T0b");
|
|
||||||
} else if(sent_int) {
|
|
||||||
/* Target interrupted */
|
|
||||||
gdb_putpacketz("T02");
|
|
||||||
} else {
|
} else {
|
||||||
gdb_putpacketz("T05");
|
gdb_putpacket_f("T%02X", sig);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,9 +88,6 @@ target *target_attach(target *t, target_destroy_callback destroy_cb);
|
||||||
#define target_halt_resume(target, step) \
|
#define target_halt_resume(target, step) \
|
||||||
(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 */
|
/* Break-/watchpoint functions */
|
||||||
#define target_set_hw_bp(target, addr) \
|
#define target_set_hw_bp(target, addr) \
|
||||||
(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);
|
void (*halt_request)(struct target_s *target);
|
||||||
int (*halt_wait)(struct target_s *target);
|
int (*halt_wait)(struct target_s *target);
|
||||||
void (*halt_resume)(struct target_s *target, uint8_t step);
|
void (*halt_resume)(struct target_s *target, uint8_t step);
|
||||||
int (*fault_unwind)(struct target_s *target);
|
|
||||||
|
|
||||||
/* Break-/watchpoint functions */
|
/* Break-/watchpoint functions */
|
||||||
int (*set_hw_bp)(struct target_s *target, uint32_t addr);
|
int (*set_hw_bp)(struct target_s *target, uint32_t addr);
|
||||||
|
|
Loading…
Reference in New Issue