Support for MSP-JTAG-TINY via USB bus (CP2102).

This commit is contained in:
Peter Jansen 2010-06-28 10:35:36 +12:00 committed by Daniel Beer
parent cf4ec417ff
commit 9dd216e604
6 changed files with 288 additions and 5 deletions

View File

@ -15,3 +15,4 @@ Hans Nieuwenhuis <vzzbx@xs4all.nl>:
Peter Jansen <pwjansen@yahoo.com>: Peter Jansen <pwjansen@yahoo.com>:
* Support for MSP430F169. * Support for MSP430F169.
* Testing and analysis for Olimex MSP430-JTAG-TINY. * Testing and analysis for Olimex MSP430-JTAG-TINY.
* libusb driver for Olimex MSP430-JTAG-TINY.

View File

@ -43,8 +43,8 @@ install: mspdebug mspdebug.man
.SUFFIXES: .c .o .SUFFIXES: .c .o
mspdebug: main.o fet.o rf2500.o dis.o uif.o ihex.o elf32.o stab.o util.o \ mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \
bsl.o sim.o symmap.o gdb.o btree.o rtools.o sym.o devcmd.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 cproc.o vector.o cproc_util.o expr.o fet_error.o binfile.o fet_db.o
$(CC) $(LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS) $(CC) $(LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)

19
main.c
View File

