Add raw USB driver for Olimex MSP430-JTAG-ISO.

This commit is contained in:
Daniel Beer 2012-03-02 12:13:11 +13:00
parent a7a71b993f
commit 902c2903c3
5 changed files with 304 additions and 8 deletions

View File

@ -121,6 +121,7 @@ OBJ=\
drivers/uif.o \ drivers/uif.o \
drivers/ti3410.o \ drivers/ti3410.o \
drivers/tilib.o \ drivers/tilib.o \
drivers/olimex_iso.o \
formats/binfile.o \ formats/binfile.o \
formats/coff.o \ formats/coff.o \
formats/elf32.o \ formats/elf32.o \

View File

@ -36,6 +36,7 @@
#include "uif.h" #include "uif.h"
#include "olimex.h" #include "olimex.h"
#include "olimex_iso.h"
#include "rf2500.h" #include "rf2500.h"
#include "ti3410.h" #include "ti3410.h"
@ -1148,14 +1149,13 @@ static device_t fet_open_olimex_iso(const struct device_args *args)
{ {
transport_t trans; transport_t trans;
if (!(args->flags & DEVICE_FLAG_TTY)) { if (args->flags & DEVICE_FLAG_TTY)
printc_err("This driver does not support raw USB access.\n"); trans = uif_open(args->path, UIF_TYPE_FET);
return NULL; else
} trans = olimex_iso_open(args->path, args->requested_serial);
trans = uif_open(args->path, UIF_TYPE_OLIMEX_ISO); if (!trans)
if (!trans) return NULL;
return NULL;
return fet_open(args, FET_PROTO_NOLEAD_SEND | FET_PROTO_EXTRA_RECV | return fet_open(args, FET_PROTO_NOLEAD_SEND | FET_PROTO_EXTRA_RECV |
FET_PROTO_IDENTIFY_NEW, FET_PROTO_IDENTIFY_NEW,

262
drivers/olimex_iso.c Normal file
View File

@ -0,0 +1,262 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2012 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 <string.h>
#include <time.h>
#include "olimex_iso.h"
#include "util.h"
#include "usbutil.h"
#include "output.h"
struct iso_transport {
struct transport base;
struct usb_dev_handle *handle;
};
#define USB_VENDOR 0x15ba
#define USB_PRODUCT 0x0008
#define USB_INTERFACE 0
#define USB_CONFIG 1
#define EP_IN 0x81
#define EP_OUT 0x02
#define TIMEOUT_S 10
#define REQ_TIMEOUT_MS 100
#define REQTYPE_HOST_TO_DEVICE 0x40
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */
#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */
#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of
the port */
#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem
status register */
#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */
#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */
#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
#define FTDI_SIO_GET_LATENCY_TIMER 10 /* Get the latency timer */
#define FTDI_SIO_RESET_SIO 0
#define FTDI_SIO_RESET_PURGE_RX 1
#define FTDI_SIO_RESET_PURGE_TX 2
#define FTDI_PACKET_SIZE 64
struct config_rec {
const char *desc;
int request;
int value;
};
static const struct config_rec config[] = {
{"reset FTDI",
FTDI_SIO_RESET, FTDI_SIO_RESET_SIO},
{"set data characteristics",
FTDI_SIO_SET_DATA, 8}, /* 8,N,1 */
{"disable flow control",
FTDI_SIO_SET_FLOW_CTRL, 0},
{"set modem control lines",
FTDI_SIO_MODEM_CTRL, 0x303}, /* DSR + CTS */
{"set baud rate divisor",
FTDI_SIO_SET_BAUD_RATE, 0xf}, /* 200 kbps */
{"set latency timer",
FTDI_SIO_SET_LATENCY_TIMER, 50}, /* 50 ms */
{"purge TX",
FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_TX},
{"purge RX",
FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_RX}
};
int configure_ftdi(struct usb_dev_handle *handle)
{
int i;
for (i = 0; i < ARRAY_LEN(config); i++) {
const struct config_rec *r = &config[i];
if (usb_control_msg(handle, REQTYPE_HOST_TO_DEVICE,
r->request, r->value, 0,
NULL, 0, REQ_TIMEOUT_MS)) {
printc_err("olimex_iso: %s failed: %s\n",
r->desc, usb_strerror());
return -1;
}
}
return 0;
}
static int open_device(struct iso_transport *tr, struct usb_device *dev)
{
int driver;
char drv_name[128];
printc_dbg("olimex_iso: trying to open %s\n", dev->filename);
tr->handle = usb_open(dev);
if (!tr->handle) {
printc_err("olimex_iso: can't open device: %s\n",
usb_strerror());
return -1;
}
#ifdef __linux__
driver = usb_get_driver_np(tr->handle, USB_INTERFACE,
drv_name, sizeof(drv_name));
if (driver >= 0) {
printc_dbg("Detaching kernel driver \"%s\"\n", drv_name);
if (usb_detach_kernel_driver_np(tr->handle, USB_INTERFACE) < 0)
printc_err("warning: olimex_iso: can't detach "
"kernel driver: %s\n", usb_strerror());
}
#endif
#ifdef WIN32
if (usb_set_configuration(tr->handle, USB_CONFIG) < 0) {
printc_err("olimex_iso: can't set configuration: %s\n",
usb_strerror());
usb_close(tr->handle);
return -1;
}
#endif
if (usb_claim_interface(tr->handle, USB_INTERFACE) < 0) {
printc_err("olimex_iso: can't claim interface: %s\n",
usb_strerror());
usb_close(tr->handle);
return -1;
}
if (configure_ftdi(tr->handle) < 0) {
printc_err("olimex_iso: failed to configure device: %s\n",
usb_strerror());
usb_close(tr->handle);
return -1;
}
return 0;
}
static void tr_destroy(transport_t tr_base)
{
struct iso_transport *tr = (struct iso_transport *)tr_base;
usb_close(tr->handle);
free(tr);
}
static int tr_recv(transport_t tr_base, uint8_t *databuf, int max_len)
{
struct iso_transport *tr = (struct iso_transport *)tr_base;
time_t deadline = time(NULL) + TIMEOUT_S;
char tmpbuf[FTDI_PACKET_SIZE];
if (max_len > FTDI_PACKET_SIZE - 2)
max_len = FTDI_PACKET_SIZE - 2;
while(time(NULL) < deadline) {
int r = usb_bulk_read(tr->handle, EP_IN,
tmpbuf, max_len + 2,
TIMEOUT_S * 1000);
if (r <= 0) {
printc_err("olimex_iso: usb_bulk_read: %s\n",
usb_strerror());
return -1;
}
if (r > 2) {
memcpy(databuf, tmpbuf + 2, r - 2);
#ifdef DEBUG_OLIMEX_ISO
printc_dbg("olimex_iso: tr_recv: flags = %02x %02x\n",
tmpbuf[0], tmpbuf[1]);
debug_hexdump("olimex_iso: tr_recv", databuf, r - 2);
#endif
return r - 2;
}
}
printc_err("olimex_iso: timed out while receiving data\n");
return -1;
}
static int tr_send(transport_t tr_base, const uint8_t *databuf, int len)
{
struct iso_transport *tr = (struct iso_transport *)tr_base;
#ifdef DEBUG_OLIMEX_ISO
debug_hexdump("olimex_iso: tr_send", databuf, len);
#endif
while (len) {
int r = usb_bulk_write(tr->handle, EP_OUT,
(char *)databuf, len,
TIMEOUT_S * 1000);
if (r <= 0) {
printc_err("olimex_iso: usb_bulk_write: %s\n",
usb_strerror());
return -1;
}
databuf += r;
len -= r;
}
return 0;
}
transport_t olimex_iso_open(const char *devpath,
const char *requested_serial)
{
struct iso_transport *tr = malloc(sizeof(*tr));
struct usb_device *dev;
if (!tr) {
pr_error("olimex_iso: can't allocate memory");
return NULL;
}
tr->base.destroy = tr_destroy;
tr->base.send = tr_send;
tr->base.recv = tr_recv;
usb_init();
usb_find_busses();
usb_find_devices();
if (devpath)
dev = usbutil_find_by_loc(devpath);
else
dev = usbutil_find_by_id(USB_VENDOR, USB_PRODUCT,
requested_serial);
if (!dev) {
free(tr);
return NULL;
}
if (open_device(tr, dev) < 0) {
printc_err("olimex_iso: failed to open device\n");
return NULL;
}
return &tr->base;
}

32
drivers/olimex_iso.h Normal file
View File

@ -0,0 +1,32 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2012 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
*/
#ifndef OLIMEX_ISO_H_
#define OLIMEX_ISO_H_
#include "transport.h"
/* Search the USB bus for the first Olimex ISO device and initialize it.
* If successful, return a transport object. Otherwise, return NULL.
*
* A particular USB device or serial number may be specified.
*/
transport_t olimex_iso_open(const char *usb_device,
const char *requested_serial);
#endif

View File

@ -95,7 +95,8 @@ Connect to an Olimex MSP-JTAG-TINY (V1) device. Both USB and tty access are
supported. This driver must be used instead of \fBolimex\fR if connecting supported. This driver must be used instead of \fBolimex\fR if connecting
to a V1 device via a tty interface. to a V1 device via a tty interface.
.IP "\fBolimex-iso\fR" .IP "\fBolimex-iso\fR"
Connect to an Olimex MSP-JTAG-ISO device. Only tty access is supported. Connect to an Olimex MSP-JTAG-ISO device. Both USB and tty access are
supported.
.IP "\fBsim\fR" .IP "\fBsim\fR"
Do not connect to any hardware device, but instead start in simulation Do not connect to any hardware device, but instead start in simulation
mode. A 64k buffer is allocated to simulate the device memory. mode. A 64k buffer is allocated to simulate the device memory.