Moved breakpoint table into device base structure.

Breakpoints only ever change by debugger control, so there's no point
having a device-dependent "getbrk" method. Breakpoint update need only
be done before starting the device running.
This commit is contained in:
Daniel Beer 2010-07-27 13:08:21 +12:00
parent 444b09da79
commit 3f6d8f91ad
8 changed files with 182 additions and 203 deletions

View File

@ -56,7 +56,7 @@ install: mspdebug mspdebug.man
mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \
util.o bsl.o sim.o symmap.o gdb.o btree.o rtools.o sym.o devcmd.o \
cproc.o vector.o cproc_util.o expr.o fet_error.o binfile.o fet_db.o \
usbutil.o titext.o srec.o
usbutil.o titext.o srec.o device.o
$(CC) $(LDFLAGS) $(MACPORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)
.c.o:

17
bsl.c
View File

@ -222,18 +222,6 @@ static device_status_t bsl_poll(device_t dev_base)
return DEVICE_STATUS_HALTED;
}
static int bsl_setbrk(device_t dev_base, int n, int enabled, uint16_t addr)
{
fprintf(stderr, "bsl: breakpoints are not implemented\n");
return -1;
}
static int bsl_getbrk(device_t dev_base, int n, int *enabled, uint16_t *addr)
{
fprintf(stderr, "bsl: breakpoints are not implemented\n");
return -1;
}
static int bsl_getregs(device_t dev_base, uint16_t *regs)
{
fprintf(stderr, "bsl: register fetch is not implemented\n");
@ -327,14 +315,13 @@ device_t bsl_open(const char *device)
return NULL;
}
dev->base.max_breakpoints = 0;
memset(dev, 0, sizeof(*dev));
dev->base.destroy = bsl_destroy;
dev->base.readmem = bsl_readmem;
dev->base.writemem = bsl_writemem;
dev->base.getregs = bsl_getregs;
dev->base.setregs = bsl_setregs;
dev->base.setbrk = bsl_setbrk;
dev->base.getbrk = bsl_getbrk;
dev->base.ctl = bsl_ctl;
dev->base.poll = bsl_poll;

View File