@ -42,6 +42,7 @@
#include "fet_db.h" #include "fet_db.h"
#include "uif.h" #include "uif.h"
#include "olimex.h"
#include "rf2500.h" #include "rf2500.h"
static void io_prefix(stab_t stab, static void io_prefix(stab_t stab,
@ -123,6 +124,7 @@ static void usage(const char *progname)
"Usage: %s [options] -R [-v voltage] [command ...]\n" "Usage: %s [options] -R [-v voltage] [command ...]\n"
" %s [options] -u <device> [-j] [-v voltage] [command ...]\n" " %s [options] -u <device> [-j] [-v voltage] [command ...]\n"
" %s [options] -O <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] -B <device> [command ...]\n"
" %s [options] -s [command ...]\n" " %s [options] -s [command ...]\n"
"\n" "\n"
@ -132,6 +134,8 @@ static void usage(const char *progname)
" Open the given tty device (FET430UIF compatible devices).\n" " Open the given tty device (FET430UIF compatible devices).\n"
" -O device\n" " -O device\n"
" Open the given tty device (Olimex MSP430-JTAG-TINY).\n" " Open the given tty device (Olimex MSP430-JTAG-TINY).\n"
" -l\n"
" Open the first available Olimex MSP430-JTAG-TINY using libusb.\n"
" -j\n" " -j\n"
" Use JTAG, rather than Spy-Bi-Wire (UIF devices only).\n" " Use JTAG, rather than Spy-Bi-Wire (UIF devices only).\n"
" -v voltage\n" " -v voltage\n"
@ -153,7 +157,7 @@ static void usage(const char *progname)
"\n" "\n"
"If commands are given, they will be executed. Otherwise, an interactive\n" "If commands are given, they will be executed. Otherwise, an interactive\n"
"command reader is started.\n", "command reader is started.\n",
progname, progname, progname, progname, progname); progname, progname, progname, progname, progname, progname);
} }
static void process_rc_file(cproc_t cp) static void process_rc_file(cproc_t cp)
@ -174,6 +178,7 @@ static void process_rc_file(cproc_t cp)
#define MODE_UIF_BSL 0x04 #define MODE_UIF_BSL 0x04
#define MODE_SIM 0x08 #define MODE_SIM 0x08
#define MODE_OLIMEX 0x10 #define MODE_OLIMEX 0x10
#define MODE_OLIMEX_USB 0x20
struct cmdline_args { struct cmdline_args {
const char *devpath; const char *devpath;
@ -229,7 +234,7 @@ static int parse_cmdline_args(int argc, char **argv,
{NULL, 0, 0, 0} {NULL, 0, 0, 0}
}; };
while ((opt = getopt_long(argc, argv, "u:jv:B:O:sR?n", while ((opt = getopt_long(argc, argv, "lu:jv:B:O:sR?n",
longopts, NULL)) >= 0) longopts, NULL)) >= 0)
switch (opt) { switch (opt) {
case 'O': case 'O':
@ -257,6 +262,10 @@ static int parse_cmdline_args(int argc, char **argv,
args->mode |= MODE_UIF; args->mode |= MODE_UIF;
break; break;
case 'l':
args->mode |= MODE_OLIMEX_USB;
break;
case 'v': case 'v':
args->vcc_mv = atoi(optarg); args->vcc_mv = atoi(optarg);
break; break;
@ -323,6 +332,9 @@ device_t setup_device(const struct cmdline_args *args,
flags |= FET_PROTO_OLIMEX; flags |= FET_PROTO_OLIMEX;
} else if (args->mode == MODE_UIF) { } else if (args->mode == MODE_UIF) {
trans = uif_open(args->devpath, 0); trans = uif_open(args->devpath, 0);
} else if (args->mode == MODE_OLIMEX_USB) {
trans = olimex_open();
flags |= FET_PROTO_OLIMEX;
} else { } else {
trans = rf2500_open(); trans = rf2500_open();
flags |= FET_PROTO_RF2500; flags |= FET_PROTO_RF2500;
@ -392,7 +404,8 @@ int main(int argc, char **argv)
"MSPDebug version 0.8 - debugging tool for MSP430 MCUs\n" "MSPDebug version 0.8 - debugging tool for MSP430 MCUs\n"
"Copyright (C) 2009, 2010 Daniel Beer <daniel@tortek.co.nz>\n" "Copyright (C) 2009, 2010 Daniel Beer <daniel@tortek.co.nz>\n"
"This is free software; see the source for copying conditions. There is NO\n" "This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR "
"PURPOSE.\n");
args.vcc_mv = 3000; args.vcc_mv = 3000;
if (parse_cmdline_args(argc, argv, &args) < 0) if (parse_cmdline_args(argc, argv, &args) < 0)

View File

@ -8,6 +8,8 @@ MSPDebug - debugging tool for MSP430 MCUs
.br .br
\fBmspdebug\fR [options] \-O \fIdevice\fR [\-j] [\-v \fIvoltage\fR] [\fIcommand\fR ...] \fBmspdebug\fR [options] \-O \fIdevice\fR [\-j] [\-v \fIvoltage\fR] [\fIcommand\fR ...]
.br .br
\fBmspdebug\fR [options] \-l [\-j] [\-v \fIvoltage\fR] [\fIcommand\fR ...]
.br
\fBmspdebug\fR [options] \-B \fIdevice\fR [\fIcommand\fR ...] \fBmspdebug\fR [options] \-B \fIdevice\fR [\fIcommand\fR ...]
.br .br
\fBmspdebug\fR [options] \-s [\fIcommand\fR ...] \fBmspdebug\fR [options] \-s [\fIcommand\fR ...]
@ -54,6 +56,9 @@ Linux kernel, and should appear as /dev/tty\fIXX\fR when attached.
.IP "\-O \fIdevice\fR" .IP "\-O \fIdevice\fR"
Connect to an Olimex MSP430-JTAG-TINY device. The device argument Connect to an Olimex MSP430-JTAG-TINY device. The device argument
should be the filename of the appropriate tty device. 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" .IP "\-j"
Use JTAG instead of Spy-Bi-Wire to communicate with the MSP430. This Use JTAG instead of Spy-Bi-Wire to communicate with the MSP430. This
option only works on FET430UIF devices. option only works on FET430UIF devices.

233
olimex.c Normal file
View File

@ -0,0 +1,233 @@
/* MSPDebug - debugging tool for the eZ430
* Copyright (C) 2009, 2010 Daniel Beer
* Copyright (C) 2010 Peter Jansen
*
* 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 <stdio.h>
#include <string.h>
#include <usb.h>
#include "olimex.h"
#include "util.h"
struct olimex_transport {
struct transport base;
int int_number;
struct usb_dev_handle *handle;
uint8_t buf[64];
int len;
int offset;
};
/*********************************************************************
* USB transport
*
* These functions handle the details of slicing data over USB
* transfers. The interface presented is a continuous byte stream with
* no slicing codes.
*
* Writes are unbuffered -- a single write translates to at least
* one transfer.
*/
#define USB_FET_VENDOR 0x15ba
#define USB_FET_PRODUCT 0x0002
#define USB_FET_INTERFACE_CLASS 255
#define USB_FET_IN_EP 0x81
#define USB_FET_OUT_EP 0x01
#define CP210x_REQTYPE_HOST_TO_DEVICE 0x41
#define CP210X_IFC_ENABLE 0x00
#define CP210X_SET_MHS 0x07
#define TIMEOUT 1000
static int open_interface(struct olimex_transport *tr,
struct usb_device *dev, int ino)
{
#if !(defined (__APPLE__) || defined(WIN32))
int drv;
char drName[256];
#endif
printf(__FILE__": Trying to open interface %d on %s\n",
ino, dev->filename);
tr->int_number = ino;
tr->handle = usb_open(dev);
if (!tr->handle) {
perror(__FILE__": can't open device");
return -1;
}
#if !(defined(__APPLE__) || defined(WIN32))
drv = usb_get_driver_np(tr->handle, tr->int_number, drName,
sizeof(drName));
printf(__FILE__" : driver %d\n", drv);
if (drv >= 0) {
if (usb_detach_kernel_driver_np(tr->handle,
tr->int_number) < 0)
perror(__FILE__": warning: can't detach "
"kernel driver");
}
#endif
if (usb_claim_interface(tr->handle, tr->int_number) < 0) {
perror(__FILE__": can't claim interface");
usb_close(tr->handle);
return -1;
}
int ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE,
CP210X_IFC_ENABLE, 0x1, 0, NULL, 0, 300);
#ifdef DEBUG_OLIMEX
printf(__FILE__": %s : Sending control message ret %d\n",
__FUNCTION__, ret);
#endif
ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE,
CP210X_SET_MHS, 0x303, 0, NULL, 0, 300);
#ifdef DEBUG_OLIMEX
printf(__FILE__": %s : Sending control message ret %d\n",
__FUNCTION__, ret);
#endif
return 0;
}
static int open_device(struct olimex_transport *tr, struct usb_device *dev)
{
struct usb_config_descriptor *c = &dev->config[0];
int i;
for (i = 0; i < c->bNumInterfaces; i++) {
struct usb_interface *intf = &c->interface[i];
struct usb_interface_descriptor *desc = &intf->altsetting[0];
if (desc->bInterfaceClass == USB_FET_INTERFACE_CLASS &&
!open_interface(tr, dev, desc->bInterfaceNumber))
return 0;
}
return -1;
}
static int usbtr_send(transport_t tr_base, const uint8_t *data, int len)
{
struct olimex_transport *tr = (struct olimex_transport *)tr_base;
int sent;
while (len) {
#ifdef DEBUG_OLIMEX
debug_hexdump(__FILE__": USB transfer out", data, len);
#endif
sent = usb_bulk_write(tr->handle, USB_FET_OUT_EP,
(char *)data, len, TIMEOUT);
if (sent < 0) {
perror(__FILE__": can't send data");
return -1;
}
len -= sent;
}
return 0;
}
static int usbtr_recv(transport_t tr_base, uint8_t *databuf, int max_len)
{
struct olimex_transport *tr = (struct olimex_transport *)tr_base;
int rlen;
#ifdef DEBUG_OLIMEX
printf(__FILE__": %s : read max %d\n", __FUNCTION__, max_len);
#endif
rlen = usb_bulk_read(tr->handle, USB_FET_IN_EP, (char *)databuf,
max_len, TIMEOUT);
#ifdef DEBUG_OLIMEX
printf(__FILE__": %s : read %d\n", __FUNCTION__, rlen);
#endif
if (rlen < 0) {
perror(__FILE__": can't receive data");
return -1;
}
#ifdef DEBUG_OLIMEX
debug_hexdump(__FILE__": USB transfer in", databuf, rlen);
#endif
return rlen;
}
static void usbtr_destroy(transport_t tr_base)
{
struct olimex_transport *tr = (struct olimex_transport *)tr_base;
usb_release_interface(tr->handle, tr->int_number);
usb_close(tr->handle);
free(tr);
}
transport_t olimex_open(void)
{
struct olimex_transport *tr = malloc(sizeof(*tr));
struct usb_bus *bus;
if (!tr) {
perror(__FILE__": can't allocate memory");
return NULL;
}
tr->base.destroy = usbtr_destroy;
tr->base.send = usbtr_send;
tr->base.recv = usbtr_recv;
usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == USB_FET_VENDOR &&
dev->descriptor.idProduct == USB_FET_PRODUCT &&
!open_device(tr, dev)) {
char buf[64];
/* Flush out lingering data */
while (usb_bulk_read(tr->handle, USB_FET_IN_EP,
buf, sizeof(buf),
100) >= 0);
return (transport_t)tr;
}
}
}
fprintf(stderr, __FILE__": no devices could be found\n");
free(tr);
return NULL;
}

31
olimex.h Normal file
View File

@ -0,0 +1,31 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2009, 2010 Daniel Beer
* Copyright (C) 2010 Peter Jansen
*
* 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
*/
#ifndef OLIMEX_H_
#define OLIMEX_H_
#include "transport.h"
/* Search the USB bus for the first Olimex MSP-JTAG-TINY, and
* initialize it. If successful, 0 is returned and the fet_* functions
* are ready for use. If an error occurs, -1 is returned.
*/
transport_t olimex_open(void);
#endif