Drivers are now specified by name, rather than different switches.

This commit is contained in:
Daniel Beer 2010-06-28 14:36:05 +12:00
parent 9dd216e604
commit 8503cc4a85
2 changed files with 211 additions and 181 deletions

291
main.c
View File

@ -118,32 +118,144 @@ static void store_io(void *user_data, uint16_t pc,
printf(" => 0x%04x\n", data);
}
struct cmdline_args {
const char *driver_name;
const char *serial_device;
const char *fet_force_id;
int want_jtag;
int no_rc;
int vcc_mv;
stab_t stab;
};
struct driver {
const char *name;
const char *help;
device_t (*func)(const struct cmdline_args *args);
};
static device_t driver_open_fet(const struct cmdline_args *args,
int flags, transport_t trans)
{
device_t dev;
if (!args->want_jtag)
flags |= FET_PROTO_SPYBIWIRE;
dev = fet_open(trans, flags, args->vcc_mv, args->fet_force_id);
if (!dev) {
trans->destroy(trans);
return NULL;
}
return dev;
}
static device_t driver_open_rf2500(const struct cmdline_args *args)
{
transport_t trans;
if (args->serial_device) {
fprintf(stderr, "This driver does not support tty devices.\n");
return NULL;
}
trans = rf2500_open();
if (!trans)
return NULL;
return driver_open_fet(args, FET_PROTO_RF2500, trans);
}
static device_t driver_open_olimex(const struct cmdline_args *args)
{
transport_t trans;
if (args->serial_device)
trans = uif_open(args->serial_device, 1);
else
trans = olimex_open();
if (!trans)
return NULL;
return driver_open_fet(args, FET_PROTO_OLIMEX, trans);
}
static device_t driver_open_sim(const struct cmdline_args *args)
{
return sim_open(fetch_io, store_io, args->stab);
}
static device_t driver_open_uif(const struct cmdline_args *args)
{
transport_t trans;
if (!args->serial_device) {
fprintf(stderr, "This driver does not support USB access. "
"Specify a tty device using -d.\n");
return NULL;
}
trans = uif_open(args->serial_device, 0);
if (!trans)
return NULL;
return driver_open_fet(args, 0, trans);
}
static device_t driver_open_uif_bsl(const struct cmdline_args *args)
{
if (!args->serial_device) {
fprintf(stderr, "This driver does not support USB access. "
"Specify a tty device using -d.\n");
return NULL;
}
return bsl_open(args->serial_device);
}
static const struct driver driver_table[] = {
{
.name = "rf2500",
.help = "eZ430-RF2500 devices. Only USB connection is "
"supported.",
driver_open_rf2500
},
{ .name = "olimex",
.help = "Olimex MSP-JTAG-TINY.",
.func = driver_open_olimex
},
{
.name = "sim",
.help = "Simulation mode.",
.func = driver_open_sim
},
{
.name = "uif",
.help = "TI FET430UIF and compatible devices (e.g. eZ430).",
.func = driver_open_uif
},
{
.name = "uif-bsl",
.help = "TI FET430UIF bootloader.",
.func = driver_open_uif_bsl
}
};
static void usage(const char *progname)
{
int i;
fprintf(stderr,
"Usage: %s [options] -R [-v voltage] [command ...]\n"
" %s [options] -u <device> [-j] [-v voltage] [command ...]\n"
" %s [options] -O <device> [-j] [-v voltage] [command ...]\n"
" %s [options] -l [-j] [-v voltage] [command ...]\n"
" %s [options] -B <device> [command ...]\n"
" %s [options] -s [command ...]\n"
"Usage: %s [options] <driver> [command ...]\n"
"\n"
" -R\n"
" Open the first available RF2500 device on the USB bus.\n"
" -u device\n"
" Open the given tty device (FET430UIF compatible devices).\n"
" -O device\n"
" Open the given tty device (Olimex MSP430-JTAG-TINY).\n"
" -l\n"
" Open the first available Olimex MSP430-JTAG-TINY using libusb.\n"
" -d device\n"
" Connect via the given tty device, rather than USB.\n"
" -j\n"
" Use JTAG, rather than Spy-Bi-Wire (UIF devices only).\n"
" -v voltage\n"
" Set the supply voltage, in millivolts.\n"
" -B device\n"
" Debug the FET itself through the bootloader.\n"
" -s\n"
" Start in simulation mode.\n"
" -n\n"
" Do not read ~/.mspdebug on startup.\n"
" --help\n"
@ -153,11 +265,19 @@ static void usage(const char *progname)
" --fet-force-id string\n"
" Override the device ID returned by the FET.\n"
"\n"
"By default, the first RF2500 device on the USB bus is opened.\n"
"Most drivers connect by default via USB, unless told otherwise via the\n"
"-d option.\n"
"\n"
"If commands are given, they will be executed. Otherwise, an interactive\n"
"command reader is started.\n",
progname, progname, progname, progname, progname, progname);
"command reader is started.\n\n",
progname);
printf("Available drivers are:\n");
for (i = 0; i < ARRAY_LEN(driver_table); i++) {
const struct driver *drv = &driver_table[i];
printf(" %s\n %s\n", drv->name, drv->help);
}
}
static void process_rc_file(cproc_t cp)
@ -173,22 +293,6 @@ static void process_rc_file(cproc_t cp)
cproc_process_file(cp, text);
}
#define MODE_RF2500 0x01
#define MODE_UIF 0x02
#define MODE_UIF_BSL 0x04
#define MODE_SIM 0x08
#define MODE_OLIMEX 0x10
#define MODE_OLIMEX_USB 0x20
struct cmdline_args {
const char *devpath;
const char *fet_force_id;
int mode;
int want_jtag;
int no_rc;
int vcc_mv;
};
static int add_fet_device(void *user_data, const struct fet_db_record *r)
{
struct vector *v = (struct vector *)user_data;
@ -234,12 +338,11 @@ static int parse_cmdline_args(int argc, char **argv,
{NULL, 0, 0, 0}
};
while ((opt = getopt_long(argc, argv, "lu:jv:B:O:sR?n",
while ((opt = getopt_long(argc, argv, "d:jv:n",
longopts, NULL)) >= 0)
switch (opt) {
case 'O':
args->devpath = optarg;
args->mode |= MODE_OLIMEX;
case 'd':
args->serial_device = optarg;
break;
case 'L':
@ -253,19 +356,6 @@ static int parse_cmdline_args(int argc, char **argv,
usage(argv[0]);
exit(0);
case 'R':
args->mode |= MODE_RF2500;
break;
case 'u':
args->devpath = optarg;
args->mode |= MODE_UIF;
break;
case 'l':
args->mode |= MODE_OLIMEX_USB;
break;
case 'v':
args->vcc_mv = atoi(optarg);
break;
@ -274,103 +364,50 @@ static int parse_cmdline_args(int argc, char **argv,
args->want_jtag = 1;
break;
case 'B':
args->devpath = optarg;
args->mode |= MODE_UIF_BSL;
break;
case 's':
args->mode |= MODE_SIM;
break;
case 'n':
args->no_rc = 1;
break;
case '?':
return -1;
default:
fprintf(stderr, "Invalid argument: %c\n"
"Try --help for help.\n", opt);
fprintf(stderr, "Try --help for usage information.\n");
return -1;
}
/* Check for incompatible arguments */
if (args->mode & (args->mode - 1)) {
fprintf(stderr, "Multiple incompatible options specified.\n"
"Try --help for help.\n");
if (optind >= argc) {
fprintf(stderr, "You need to specify a driver. Try --help for "
"a list.\n");
return -1;
}
if (!args->mode) {
fprintf(stderr, "You need to specify an operating mode.\n"
"Try --help for help.\n");
return -1;
}
args->driver_name = argv[optind];
optind++;
return 0;
}
device_t setup_device(const struct cmdline_args *args,
stab_t stab)
{
device_t msp430_dev = NULL;
transport_t trans = NULL;
/* Open a device */
if (args->mode == MODE_SIM) {
msp430_dev = sim_open(fetch_io, store_io, stab);
} else if (args->mode == MODE_UIF_BSL) {
msp430_dev = bsl_open(args->devpath);
} else {
int flags = 0;
/* Open the appropriate transport */
if (args->mode == MODE_OLIMEX) {
trans = uif_open(args->devpath, 1);
flags |= FET_PROTO_OLIMEX;
} else if (args->mode == MODE_UIF) {
trans = uif_open(args->devpath, 0);
} else if (args->mode == MODE_OLIMEX_USB) {
trans = olimex_open();
flags |= FET_PROTO_OLIMEX;
} else {
trans = rf2500_open();
flags |= FET_PROTO_RF2500;
}
if (!trans)
return NULL;
/* Then initialize the device */
if (!args->want_jtag)
flags |= FET_PROTO_SPYBIWIRE;
msp430_dev = fet_open(trans, flags, args->vcc_mv,
args->fet_force_id);
}
if (!msp430_dev) {
if (trans)
trans->destroy(trans);
return NULL;
}
return msp430_dev;
}
cproc_t setup_cproc(const struct cmdline_args *args)
cproc_t setup_cproc(struct cmdline_args *args)
{
int i;
device_t msp430_dev;
stab_t stab;
cproc_t cp;
i = 0;
while (i < ARRAY_LEN(driver_table) &&
strcasecmp(driver_table[i].name, args->driver_name))
i++;
if (i >= ARRAY_LEN(driver_table)) {
fprintf(stderr, "Unknown driver: %s. Try --help for a list.\n",
args->driver_name);
return NULL;
}
stab = stab_new();
if (!stab)
return NULL;
args->stab = stab;
msp430_dev = setup_device(args, stab);
msp430_dev = driver_table[i].func(args);
if (!msp430_dev) {
stab_destroy(stab);
return NULL;

View File

@ -2,21 +2,12 @@
.SH NAME
MSPDebug - debugging tool for MSP430 MCUs
.SH SYNOPSIS
\fBmspdebug\fR [options] \-R [\-v \fIvoltage\fR] [\fIcommand\fR ...]
.br
\fBmspdebug\fR [options] \-u \fIdevice\fR [\-j] [\-v \fIvoltage\fR] [\fIcommand\fR ...]
.br
\fBmspdebug\fR [options] \-O \fIdevice\fR [\-j] [\-v \fIvoltage\fR] [\fIcommand\fR ...]
.br
\fBmspdebug\fR [options] \-l [\-j] [\-v \fIvoltage\fR] [\fIcommand\fR ...]
.br
\fBmspdebug\fR [options] \-B \fIdevice\fR [\fIcommand\fR ...]
.br
\fBmspdebug\fR [options] \-s [\fIcommand\fR ...]
\fBmspdebug\fR [options] \fIdriver\fR [\fIcommand\fR ...]
.SH DESCRIPTION
MSPDebug is a command-line tool designed for debugging and programming
the MSP430 family of MCUs. It supports the eZ430-F2013, eZ430-RF2500
and FET430UIF programming tools.
the MSP430 family of MCUs. It supports the eZ430-F2013, eZ430-RF2500,
FET430UIF and Olimex MSP-JTAG-TINY programming tools, as well as a
simulation mode.
When started with appropriate options, MSPDebug will attempt to
connect to the debugging tool specified and identify the device under
@ -39,42 +30,36 @@ commands are specified on the end of the command-line, then they are
executed after connecting to the device, and the interactive prompt is
not started. See the section labelled \fBCOMMANDS\fR for more
information.
.IP "\-R"
Connect to an eZ430-RF2500 device. The USB bus will be searched for
the first available device. You must have write permission for usbfs
in order for this to work. You can achieve this by running as root
(not recommended), or by remounting usbfs using the
devuid/devgid/devmode options.
.IP "\-v \fIvoltage\fR"
Set the programming voltage. The voltage should be specified as an integer
in millivolts. It defaults to 3000 (3.0 V).
.IP "\-u \fIdevice\fR"
Connect to an eZ430-F2013 or a FET430UIF device. The device argument
should be the filename of the appropriate tty device. The TI serial
converter chips on these devices are supported by newer versions of the
Linux kernel, and should appear as /dev/tty\fIXX\fR when attached.
.IP "\-O \fIdevice\fR"
Connect to an Olimex MSP430-JTAG-TINY device. The device argument
should be the filename of the appropriate tty device.
.IP "\-l"
Connect to an Olimex MSP430-JTAG-TINY device using libusb. The first
available device on the USB bus is claimed.
.IP "\-j"
Use JTAG instead of Spy-Bi-Wire to communicate with the MSP430. This
option only works on FET430UIF devices.
.IP "\-B \fIdevice\fR"
Connect to the bootloader on a FET430UIF device. These devices contain
MSP430F419 chips. By sending a special command sequence, you can obtain
access to the bootloader and inspect memory on the MSP430F419 in the
programming device itself.
Currently, only memory inspection is supported. CPU control via the
bootloader is not possible. Memory erase and write is possible, but is
currently not implemented, for lack of ability to test it. If implemented,
this would allow firmware updates to FET430UIF devices.
The argument should be the filename of the appropriate tty device.
.IP "\-s"
.IP "\-d \fIdevice\fR"
Specify that the driver should connect via a tty device rather than USB.
The supported connection methods vary depending on the driver. See the
section \fBDRIVERS\fR below for details.
.IP "\-n"
Do not process the startup file (~/.mspdebug).
.IP "\-\-help"
Display a brief help message and exit.
.IP "\-\-fet\-list"
Display a list of devices supported by the FET driver (the driver used
for \fB\-R\fR and \fB\-u\fR operating modes).
.IP "\-\-fet\-force\-id \fIstring\fR"
When using a FET device, force the connected chip to be recognised by
MSPDebug as one of the given type during initialization. This overrides
the device ID returned by the FET.
.SH DRIVERS
A driver name must be specified on the command line for MSPDebug to
connect to. Valid driver names are listed here.
.IP "\fBrf2500\fR"
Connect to an eZ430-RF2500 device. Only USB connection is supported.
.IP "\fBolimex\fR"
Connect to an Olimex MSP-JTAG-TINY device. Both USB and tty access are
supported.
.IP "\fBsim\fR"
Do not connect to any hardware device, but instead start in simulation
mode. A 64k buffer is allocated to simulate the device memory. The CPU
core alone is emulated (no peripheral emulation).
@ -94,17 +79,25 @@ execution.
This mode is intended for testing of changes to MSPDebug, and for
aiding the disassembly of MSP430 binaries (as all binary and symbol
table formats are still usable in this mode).
.IP "\-n"
Do not process the startup file (~/.mspdebug).
.IP "\-\-help"
Display a brief help message and exit.
.IP "\-\-fet\-list"
Display a list of devices supported by the FET driver (the driver used
for \fB\-R\fR and \fB\-u\fR operating modes).
.IP "\-\-fet\-force\-id \fIstring\fR"
When using a FET device, force the connected chip to be recognised by
MSPDebug as one of the given type during initialization. This overrides
the device ID returned by the FET.
.IP "\fBuif\fR"
Connect to an eZ430-F2013 or a FET430UIF device. The device argument
should be the filename of the appropriate tty device. The TI serial
converter chips on these devices are supported by newer versions of the
Linux kernel, and should appear as /dev/tty\fIXX\fR when attached.
USB connection is not supported for this driver.
.IP "\fBuif-bsl\fR"
Connect to the bootloader on a FET430UIF device. These devices contain
MSP430F419 chips. By sending a special command sequence, you can obtain
access to the bootloader and inspect memory on the MSP430F419 in the
programming device itself.
Currently, only memory inspection is supported. CPU control via the
bootloader is not possible. Memory erase and write is possible, but is
currently not implemented, for lack of ability to test it. If implemented,
this would allow firmware updates to FET430UIF devices.
USB connection is not supported for this driver.
.SH COMMANDS
MSPDebug can accept commands either through an interactive prompt, or
non-interactively when specified on the command line. The supported