@ -559,7 +559,7 @@ static int cmd_setbreak(cproc_t cp, char **arg)
stab_t stab = cproc_stab(cp);
char *addr_text = get_arg(arg);
char *index_text = get_arg(arg);
int index;
int index = -1;
int addr;
if (!addr_text) {
@ -574,29 +574,22 @@ static int cmd_setbreak(cproc_t cp, char **arg)
if (index_text) {
index = atoi(index_text);
} else {
int i;
for (i = 0; i < dev->max_breakpoints; i++) {
int enabled;
if (!dev->getbrk(dev, i, &enabled, NULL) &&
!enabled)
break;
}
if (i >= dev->max_breakpoints) {
fprintf(stderr, "setbreak: all breakpoint slots are "
"occupied\n");
if (index < 0 || index >= dev->max_breakpoints) {
fprintf(stderr, "setbreak: invalid breakpoint "
"slot: %d\n", index);
return -1;
}
index = i;
}
printf("Setting breakpoint %d\n", index);
dev->setbrk(dev, index, 1, addr);
index = device_setbrk(dev, index, 1, addr);
if (index < 0) {
fprintf(stderr, "setbreak: all breakpoint slots are "
"occupied\n");
return -1;
}
printf("Set breakpoint %d\n", index);
return 0;
}
@ -609,15 +602,20 @@ static int cmd_delbreak(cproc_t cp, char **arg)
if (index_text) {
int index = atoi(index_text);
if (index < 0 || index >= dev->max_breakpoints) {
fprintf(stderr, "delbreak: invalid breakpoint "
"slot: %d\n", index);
return -1;
}
printf("Clearing breakpoint %d\n", index);
ret = dev->setbrk(dev, index, 0, 0);
device_setbrk(dev, index, 0, 0);
} else {
int i;
printf("Clearing all breakpoints...\n");
for (i = 0; i < dev->max_breakpoints; i++)
if (dev->setbrk(dev, i, 0, 0) < 0)
ret = -1;
device_setbrk(dev, i, 0, 0);
}
return ret;
@ -631,15 +629,14 @@ static int cmd_break(cproc_t cp, char **arg)
printf("%d breakpoints available:\n", dev->max_breakpoints);
for (i = 0; i < dev->max_breakpoints; i++) {
int enabled;
uint16_t addr;
const struct device_breakpoint *bp = &dev->breakpoints[i];
if (!dev->getbrk(dev, i, &enabled, &addr) && enabled) {
if (bp->flags & DEVICE_BP_ENABLED) {
char name[128];
uint16_t offset;
printf(" %d. 0x%04x", i, addr);
if (!stab_nearest(stab, addr, name,
printf(" %d. 0x%04x", i, bp->addr);
if (!stab_nearest(stab, bp->addr, name,
sizeof(name), &offset)) {
printf(" (%s", name);
if (offset)

85
device.c Normal file
View File

@ -0,0 +1,85 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2009, 2010 Daniel Beer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "device.h"
static int addbrk(device_t dev, uint16_t addr)
{
int i;
int which = -1;
struct device_breakpoint *bp;
for (i = 0; i < dev->max_breakpoints; i++) {
bp = &dev->breakpoints[i];
if (bp->flags & DEVICE_BP_ENABLED) {
if (bp->addr == addr)
return i;
} else if (which < 0) {
which = i;
}
}
if (which < 0)
return -1;
bp = &dev->breakpoints[which];
bp->flags = DEVICE_BP_ENABLED | DEVICE_BP_DIRTY;
bp->addr = addr;
return which;
}
static void delbrk(device_t dev, uint16_t addr)
{
int i;
for (i = 0; i < dev->max_breakpoints; i++) {
struct device_breakpoint *bp = &dev->breakpoints[i];
if ((bp->flags & DEVICE_BP_ENABLED) &&
bp->addr == addr) {
bp->flags = DEVICE_BP_DIRTY;
bp->addr = 0;
}
}
}
int device_setbrk(device_t dev, int which, int enabled, uint16_t addr)
{
if (which < 0) {
if (enabled)
return addbrk(dev, addr);
delbrk(dev, addr);
} else {
struct device_breakpoint *bp = &dev->breakpoints[which];
int new_flags = enabled ? DEVICE_BP_ENABLED : 0;
if (!enabled)
addr = 0;
if (bp->addr != addr ||
(bp->flags & DEVICE_BP_ENABLED) != new_flags) {
bp->flags = new_flags | DEVICE_BP_DIRTY;
bp->addr = addr;
}
}
return 0;
}

View File

@ -40,9 +40,24 @@ typedef enum {
} device_status_t;
#define DEVICE_NUM_REGS 16
#define DEVICE_MAX_BREAKPOINTS 32
#define DEVICE_BP_ENABLED 0x01
#define DEVICE_BP_DIRTY 0x02
struct device_breakpoint {
uint16_t addr;
int flags;
};
struct device {
/* Breakpoint table. This should not be modified directly.
* Instead, you should use the device_setbrk() helper function. This
* will set the appropriate flags and ensure that the breakpoint is
* reloaded before the next run.
*/
int max_breakpoints;
struct device_breakpoint breakpoints[DEVICE_MAX_BREAKPOINTS];
/* Close the connection to the device and destroy the driver object */
void (*destroy)(device_t dev);
@ -57,10 +72,6 @@ struct device {
int (*getregs)(device_t dev, uint16_t *regs);
int (*setregs)(device_t dev, const uint16_t *regs);
/* Breakpoint control */
int (*setbrk)(device_t dev, int n, int enabled, uint16_t addr);
int (*getbrk)(device_t dev, int n, int *enabled, uint16_t *addr);
/* CPU control */
int (*ctl)(device_t dev, device_ctl_t op);
@ -68,4 +79,14 @@ struct device {
device_status_t (*poll)(device_t dev);
};
/* Set or clear a breakpoint. The index of the modified entry is
* returned, or -1 if no free entries were available. The modified
* entry is flagged so that it will be reloaded on the next run.
*
* If which is specified, a particular breakpoint slot is
* modified. Otherwise, if which < 0, breakpoint slots are selected
* automatically.
*/
int device_setbrk(device_t dev, int which, int enabled, uint16_t address);
#endif

92
fet.c
View File

@ -33,12 +33,6 @@
#include "fet_db.h"
#define MAX_PARAMS 16
#define MAX_BREAKPOINTS 16
struct fet_bp {
int enabled;
uint16_t addr;
};
struct fet_device {
struct device base;
@ -47,9 +41,6 @@ struct fet_device {
int proto_flags;
int version;
/* Breakpoint array */
struct fet_bp bps[MAX_BREAKPOINTS];
/* Device-specific information */
u_int16_t code_start;
@ -627,6 +618,33 @@ static device_status_t fet_poll(device_t dev_base)
return DEVICE_STATUS_RUNNING;
}
static int refresh_bps(struct fet_device *dev)
{
int i;
int ret = 0;
for (i = 0; i < dev->base.max_breakpoints; i++) {
struct device_breakpoint *bp = &dev->base.breakpoints[i];
if (bp->flags & DEVICE_BP_DIRTY) {
uint16_t addr = bp->addr;
if (!(bp->flags & DEVICE_BP_ENABLED))
addr = 0;
if (xfer(dev, C_BREAKPOINT, NULL, 0, 2, i, addr) < 0) {
fprintf(stderr, "fet: failed to refresh "
"breakpoint #%d\n", i);
ret = -1;
} else {
bp->flags &= ~DEVICE_BP_DIRTY;
}
}
}
return ret;
}
static int fet_ctl(device_t dev_base, device_ctl_t action)
{
struct fet_device *dev = (struct fet_device *)dev_base;
@ -640,6 +658,9 @@ static int fet_ctl(device_t dev_base, device_ctl_t action)
break;
case DEVICE_CTL_RUN:
if (refresh_bps(dev) < 0)
fprintf(stderr, "warning: fet: failed to refresh "
"breakpoints\n");
return do_run(dev, FET_RUN_BREAKPOINT);
case DEVICE_CTL_HALT:
@ -783,43 +804,6 @@ static int fet_setregs(device_t dev_base, const uint16_t *regs)
return 0;
}
static int fet_setbrk(device_t dev_base, int n, int enabled, uint16_t addr)
{
struct fet_device *dev = (struct fet_device *)dev_base;
if (n < 0 || n > dev_base->max_breakpoints) {
fprintf(stderr, "fet: invalid breakpoint number: %d\n", n);
return -1;
}
if (xfer(dev, C_BREAKPOINT, NULL, 0, 2, n, enabled ? addr : 0) < 0) {
fprintf(stderr, "fet: set breakpoint failed\n");
return -1;
}
dev->bps[n].enabled = enabled;
dev->bps[n].addr = addr;
return 0;
}
static int fet_getbrk(device_t dev_base, int n, int *enabled, uint16_t *addr)
{
struct fet_device *dev = (struct fet_device *)dev_base;
if (n < 0 || n > dev_base->max_breakpoints) {
fprintf(stderr, "fet: invalid breakpoint number: %d\n", n);
return -1;
}
if (enabled)
*enabled = dev->bps[n].enabled;
if (addr)
*addr = dev->bps[n].addr;
return 0;
}
static int do_configure(struct fet_device *dev)
{
if (dev->proto_flags & FET_PROTO_SPYBIWIRE) {
@ -863,23 +847,19 @@ device_t fet_open(transport_t transport, int proto_flags, int vcc_mv,
return NULL;
}
memset(dev, 0, sizeof(*dev));
dev->base.destroy = fet_destroy;
dev->base.readmem = fet_readmem;
dev->base.writemem = fet_writemem;
dev->base.getregs = fet_getregs;
dev->base.setregs = fet_setregs;
dev->base.setbrk = fet_setbrk;
dev->base.getbrk = fet_getbrk;
dev->base.ctl = fet_ctl;
dev->base.poll = fet_poll;
memset(dev->bps, 0, sizeof(dev->bps));
dev->transport = transport;
dev->proto_flags = proto_flags;
dev->fet_len = 0;
if (proto_flags & FET_PROTO_OLIMEX) {
printf("Resetting Olimex command processor...\n");
transport->send(dev->transport, (const uint8_t *)"\x7e", 1);
@ -917,11 +897,11 @@ device_t fet_open(transport_t transport, int proto_flags, int vcc_mv,
goto fail;
}
printf("Resetting all breakpoints...\n");
/* Make sure breakpoints get reset on the first run */
if (dev->base.max_breakpoints > DEVICE_MAX_BREAKPOINTS)
dev->base.max_breakpoints = DEVICE_MAX_BREAKPOINTS;
for (i = 0; i < dev->base.max_breakpoints; i++)
xfer(dev, C_BREAKPOINT, NULL, 0, 2, i, 0);
if (dev->base.max_breakpoints > MAX_BREAKPOINTS)
dev->base.max_breakpoints = MAX_BREAKPOINTS;
dev->base.breakpoints[i].flags = DEVICE_BP_DIRTY;
return (device_t)dev;

55
gdb.c
View File

@ -435,50 +435,6 @@ static int run(struct gdb_data *data, char *buf)
return run_final_status(data);
}
static int add_breakpoint(device_t dev, int addr)
{
int i;
int avail = -1;
for (i = 0; i < dev->max_breakpoints; i++) {
int enabled;
uint16_t ba;
if (!dev->getbrk(dev, i, &enabled, &ba)) {
if (!enabled && avail < 0)
avail = i;
if (enabled && addr == ba) {
fprintf(stderr, "warning: gdb: breakpoint at "
"0x%04x already set", addr);
return 0;
}
}
}
if (avail < 0) {
fprintf(stderr, "gdb: no breakpoint slots available\n");
return -1;
}
return dev->setbrk(dev, avail, 1, addr);
}
static int remove_breakpoint(device_t dev, int addr)
{
int i;
for (i = 0; i < dev->max_breakpoints; i++) {
int enabled;
uint16_t ba;
if (!dev->getbrk(dev, i, &enabled, &ba) && enabled &&
ba == addr && dev->setbrk(dev, i, 0, 0) < 0)
return -1;
}
return 0;
}
static int set_breakpoint(struct gdb_data *data, int enable, char *buf)
{
char *parts[2];
@ -514,7 +470,7 @@ static int set_breakpoint(struct gdb_data *data, int enable, char *buf)
addr = strtoul(parts[1], NULL, 16);
if (enable) {
if (add_breakpoint(data->device, addr) < 0) {
if (device_setbrk(data->device, -1, 1, addr) < 0) {
fprintf(stderr, "gdb: can't add breakpoint at "
"0x%04x\n", addr);
return gdb_send(data, "E00");
@ -522,12 +478,7 @@ static int set_breakpoint(struct gdb_data *data, int enable, char *buf)
printf("Breakpoint set at 0x%04x\n", addr);
} else {
if (remove_breakpoint(data->device, addr) < 0) {
fprintf(stderr, "gdb: can't remove breakpoint at "
"0x%04x\n", addr);
return gdb_send(data, "E00");
}
device_setbrk(data->device, -1, 0, addr);
printf("Breakpoint cleared at 0x%04x\n", addr);
}
@ -695,7 +646,7 @@ static int gdb_server(device_t device, int port)
/* Put the hardware breakpoint setting into a known state. */
printf("Clearing all breakpoints...\n");
for (i = 0; i < device->max_breakpoints; i++)
device->setbrk(device, i, 0, 0);
device_setbrk(device, i, 0, 0);
gdb_reader_loop(&data);

56
sim.c
View File

@ -28,13 +28,6 @@
#define MEM_SIZE 65536
#define MEM_IO_END 0x200
#define NUM_BREAKPOINTS 8
struct sim_bp {
int enabled;
uint16_t addr;
};
struct sim_device {
struct device base;
@ -47,8 +40,6 @@ struct sim_device {
int running;
uint16_t current_insn;
struct sim_bp bps[NUM_BREAKPOINTS];
};
#define MEM_GETB(dev, offset) ((dev)->memory[offset])
@ -489,38 +480,6 @@ static int sim_setregs(device_t dev_base, const uint16_t *regs)
return 0;
}
static int sim_setbrk(device_t dev_base, int n, int enabled, uint16_t addr)
{
struct sim_device *dev = (struct sim_device *)dev_base;
if (n < 0 || n > NUM_BREAKPOINTS) {
fprintf(stderr, "sim: invalid breakpoint number: %d\n", n);
return -1;
}
dev->bps[n].enabled = enabled;
dev->bps[n].addr = addr;
return 0;
}
static int sim_getbrk(device_t dev_base, int n, int *enabled, uint16_t *addr)
{
struct sim_device *dev = (struct sim_device *)dev_base;
if (n < 0 || n > NUM_BREAKPOINTS) {
fprintf(stderr, "sim: invalid breakpoint number: %d\n", n);
return -1;
}
if (enabled)
*enabled = dev->bps[n].enabled;
if (addr)
*addr = dev->bps[n].addr;
return 0;
}
static int sim_ctl(device_t dev_base, device_ctl_t op)
{
struct sim_device *dev = (struct sim_device *)dev_base;
@ -562,10 +521,11 @@ static device_status_t sim_poll(device_t dev_base)
while (count > 0) {
int i;
for (i = 0; i < NUM_BREAKPOINTS; i++) {
struct sim_bp *bp = &dev->bps[i];
for (i = 0; i < dev->base.max_breakpoints; i++) {
struct device_breakpoint *bp =
&dev->base.breakpoints[i];
if (bp->enabled &&
if ((bp->flags & DEVICE_BP_ENABLED) &&
dev->regs[MSP430_REG_PC] == bp->addr) {
dev->running = 0;
return DEVICE_STATUS_HALTED;
@ -603,14 +563,14 @@ device_t sim_open(sim_fetch_func_t fetch_func,
return NULL;
}
dev->base.max_breakpoints = NUM_BREAKPOINTS;
memset(dev, 0, sizeof(*dev));
dev->base.max_breakpoints = DEVICE_MAX_BREAKPOINTS;
dev->base.destroy = sim_destroy;
dev->base.readmem = sim_readmem;
dev->base.writemem = sim_writemem;
dev->base.getregs = sim_getregs;
dev->base.setregs = sim_setregs;
dev->base.setbrk = sim_setbrk;
dev->base.getbrk = sim_getbrk;
dev->base.ctl = sim_ctl;
dev->base.poll = sim_poll;
@ -624,8 +584,6 @@ device_t sim_open(sim_fetch_func_t fetch_func,
dev->running = 0;
dev->current_insn = 0;
memset(dev->bps, 0, sizeof(dev->bps));
printf("Simulation started, 0x%x bytes of RAM\n", MEM_SIZE);
return (device_t)dev;
}