Watchpoint support (only implemented for tilib driver).
This commit is contained in:
parent
a914bc732d
commit
a354116441
|
@ -20,7 +20,7 @@
|
|||
|
||||
device_t device_default;
|
||||
|
||||
static int addbrk(device_t dev, uint16_t addr)
|
||||
static int addbrk(device_t dev, uint16_t addr, device_bptype_t type)
|
||||
{
|
||||
int i;
|
||||
int which = -1;
|
||||
|
@ -30,7 +30,7 @@ static int addbrk(device_t dev, uint16_t addr)
|
|||
bp = &dev->breakpoints[i];
|
||||
|
||||
if (bp->flags & DEVICE_BP_ENABLED) {
|
||||
if (bp->addr == addr)
|
||||
if (bp->addr == addr && bp->type == type)
|
||||
return i;
|
||||
} else if (which < 0) {
|
||||
which = i;
|
||||
|
@ -43,11 +43,12 @@ static int addbrk(device_t dev, uint16_t addr)
|
|||
bp = &dev->breakpoints[which];
|
||||
bp->flags = DEVICE_BP_ENABLED | DEVICE_BP_DIRTY;
|
||||
bp->addr = addr;
|
||||
bp->type = type;
|
||||
|
||||
return which;
|
||||
}
|
||||
|
||||
static void delbrk(device_t dev, uint16_t addr)
|
||||
static void delbrk(device_t dev, uint16_t addr, device_bptype_t type)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -55,20 +56,21 @@ static void delbrk(device_t dev, uint16_t addr)
|
|||
struct device_breakpoint *bp = &dev->breakpoints[i];
|
||||
|
||||
if ((bp->flags & DEVICE_BP_ENABLED) &&
|
||||
bp->addr == addr) {
|
||||
bp->addr == addr && bp->type == type) {
|
||||
bp->flags = DEVICE_BP_DIRTY;
|
||||
bp->addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int device_setbrk(device_t dev, int which, int enabled, address_t addr)
|
||||
int device_setbrk(device_t dev, int which, int enabled, address_t addr,
|
||||
device_bptype_t type)
|
||||
{
|
||||
if (which < 0) {
|
||||
if (enabled)
|
||||
return addbrk(dev, addr);
|
||||
return addbrk(dev, addr, type);
|
||||
|
||||
delbrk(dev, addr);
|
||||
delbrk(dev, addr, type);
|
||||
} else {
|
||||
struct device_breakpoint *bp = &dev->breakpoints[which];
|
||||
int new_flags = enabled ? DEVICE_BP_ENABLED : 0;
|
||||
|
@ -80,6 +82,7 @@ int device_setbrk(device_t dev, int which, int enabled, address_t addr)
|
|||
(bp->flags & DEVICE_BP_ENABLED) != new_flags) {
|
||||
bp->flags = new_flags | DEVICE_BP_DIRTY;
|
||||
bp->addr = addr;
|
||||
bp->type = type;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,15 @@ typedef enum {
|
|||
#define DEVICE_BP_ENABLED 0x01
|
||||
#define DEVICE_BP_DIRTY 0x02
|
||||
|
||||
typedef enum {
|
||||
DEVICE_BPTYPE_BREAK,
|
||||
DEVICE_BPTYPE_WATCH
|
||||
} device_bptype_t;
|
||||
|
||||
struct device_breakpoint {
|
||||
address_t addr;
|
||||
int flags;
|
||||
device_bptype_t type;
|
||||
address_t addr;
|
||||
int flags;
|
||||
};
|
||||
|
||||
#define DEVICE_FLAG_JTAG 0x01 /* default is SBW */
|
||||
|
@ -122,7 +128,8 @@ struct device {
|
|||
* modified. Otherwise, if which < 0, breakpoint slots are selected
|
||||
* automatically.
|
||||
*/
|
||||
int device_setbrk(device_t dev, int which, int enabled, address_t address);
|
||||
int device_setbrk(device_t dev, int which, int enabled, address_t address,
|
||||
device_bptype_t type);
|
||||
|
||||
extern device_t device_default;
|
||||
|
||||
|
|
|
@ -698,13 +698,15 @@ static int refresh_bps(struct fet_device *dev)
|
|||
for (i = 0; i < dev->base.max_breakpoints; i++) {
|
||||
struct device_breakpoint *bp = &dev->base.breakpoints[i];
|
||||
|
||||
if (bp->flags & DEVICE_BP_DIRTY) {
|
||||
if ((bp->flags & DEVICE_BP_DIRTY) &&
|
||||
bp->type == DEVICE_BPTYPE_BREAK) {
|
||||
uint16_t addr = bp->addr;
|
||||
|
||||
if (!(bp->flags & DEVICE_BP_ENABLED))
|
||||
addr = 0;
|
||||
|
||||
if (xfer(dev, C_BREAKPOINT, NULL, 0, 2, i, addr) < 0) {
|
||||
if (xfer(dev, C_BREAKPOINT, NULL, 0,
|
||||
2, i, addr) < 0) {
|
||||
printc_err("fet: failed to refresh "
|
||||
"breakpoint #%d\n", i);
|
||||
ret = -1;
|
||||
|
|
|
@ -238,6 +238,9 @@ static int refresh_bps(struct gdb_client *dev)
|
|||
if (!(bp->flags & DEVICE_BP_DIRTY))
|
||||
continue;
|
||||
|
||||
if (bp->type != DEVICE_BPTYPE_BREAK)
|
||||
continue;
|
||||
|
||||
if ((old->flags & DEVICE_BP_ENABLED) &&
|
||||
(bp_send(&dev->gdb, 'z', old->addr) < 0))
|
||||
return -1;
|
||||
|
|
|
@ -702,6 +702,7 @@ static device_status_t sim_poll(device_t dev_base)
|
|||
&dev->base.breakpoints[i];
|
||||
|
||||
if ((bp->flags & DEVICE_BP_ENABLED) &&
|
||||
(bp->type == DEVICE_BPTYPE_BREAK) &&
|
||||
dev->regs[MSP430_REG_PC] == bp->addr) {
|
||||
dev->running = 0;
|
||||
return DEVICE_STATUS_HALTED;
|
||||
|
|
|
@ -304,6 +304,46 @@ static int tilib_setregs(device_t dev_base, const address_t *regs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void load_break(BpParameter_t *param, address_t addr)
|
||||
{
|
||||
param->bpMode = BP_CODE;
|
||||
param->lAddrVal = addr;
|
||||
param->bpType = BP_MAB;
|
||||
param->lReg = 0; /* not used */
|
||||
param->bpAccess = BP_FETCH;
|
||||
param->bpAction = BP_BRK;
|
||||
param->bpOperat = BP_EQUAL;
|
||||
param->lMask = 0; /* what's this? */
|
||||
param->lRangeEndAdVa = 0; /* not used */
|
||||
param->bpRangeAction = 0; /* not used */
|
||||
param->bpCondition = BP_NO_COND;
|
||||
param->lCondMdbVal = 0;
|
||||
param->bpCondAccess = BP_FETCH;
|
||||
param->lCondMask = 0; /* what's this? */
|
||||
param->bpCondOperat = BP_EQUAL;
|
||||
param->wExtCombine = 0; /* not used? */
|
||||
}
|
||||
|
||||
static void load_watch(BpParameter_t *param, address_t addr)
|
||||
{
|
||||
param->bpMode = BP_COMPLEX;
|
||||
param->lAddrVal = addr;
|
||||
param->bpType = BP_MAB;
|
||||
param->lReg = 0; /* not used (only for register-write) */
|
||||
param->bpAccess = BP_NO_FETCH;
|
||||
param->bpAction = BP_BRK;
|
||||
param->bpOperat = BP_EQUAL;
|
||||
param->lMask = 0xffffff;
|
||||
param->lRangeEndAdVa = 0; /* not used */
|
||||
param->bpRangeAction = 0; /* not used */
|
||||
param->bpCondition = BP_NO_COND;
|
||||
param->lCondMdbVal = 0;
|
||||
param->bpCondAccess = BP_NO_FETCH;
|
||||
param->lCondMask = 0; /* what's this? */
|
||||
param->bpCondOperat = BP_EQUAL;
|
||||
param->wExtCombine = 0; /* not used? */
|
||||
}
|
||||
|
||||
static int refresh_bps(struct tilib_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
@ -316,22 +356,15 @@ static int refresh_bps(struct tilib_device *dev)
|
|||
continue;
|
||||
|
||||
if (bp->flags & DEVICE_BP_ENABLED) {
|
||||
param.bpMode = BP_CODE;
|
||||
param.lAddrVal = bp->addr;
|
||||
param.bpType = BP_MAB;
|
||||
param.lReg = 0; /* not used */
|
||||
param.bpAccess = BP_FETCH;
|
||||
param.bpAction = BP_BRK;
|
||||
param.bpOperat = BP_EQUAL;
|
||||
param.lMask = 0; /* what's this? */
|
||||
param.lRangeEndAdVa = 0; /* not used */
|
||||
param.bpRangeAction = 0; /* not used */
|
||||
param.bpCondition = BP_NO_COND;
|
||||
param.lCondMdbVal = 0;
|
||||
param.bpCondAccess = BP_FETCH;
|
||||
param.lCondMask = 0; /* what's this? */
|
||||
param.bpCondOperat = BP_EQUAL;
|
||||
param.wExtCombine = 0; /* not used? */
|
||||
switch (bp->type) {
|
||||
case DEVICE_BPTYPE_BREAK:
|
||||
load_break(¶m, bp->addr);
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_WATCH:
|
||||
load_watch(¶m, bp->addr);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
param.bpMode = BP_CLEAR;
|
||||
}
|
||||
|
|
|
@ -153,7 +153,8 @@ Use the Texas Instruments MSP430.DLL to access the device. The library
|
|||
file (MSP430.DLL for Windows, libmsp430.so for Unix-like systems) must
|
||||
be present in the dynamic loader search path.
|
||||
|
||||
USB connection is not supported for this driver.
|
||||
USB connection is not supported for this driver. This driver supports
|
||||
watchpoints.
|
||||
.SH COMMANDS
|
||||
MSPDebug can accept commands either through an interactive prompt, or
|
||||
non-interactively when specified on the command line. The supported
|
||||
|
@ -402,6 +403,11 @@ Add a new breakpoint. The breakpoint location is an address expression. An
|
|||
optional index may be specified, indicating that this new breakpoint should
|
||||
overwrite an existing slot. If no index is specified, then the breakpoint
|
||||
will be stored in the next unused slot.
|
||||
.IP "\fBsetwatch\fR \fIaddress\fR [\fIindex\fR]"
|
||||
Add a new watchpoint. The watchpoint location is an address expression, and
|
||||
an optional index may be specified. Watchpoints are considered to be a type
|
||||
of breakpoint and can be inspected or removed using the \fBbreak\fR and
|
||||
\fBdelbreak\fR commands. Note that not all drivers support watchpoints.
|
||||
.IP "\fBsimio add\fR \fIclass\fR \fIname\fR [\fIargs ...\fR]"
|
||||
Add a new peripheral to the IO simulator. The \fIclass\fR parameter may be
|
||||
any of the peripheral types named in the output of the \fBsimio classes\fR
|
||||
|
|
|
@ -59,6 +59,14 @@ const struct cmddb_record commands[] = {
|
|||
.help =
|
||||
"setbreak <addr> [index]\n"
|
||||
" Set a breakpoint. If no index is specified, the first available\n"
|
||||
" slot will be used.\n"
|
||||
},
|
||||
{
|
||||
.name = "setwatch",
|
||||
.func = cmd_setwatch,
|
||||
.help =
|
||||
"setwatch <addr> [index]\n"
|
||||
" Set a watchpoint. If no index is specified. the first available\n"
|
||||
" slot will be used.\n"
|
||||
},
|
||||
{
|
||||
|
|
33
ui/devcmd.c
33
ui/devcmd.c
|
@ -215,6 +215,7 @@ int cmd_run(char **arg)
|
|||
&device_default->breakpoints[i];
|
||||
|
||||
if ((bp->flags & DEVICE_BP_ENABLED) &&
|
||||
bp->type == DEVICE_BPTYPE_BREAK &&
|
||||
bp->addr == regs[0])
|
||||
break;
|
||||
}
|
||||
|
@ -563,7 +564,7 @@ int cmd_load(char **arg)
|
|||
return do_cmd_prog(arg, 0);
|
||||
}
|
||||
|
||||
int cmd_setbreak(char **arg)
|
||||
static int do_setbreak(device_bptype_t type, char **arg)
|
||||
{
|
||||
char *addr_text = get_arg(arg);
|
||||
char *index_text = get_arg(arg);
|
||||
|
@ -585,14 +586,15 @@ int cmd_setbreak(char **arg)
|
|||
|
||||
if (expr_eval(index_text, &val) < 0 ||
|
||||
val >= device_default->max_breakpoints) {
|
||||
printc("setbreak: invalid breakpoint slot: %d\n", val);
|
||||
printc("setbreak: invalid breakpoint slot: %d\n",
|
||||
val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = val;
|
||||
}
|
||||
|
||||
index = device_setbrk(device_default, index, 1, addr);
|
||||
index = device_setbrk(device_default, index, 1, addr, type);
|
||||
if (index < 0) {
|
||||
printc_err("setbreak: all breakpoint slots are "
|
||||
"occupied\n");
|
||||
|
@ -603,6 +605,16 @@ int cmd_setbreak(char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cmd_setbreak(char **arg)
|
||||
{
|
||||
return do_setbreak(DEVICE_BPTYPE_BREAK, arg);
|
||||
}
|
||||
|
||||
int cmd_setwatch(char **arg)
|
||||
{
|
||||
return do_setbreak(DEVICE_BPTYPE_WATCH, arg);
|
||||
}
|
||||
|
||||
int cmd_delbreak(char **arg)
|
||||
{
|
||||
char *index_text = get_arg(arg);
|
||||
|
@ -619,13 +631,13 @@ int cmd_delbreak(char **arg)
|
|||
}
|
||||
|
||||
printc("Clearing breakpoint %d\n", index);
|
||||
device_setbrk(device_default, index, 0, 0);
|
||||
device_setbrk(device_default, index, 0, 0, 0);
|
||||
} else {
|
||||
int i;
|
||||
|
||||
printc("Clearing all breakpoints...\n");
|
||||
for (i = 0; i < device_default->max_breakpoints; i++)
|
||||
device_setbrk(device_default, i, 0, 0);
|
||||
device_setbrk(device_default, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -637,7 +649,8 @@ int cmd_break(char **arg)
|
|||
|
||||
(void)arg;
|
||||
|
||||
printc("%d breakpoints available:\n", device_default->max_breakpoints);
|
||||
printc("%d breakpoints available:\n",
|
||||
device_default->max_breakpoints);
|
||||
for (i = 0; i < device_default->max_breakpoints; i++) {
|
||||
const struct device_breakpoint *bp =
|
||||
&device_default->breakpoints[i];
|
||||
|
@ -646,7 +659,13 @@ int cmd_break(char **arg)
|
|||
char name[128];
|
||||
|
||||
print_address(bp->addr, name, sizeof(name));
|
||||
printc(" %d. %s\n", i, name);
|
||||
printc(" %d. %s", i, name);
|
||||
|
||||
if (bp->type == DEVICE_BPTYPE_WATCH) {
|
||||
printc(" [watchpoint]\n");
|
||||
} else {
|
||||
printc("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ int cmd_hexout(char **arg);
|
|||
int cmd_prog(char **arg);
|
||||
int cmd_load(char **arg);
|
||||
int cmd_setbreak(char **arg);
|
||||
int cmd_setwatch(char **arg);
|
||||
int cmd_delbreak(char **arg);
|
||||
int cmd_break(char **arg);
|
||||
int cmd_locka(char **arg);
|
||||
|
|
8
ui/gdb.c
8
ui/gdb.c
|
@ -341,7 +341,8 @@ static int set_breakpoint(struct gdb_data *data, int enable, char *buf)
|
|||
addr = strtoul(parts[1], NULL, 16);
|
||||
|
||||
if (enable) {
|
||||
if (device_setbrk(device_default, -1, 1, addr) < 0) {
|
||||
if (device_setbrk(device_default, -1, 1, addr,
|
||||
DEVICE_BPTYPE_BREAK) < 0) {
|
||||
printc_err("gdb: can't add breakpoint at "
|
||||
"0x%04x\n", addr);
|
||||
return gdb_send(data, "E00");
|
||||
|
@ -349,7 +350,8 @@ static int set_breakpoint(struct gdb_data *data, int enable, char *buf)
|
|||
|
||||
printc("Breakpoint set at 0x%04x\n", addr);
|
||||
} else {
|
||||
device_setbrk(device_default, -1, 0, addr);
|
||||
device_setbrk(device_default, -1, 0, addr,
|
||||
DEVICE_BPTYPE_BREAK);
|
||||
printc("Breakpoint cleared at 0x%04x\n", addr);
|
||||
}
|
||||
|
||||
|
@ -502,7 +504,7 @@ static int gdb_server(int port)
|
|||
/* Put the hardware breakpoint setting into a known state. */
|
||||
printc("Clearing all breakpoints...\n");
|
||||
for (i = 0; i < device_default->max_breakpoints; i++)
|
||||
device_setbrk(device_default, i, 0, 0);
|
||||
device_setbrk(device_default, i, 0, 0, 0);
|
||||
|
||||
#ifdef DEBUG_GDB
|
||||
printc("starting GDB reader loop...\n");
|
||||
|
|
Loading…
Reference in New Issue