target: target_halt_wait and target_check_hw_wp replaced with target_halt_poll.
The new function returns a stop reason which must be translated in gdb server. In the case of a watchpoint hit, the address is returned by a pointer parameter. Simplify the extenal interface for set/clear breaki-/watchpoints.
This commit is contained in:
parent
ab06243e93
commit
9136cf4c98
|
@ -34,6 +34,13 @@
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
|
|
||||||
|
enum gdb_signal {
|
||||||
|
GDB_SIGINT = 2,
|
||||||
|
GDB_SIGTRAP = 5,
|
||||||
|
GDB_SIGSEGV = 11,
|
||||||
|
GDB_SIGLOST = 29,
|
||||||
|
};
|
||||||
|
|
||||||
#define BUF_SIZE 1024
|
#define BUF_SIZE 1024
|
||||||
|
|
||||||
#define ERROR_IF_NO_TARGET() \
|
#define ERROR_IF_NO_TARGET() \
|
||||||
|
@ -156,8 +163,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||||
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. */
|
||||||
target_addr watch_addr;
|
target_addr watch;
|
||||||
int sig;
|
enum target_halt_reason reason;
|
||||||
|
|
||||||
if(!cur_target) {
|
if(!cur_target) {
|
||||||
/* Report "target exited" if no target */
|
/* Report "target exited" if no target */
|
||||||
|
@ -166,7 +173,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for target halt */
|
/* Wait for target halt */
|
||||||
while(!(sig = target_halt_wait(cur_target))) {
|
while(!(reason = target_halt_poll(cur_target, &watch))) {
|
||||||
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);
|
||||||
|
@ -174,22 +181,22 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||||
}
|
}
|
||||||
SET_RUN_STATE(0);
|
SET_RUN_STATE(0);
|
||||||
|
|
||||||
/* Negative signal indicates we're in a syscall */
|
/* Translate reason to GDB signal */
|
||||||
if (sig < 0)
|
switch (reason) {
|
||||||
|
case TARGET_HALT_ERROR:
|
||||||
|
gdb_putpacket_f("X%02X", GDB_SIGLOST);
|
||||||
break;
|
break;
|
||||||
|
case TARGET_HALT_REQUEST:
|
||||||
/* Target disappeared */
|
gdb_putpacket_f("T%02X", GDB_SIGINT);
|
||||||
if (cur_target == NULL) {
|
|
||||||
gdb_putpacket_f("X%02X", sig);
|
|
||||||
break;
|
break;
|
||||||
}
|
case TARGET_HALT_WATCHPOINT:
|
||||||
|
gdb_putpacket_f("T%02Xwatch:%08X;", GDB_SIGTRAP, watch);
|
||||||
/* Report reason for halt */
|
break;
|
||||||
if(target_check_hw_wp(cur_target, &watch_addr)) {
|
case TARGET_HALT_FAULT:
|
||||||
/* Watchpoint hit */
|
gdb_putpacket_f("T%02X", GDB_SIGSEGV);
|
||||||
gdb_putpacket_f("T%02Xwatch:%08X;", sig, watch_addr);
|
break;
|
||||||
} else {
|
default:
|
||||||
gdb_putpacket_f("T%02X", sig);
|
gdb_putpacket_f("T%02X", GDB_SIGTRAP);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -447,32 +454,18 @@ handle_z_packet(char *packet, int plen)
|
||||||
//sscanf(packet, "%*[zZ]%hhd,%08lX,%hhd", &type, &addr, &len);
|
//sscanf(packet, "%*[zZ]%hhd,%08lX,%hhd", &type, &addr, &len);
|
||||||
type = packet[1] - '0';
|
type = packet[1] - '0';
|
||||||
sscanf(packet + 2, ",%" PRIx32 ",%d", &addr, &len);
|
sscanf(packet + 2, ",%" PRIx32 ",%d", &addr, &len);
|
||||||
switch(type) {
|
if(set)
|
||||||
case 1: /* Hardware breakpoint */
|
ret = target_breakwatch_set(cur_target, type, addr, len);
|
||||||
if(set)
|
|
||||||
ret = target_set_hw_bp(cur_target, addr, len);
|
|
||||||
else
|
|
||||||
ret = target_clear_hw_bp(cur_target, addr, len);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
if(set)
|
|
||||||
ret = target_set_hw_wp(cur_target, type, addr, len);
|
|
||||||
else
|
|
||||||
ret = target_clear_hw_wp(cur_target, type, addr, len);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
gdb_putpacketz("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ret)
|
|
||||||
gdb_putpacketz("OK");
|
|
||||||
else
|
else
|
||||||
|
ret = target_breakwatch_clear(cur_target, type, addr, len);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
gdb_putpacketz("E01");
|
gdb_putpacketz("E01");
|
||||||
|
} else if (ret > 0) {
|
||||||
|
gdb_putpacketz("");
|
||||||
|
} else {
|
||||||
|
gdb_putpacketz("OK");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdb_main(void)
|
void gdb_main(void)
|
||||||
|
|
|
@ -121,18 +121,31 @@ void target_regs_read(target *t, void *data);
|
||||||
void target_regs_write(target *t, const void *data);
|
void target_regs_write(target *t, const void *data);
|
||||||
|
|
||||||
/* Halt/resume functions */
|
/* Halt/resume functions */
|
||||||
|
enum target_halt_reason {
|
||||||
|
TARGET_HALT_RUNNING = 0, /* Target not halted */
|
||||||
|
TARGET_HALT_ERROR, /* Failed to read target status */
|
||||||
|
TARGET_HALT_REQUEST,
|
||||||
|
TARGET_HALT_STEPPING,
|
||||||
|
TARGET_HALT_BREAKPOINT,
|
||||||
|
TARGET_HALT_WATCHPOINT,
|
||||||
|
TARGET_HALT_FAULT,
|
||||||
|
};
|
||||||
|
|
||||||
void target_reset(target *t);
|
void target_reset(target *t);
|
||||||
void target_halt_request(target *t);
|
void target_halt_request(target *t);
|
||||||
int target_halt_wait(target *t);
|
enum target_halt_reason target_halt_poll(target *t, target_addr *watch);
|
||||||
void target_halt_resume(target *t, bool step);
|
void target_halt_resume(target *t, bool step);
|
||||||
|
|
||||||
/* Break-/watchpoint functions */
|
/* Break-/watchpoint functions */
|
||||||
int target_set_hw_bp(target *t, target_addr addr, uint8_t len);
|
enum target_breakwatch {
|
||||||
int target_clear_hw_bp(target *t, target_addr addr, uint8_t len);
|
TARGET_BREAK_SOFT,
|
||||||
|
TARGET_BREAK_HARD,
|
||||||
int target_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len);
|
TARGET_WATCH_WRITE,
|
||||||
int target_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len);
|
TARGET_WATCH_READ,
|
||||||
int target_check_hw_wp(target *t, target_addr *addr);
|
TARGET_WATCH_ACCESS,
|
||||||
|
};
|
||||||
|
int target_breakwatch_set(target *t, enum target_breakwatch, target_addr, size_t);
|
||||||
|
int target_breakwatch_clear(target *t, enum target_breakwatch, target_addr, size_t);
|
||||||
|
|
||||||
/* Flash memory access functions */
|
/* Flash memory access functions */
|
||||||
int target_flash_erase(target *t, target_addr addr, size_t len);
|
int target_flash_erase(target *t, target_addr addr, size_t len);
|
||||||
|
@ -140,7 +153,7 @@ int target_flash_write(target *t, target_addr dest, const void *src, size_t len)
|
||||||
int target_flash_done(target *t);
|
int target_flash_done(target *t);
|
||||||
|
|
||||||
/* Accessor functions */
|
/* Accessor functions */
|
||||||
int target_regs_size(target *t);
|
size_t target_regs_size(target *t);
|
||||||
const char *target_tdesc(target *t);
|
const char *target_tdesc(target *t);
|
||||||
const char *target_mem_map(target *t);
|
const char *target_mem_map(target *t);
|
||||||
const char *target_driver_name(target *t);
|
const char *target_driver_name(target *t);
|
||||||
|
|
|
@ -35,12 +35,6 @@
|
||||||
|
|
||||||
static char cortexa_driver_str[] = "ARM Cortex-A";
|
static char cortexa_driver_str[] = "ARM Cortex-A";
|
||||||
|
|
||||||
/* Signals returned by cortexa_halt_wait() */
|
|
||||||
#define SIGINT 2
|
|
||||||
#define SIGTRAP 5
|
|
||||||
#define SIGSEGV 11
|
|
||||||
#define SIGLOST 29
|
|
||||||
|
|
||||||
static bool cortexa_attach(target *t);
|
static bool cortexa_attach(target *t);
|
||||||
static void cortexa_detach(target *t);
|
static void cortexa_detach(target *t);
|
||||||
static void cortexa_halt_resume(target *t, bool step);
|
static void cortexa_halt_resume(target *t, bool step);
|
||||||
|
@ -51,7 +45,7 @@ static void cortexa_regs_read_internal(target *t);
|
||||||
static void cortexa_regs_write_internal(target *t);
|
static void cortexa_regs_write_internal(target *t);
|
||||||
|
|
||||||
static void cortexa_reset(target *t);
|
static void cortexa_reset(target *t);
|
||||||
static int cortexa_halt_wait(target *t);
|
static enum target_halt_reason cortexa_halt_poll(target *t, target_addr *watch);
|
||||||
static void cortexa_halt_request(target *t);
|
static void cortexa_halt_request(target *t);
|
||||||
|
|
||||||
static int cortexa_set_hw_bp(target *t, target_addr addr, uint8_t len);
|
static int cortexa_set_hw_bp(target *t, target_addr addr, uint8_t len);
|
||||||
|
@ -395,7 +389,7 @@ bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base)
|
||||||
|
|
||||||
t->reset = cortexa_reset;
|
t->reset = cortexa_reset;
|
||||||
t->halt_request = cortexa_halt_request;
|
t->halt_request = cortexa_halt_request;
|
||||||
t->halt_wait = cortexa_halt_wait;
|
t->halt_poll = cortexa_halt_poll;
|
||||||
t->halt_resume = cortexa_halt_resume;
|
t->halt_resume = cortexa_halt_resume;
|
||||||
t->regs_size = sizeof(priv->reg_cache);
|
t->regs_size = sizeof(priv->reg_cache);
|
||||||
|
|
||||||
|
@ -422,7 +416,7 @@ bool cortexa_attach(target *t)
|
||||||
|
|
||||||
target_halt_request(t);
|
target_halt_request(t);
|
||||||
tries = 10;
|
tries = 10;
|
||||||
while(!platform_srst_get_val() && !target_halt_wait(t) && --tries)
|
while(!platform_srst_get_val() && !target_halt_poll(t, NULL) && --tries)
|
||||||
platform_delay(200);
|
platform_delay(200);
|
||||||
if(!tries)
|
if(!tries)
|
||||||
return false;
|
return false;
|
||||||
|
@ -586,8 +580,10 @@ static void cortexa_halt_request(target *t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cortexa_halt_wait(target *t)
|
static enum target_halt_reason cortexa_halt_poll(target *t, target_addr *watch)
|
||||||
{
|
{
|
||||||
|
(void)watch; /* No watchpoint support yet */
|
||||||
|
|
||||||
volatile uint32_t dbgdscr = 0;
|
volatile uint32_t dbgdscr = 0;
|
||||||
volatile struct exception e;
|
volatile struct exception e;
|
||||||
TRY_CATCH (e, EXCEPTION_ALL) {
|
TRY_CATCH (e, EXCEPTION_ALL) {
|
||||||
|
@ -599,14 +595,14 @@ static int cortexa_halt_wait(target *t)
|
||||||
case EXCEPTION_ERROR:
|
case EXCEPTION_ERROR:
|
||||||
/* Oh crap, there's no recovery from this... */
|
/* Oh crap, there's no recovery from this... */
|
||||||
target_list_free();
|
target_list_free();
|
||||||
return SIGLOST;
|
return TARGET_HALT_ERROR;
|
||||||
case EXCEPTION_TIMEOUT:
|
case EXCEPTION_TIMEOUT:
|
||||||
/* Timeout isn't a problem, target could be in WFI */
|
/* Timeout isn't a problem, target could be in WFI */
|
||||||
return 0;
|
return TARGET_HALT_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dbgdscr & DBGDSCR_HALTED)) /* Not halted */
|
if (!(dbgdscr & DBGDSCR_HALTED)) /* Not halted */
|
||||||
return 0;
|
return TARGET_HALT_RUNNING;
|
||||||
|
|
||||||
DEBUG("%s: DBGDSCR = 0x%08x\n", __func__, dbgdscr);
|
DEBUG("%s: DBGDSCR = 0x%08x\n", __func__, dbgdscr);
|
||||||
/* Reenable DBGITR */
|
/* Reenable DBGITR */
|
||||||
|
@ -614,18 +610,18 @@ static int cortexa_halt_wait(target *t)
|
||||||
apb_write(t, DBGDSCR, dbgdscr);
|
apb_write(t, DBGDSCR, dbgdscr);
|
||||||
|
|
||||||
/* Find out why we halted */
|
/* Find out why we halted */
|
||||||
int sig;
|
enum target_halt_reason reason;
|
||||||
switch (dbgdscr & DBGDSCR_MOE_MASK) {
|
switch (dbgdscr & DBGDSCR_MOE_MASK) {
|
||||||
case DBGDSCR_MOE_HALT_REQ:
|
case DBGDSCR_MOE_HALT_REQ:
|
||||||
sig = SIGINT;
|
reason = TARGET_HALT_REQUEST;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sig = SIGTRAP;
|
reason = TARGET_HALT_BREAKPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
cortexa_regs_read_internal(t);
|
cortexa_regs_read_internal(t);
|
||||||
|
|
||||||
return sig;
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cortexa_halt_resume(target *t, bool step)
|
void cortexa_halt_resume(target *t, bool step)
|
||||||
|
|
|
@ -47,18 +47,12 @@ const struct command_s cortexm_cmd_list[] = {
|
||||||
#define TOPT_FLAVOUR_V6M (1<<0) /* if not set, target is assumed to be v7m */
|
#define TOPT_FLAVOUR_V6M (1<<0) /* if not set, target is assumed to be v7m */
|
||||||
#define TOPT_FLAVOUR_V7MF (1<<1) /* if set, floating-point enabled. */
|
#define TOPT_FLAVOUR_V7MF (1<<1) /* if set, floating-point enabled. */
|
||||||
|
|
||||||
/* Signals returned by cortexm_halt_wait() */
|
|
||||||
#define SIGINT 2
|
|
||||||
#define SIGTRAP 5
|
|
||||||
#define SIGSEGV 11
|
|
||||||
#define SIGLOST 29
|
|
||||||
|
|
||||||
static void cortexm_regs_read(target *t, void *data);
|
static void cortexm_regs_read(target *t, void *data);
|
||||||
static void cortexm_regs_write(target *t, const void *data);
|
static void cortexm_regs_write(target *t, const void *data);
|
||||||
static uint32_t cortexm_pc_read(target *t);
|
static uint32_t cortexm_pc_read(target *t);
|
||||||
|
|
||||||
static void cortexm_reset(target *t);
|
static void cortexm_reset(target *t);
|
||||||
static int cortexm_halt_wait(target *t);
|
static enum target_halt_reason cortexm_halt_poll(target *t, target_addr *watch);
|
||||||
static void cortexm_halt_request(target *t);
|
static void cortexm_halt_request(target *t);
|
||||||
static int cortexm_fault_unwind(target *t);
|
static int cortexm_fault_unwind(target *t);
|
||||||
|
|
||||||
|
@ -68,7 +62,7 @@ static int cortexm_clear_hw_bp(target *t, target_addr addr, uint8_t len);
|
||||||
static int cortexm_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len);
|
static int cortexm_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len);
|
||||||
static int cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len);
|
static int cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len);
|
||||||
|
|
||||||
static int cortexm_check_hw_wp(target *t, target_addr *addr);
|
static target_addr cortexm_check_watch(target *t);
|
||||||
|
|
||||||
#define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */
|
#define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */
|
||||||
#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */
|
#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */
|
||||||
|
@ -242,7 +236,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
|
||||||
|
|
||||||
t->reset = cortexm_reset;
|
t->reset = cortexm_reset;
|
||||||
t->halt_request = cortexm_halt_request;
|
t->halt_request = cortexm_halt_request;
|
||||||
t->halt_wait = cortexm_halt_wait;
|
t->halt_poll = cortexm_halt_poll;
|
||||||
t->halt_resume = cortexm_halt_resume;
|
t->halt_resume = cortexm_halt_resume;
|
||||||
t->regs_size = sizeof(regnum_cortex_m);
|
t->regs_size = sizeof(regnum_cortex_m);
|
||||||
|
|
||||||
|
@ -295,7 +289,7 @@ bool cortexm_attach(target *t)
|
||||||
|
|
||||||
target_halt_request(t);
|
target_halt_request(t);
|
||||||
tries = 10;
|
tries = 10;
|
||||||
while(!platform_srst_get_val() && !target_halt_wait(t) && --tries)
|
while(!platform_srst_get_val() && !target_halt_poll(t, NULL) && --tries)
|
||||||
platform_delay(200);
|
platform_delay(200);
|
||||||
if(!tries)
|
if(!tries)
|
||||||
return false;
|
return false;
|
||||||
|
@ -338,7 +332,6 @@ bool cortexm_attach(target *t)
|
||||||
/* Data Watchpoint and Trace */
|
/* Data Watchpoint and Trace */
|
||||||
t->set_hw_wp = cortexm_set_hw_wp;
|
t->set_hw_wp = cortexm_set_hw_wp;
|
||||||
t->clear_hw_wp = cortexm_clear_hw_wp;
|
t->clear_hw_wp = cortexm_clear_hw_wp;
|
||||||
t->check_hw_wp = cortexm_check_hw_wp;
|
|
||||||
|
|
||||||
platform_srst_set_val(false);
|
platform_srst_set_val(false);
|
||||||
|
|
||||||
|
@ -480,7 +473,7 @@ static void cortexm_halt_request(target *t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cortexm_halt_wait(target *t)
|
static enum target_halt_reason cortexm_halt_poll(target *t, target_addr *watch)
|
||||||
{
|
{
|
||||||
struct cortexm_priv *priv = t->priv;
|
struct cortexm_priv *priv = t->priv;
|
||||||
|
|
||||||
|
@ -495,21 +488,21 @@ static int cortexm_halt_wait(target *t)
|
||||||
case EXCEPTION_ERROR:
|
case EXCEPTION_ERROR:
|
||||||
/* Oh crap, there's no recovery from this... */
|
/* Oh crap, there's no recovery from this... */
|
||||||
target_list_free();
|
target_list_free();
|
||||||
return SIGLOST;
|
return TARGET_HALT_ERROR;
|
||||||
case EXCEPTION_TIMEOUT:
|
case EXCEPTION_TIMEOUT:
|
||||||
/* Timeout isn't a problem, target could be in WFI */
|
/* Timeout isn't a problem, target could be in WFI */
|
||||||
return 0;
|
return TARGET_HALT_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dhcsr & CORTEXM_DHCSR_S_HALT))
|
if (!(dhcsr & CORTEXM_DHCSR_S_HALT))
|
||||||
return 0;
|
return TARGET_HALT_RUNNING;
|
||||||
|
|
||||||
/* We've halted. Let's find out why. */
|
/* We've halted. Let's find out why. */
|
||||||
uint32_t dfsr = target_mem_read32(t, CORTEXM_DFSR);
|
uint32_t dfsr = target_mem_read32(t, CORTEXM_DFSR);
|
||||||
target_mem_write32(t, CORTEXM_DFSR, dfsr); /* write back to reset */
|
target_mem_write32(t, CORTEXM_DFSR, dfsr); /* write back to reset */
|
||||||
|
|
||||||
if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(t))
|
if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(t))
|
||||||
return SIGSEGV;
|
return TARGET_HALT_FAULT;
|
||||||
|
|
||||||
/* Remember if we stopped on a breakpoint */
|
/* Remember if we stopped on a breakpoint */
|
||||||
priv->on_bkpt = dfsr & (CORTEXM_DFSR_BKPT);
|
priv->on_bkpt = dfsr & (CORTEXM_DFSR_BKPT);
|
||||||
|
@ -521,7 +514,7 @@ static int cortexm_halt_wait(target *t)
|
||||||
bkpt_instr = target_mem_read16(t, pc);
|
bkpt_instr = target_mem_read16(t, pc);
|
||||||
if (bkpt_instr == 0xBEAB) {
|
if (bkpt_instr == 0xBEAB) {
|
||||||
if (cortexm_hostio_request(t)) {
|
if (cortexm_hostio_request(t)) {
|
||||||
return SIGINT;
|
return TARGET_HALT_REQUEST;
|
||||||
} else {
|
} else {
|
||||||
target_halt_resume(t, priv->stepping);
|
target_halt_resume(t, priv->stepping);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -529,14 +522,18 @@ static int cortexm_halt_wait(target *t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dfsr & (CORTEXM_DFSR_BKPT | CORTEXM_DFSR_DWTTRAP))
|
if (dfsr & CORTEXM_DFSR_DWTTRAP) {
|
||||||
return SIGTRAP;
|
if (watch != NULL)
|
||||||
|
*watch = cortexm_check_watch(t);
|
||||||
|
return TARGET_HALT_WATCHPOINT;
|
||||||
|
}
|
||||||
|
if (dfsr & CORTEXM_DFSR_BKPT)
|
||||||
|
return TARGET_HALT_BREAKPOINT;
|
||||||
|
|
||||||
if (dfsr & CORTEXM_DFSR_HALTED)
|
if (dfsr & CORTEXM_DFSR_HALTED)
|
||||||
return priv->stepping ? SIGTRAP : SIGINT;
|
return priv->stepping ? TARGET_HALT_STEPPING : TARGET_HALT_REQUEST;
|
||||||
|
|
||||||
return SIGTRAP;
|
|
||||||
|
|
||||||
|
return TARGET_HALT_BREAKPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cortexm_halt_resume(target *t, bool step)
|
void cortexm_halt_resume(target *t, bool step)
|
||||||
|
@ -642,7 +639,7 @@ int cortexm_run_stub(target *t, uint32_t loadaddr,
|
||||||
|
|
||||||
/* Execute the stub */
|
/* Execute the stub */
|
||||||
cortexm_halt_resume(t, 0);
|
cortexm_halt_resume(t, 0);
|
||||||
while (!cortexm_halt_wait(t))
|
while (!cortexm_halt_poll(t, NULL))
|
||||||
;
|
;
|
||||||
|
|
||||||
uint32_t pc = cortexm_pc_read(t);
|
uint32_t pc = cortexm_pc_read(t);
|
||||||
|
@ -779,7 +776,7 @@ cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cortexm_check_hw_wp(target *t, target_addr *addr)
|
static target_addr cortexm_check_watch(target *t)
|
||||||
{
|
{
|
||||||
struct cortexm_priv *priv = t->priv;
|
struct cortexm_priv *priv = t->priv;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -793,8 +790,7 @@ static int cortexm_check_hw_wp(target *t, target_addr *addr)
|
||||||
|
|
||||||
if(i == priv->hw_watchpoint_max) return 0;
|
if(i == priv->hw_watchpoint_max) return 0;
|
||||||
|
|
||||||
*addr = priv->hw_watchpoint[i].addr;
|
return priv->hw_watchpoint[i].addr;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
||||||
|
|
|
@ -82,7 +82,7 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...)
|
||||||
|
|
||||||
/* start the target and wait for it to halt again */
|
/* start the target and wait for it to halt again */
|
||||||
target_halt_resume(t, false);
|
target_halt_resume(t, false);
|
||||||
while (!target_halt_wait(t));
|
while (!target_halt_poll(t, NULL));
|
||||||
|
|
||||||
/* copy back just the parameters structure */
|
/* copy back just the parameters structure */
|
||||||
target_mem_read(t, ¶m, f->iap_ram, sizeof(param));
|
target_mem_read(t, ¶m, f->iap_ram, sizeof(param));
|
||||||
|
|
|
@ -305,47 +305,52 @@ void target_regs_write(target *t, const void *data) { t->regs_write(t, data); }
|
||||||
/* Halt/resume functions */
|
/* Halt/resume functions */
|
||||||
void target_reset(target *t) { t->reset(t); }
|
void target_reset(target *t) { t->reset(t); }
|
||||||
void target_halt_request(target *t) { t->halt_request(t); }
|
void target_halt_request(target *t) { t->halt_request(t); }
|
||||||
int target_halt_wait(target *t) { return t->halt_wait(t); }
|
enum target_halt_reason target_halt_poll(target *t, target_addr *watch)
|
||||||
|
{
|
||||||
|
return t->halt_poll(t, watch);
|
||||||
|
}
|
||||||
|
|
||||||
void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); }
|
void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); }
|
||||||
|
|
||||||
/* Break-/watchpoint functions */
|
/* Break-/watchpoint functions */
|
||||||
int target_set_hw_bp(target *t, target_addr addr, uint8_t len)
|
int target_breakwatch_set(target *t,
|
||||||
|
enum target_breakwatch type, target_addr addr, size_t len)
|
||||||
{
|
{
|
||||||
if (t->set_hw_bp == NULL)
|
switch (type) {
|
||||||
return 0;
|
case TARGET_BREAK_HARD:
|
||||||
return t->set_hw_bp(t, addr, len);
|
if (t->set_hw_bp)
|
||||||
|
return t->set_hw_bp(t, addr, len);
|
||||||
|
case TARGET_WATCH_WRITE:
|
||||||
|
case TARGET_WATCH_READ:
|
||||||
|
case TARGET_WATCH_ACCESS:
|
||||||
|
if (t->set_hw_wp)
|
||||||
|
return t->set_hw_wp(t, type, addr, len);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int target_clear_hw_bp(target *t, target_addr addr, uint8_t len)
|
int target_breakwatch_clear(target *t,
|
||||||
|
enum target_breakwatch type, target_addr addr, size_t len)
|
||||||
{
|
{
|
||||||
if (t->clear_hw_bp == NULL)
|
switch (type) {
|
||||||
return 0;
|
case TARGET_BREAK_HARD:
|
||||||
return t->clear_hw_bp(t, addr, len);
|
if (t->set_hw_bp)
|
||||||
}
|
return t->set_hw_bp(t, addr, len);
|
||||||
|
case TARGET_WATCH_WRITE:
|
||||||
int target_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len)
|
case TARGET_WATCH_READ:
|
||||||
{
|
case TARGET_WATCH_ACCESS:
|
||||||
if (t->set_hw_wp == NULL)
|
if (t->set_hw_wp)
|
||||||
return 0;
|
return t->set_hw_wp(t, type, addr, len);
|
||||||
return t->set_hw_wp(t, type, addr, len);
|
default:
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
int target_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len)
|
return 1;
|
||||||
{
|
|
||||||
if (t->clear_hw_wp == NULL)
|
|
||||||
return 0;
|
|
||||||
return t->clear_hw_wp(t, type, addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int target_check_hw_wp(target *t, target_addr *addr)
|
|
||||||
{
|
|
||||||
if (t->check_hw_wp == NULL)
|
|
||||||
return 0;
|
|
||||||
return t->check_hw_wp(t, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accessor functions */
|
/* Accessor functions */
|
||||||
int target_regs_size(target *t)
|
size_t target_regs_size(target *t)
|
||||||
{
|
{
|
||||||
return t->regs_size;
|
return t->regs_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ struct target_s {
|
||||||
const void *src, size_t len);
|
const void *src, size_t len);
|
||||||
|
|
||||||
/* Register access functions */
|
/* Register access functions */
|
||||||
int regs_size;
|
size_t regs_size;
|
||||||
const char *tdesc;
|
const char *tdesc;
|
||||||
void (*regs_read)(target *t, void *data);
|
void (*regs_read)(target *t, void *data);
|
||||||
void (*regs_write)(target *t, const void *data);
|
void (*regs_write)(target *t, const void *data);
|
||||||
|
@ -92,7 +92,7 @@ struct target_s {
|
||||||
/* Halt/resume functions */
|
/* Halt/resume functions */
|
||||||
void (*reset)(target *t);
|
void (*reset)(target *t);
|
||||||
void (*halt_request)(target *t);
|
void (*halt_request)(target *t);
|
||||||
int (*halt_wait)(target *t);
|
enum target_halt_reason (*halt_poll)(target *t, target_addr *watch);
|
||||||
void (*halt_resume)(target *t, bool step);
|
void (*halt_resume)(target *t, bool step);
|
||||||
|
|
||||||
/* Break-/watchpoint functions */
|
/* Break-/watchpoint functions */
|
||||||
|
@ -102,8 +102,6 @@ struct target_s {
|
||||||
int (*set_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len);
|
int (*set_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len);
|
||||||
int (*clear_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len);
|
int (*clear_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len);
|
||||||
|
|
||||||
int (*check_hw_wp)(target *t, target_addr *addr);
|
|
||||||
|
|
||||||
/* target-defined options */
|
/* target-defined options */
|
||||||
unsigned target_options;
|
unsigned target_options;
|
||||||
uint32_t idcode;
|
uint32_t idcode;
|
||||||
|
|
Loading…
Reference in New Issue