This is an automated email from Gerrit. Jean-Michel Picod ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/1648
-- gerrit commit 2f8dab5d9928182483f50ad045bd6abe417757fc Author: Jean-Michel Picod <[email protected]> Date: Sun Sep 22 21:00:28 2013 +0200 goodfet: add driver Add support for GoodFET device (http://goodfet.sf.net) Previous work was done by Wookie in 2011 and is available at https://bitbucket.org/wookie/openocd/src I adapted those files to comply with the coding style and the latest git revision Change-Id: I1f8dcd5062cb99164f4c4f7cfc6325796f2edd35 Signed-off-by: Jean-Michel Picod <[email protected]> diff --git a/configure.ac b/configure.ac index 038212c..86f45d2 100644 --- a/configure.ac +++ b/configure.ac @@ -470,6 +470,10 @@ AC_ARG_ENABLE([buspirate], AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]), [build_buspirate=$enableval], [build_buspirate=no]) +AC_ARG_ENABLE([goodfet], + AS_HELP_STRING([--enable-goodfet], [Enable building support for the GoodFET]), + [build_goodfet=$enableval], [build_goodfet=no]) + AC_ARG_ENABLE([sysfsgpio], AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]), [build_sysfsgpio=$enableval], [build_sysfsgpio=no]) @@ -658,6 +662,13 @@ else AC_DEFINE([PARPORT_USE_GIVEIO], [0], [0 if you don't want parport to use giveio.]) fi +if test $build_goodfet = yes; then + build_bitbang=yes + AC_DEFINE([BUILD_GOODFET], [1], [1 if you want the GoodFET JTAG driver.]) +else + AC_DEFINE([BUILD_GOODFET], [0], [0 if you don't want the GoodFET JTAG driver.]) +fi + if test $build_bitbang = yes; then AC_DEFINE([BUILD_BITBANG], [1], [1 if you want a bitbang interface.]) else @@ -1146,6 +1157,7 @@ AM_CONDITIONAL([OPENJTAG], [test $build_openjtag_ftd2xx = yes -o $build_openjtag AM_CONDITIONAL([OOCD_TRACE], [test $build_oocd_trace = yes]) AM_CONDITIONAL([REMOTE_BITBANG], [test $build_remote_bitbang = yes]) AM_CONDITIONAL([BUSPIRATE], [test $build_buspirate = yes]) +AM_CONDITIONAL([GOODFET], [test $build_goodfet = yes]) AM_CONDITIONAL([SYSFSGPIO], [test $build_sysfsgpio = yes]) AM_CONDITIONAL([USE_LIBUSB0], [test $use_libusb0 = yes]) AM_CONDITIONAL([USE_LIBUSB1], [test $use_libusb1 = yes]) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 00f0165..a0270d2 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -122,6 +122,10 @@ if OPENJTAG DRIVERFILES += openjtag.c endif +if GOODFET +DRIVERFILES += goodfet.c +endif + noinst_HEADERS = \ bitbang.h \ bitq.h \ diff --git a/src/jtag/drivers/goodfet.c b/src/jtag/drivers/goodfet.c new file mode 100644 index 0000000..792743c --- /dev/null +++ b/src/jtag/drivers/goodfet.c @@ -0,0 +1,895 @@ +/*************************************************************************** + * Copyright (C) 2010 by Dave Huseby <dave at linuxprogrammer dot org> * + * * + * 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <termio.h> +#include <string.h> +#include <arpa/inet.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/select.h> + +#include <jtag/interface.h> +#include "bitbang.h" + +#define _POSIX_SOURCE 1 + +#define KB(x) (x * 1024) + +/* goodfet apps */ +#define MONITOR 0x00 +#define OPENOCD 0x18 + +/* goodfet verbs */ +#define PEEK 0x02 +#define SETUP 0x10 +#define START 0x20 +#define STOP 0x21 +#define NOK 0x7E +#define OK 0x7F +#define OPENOCD_RESET 0x80 +#define OPENOCD_READ 0x81 +#define OPENOCD_WRITE 0x82 +#define OPENOCD_LED 0x83 +#define DEBUGHEX 0xFE +#define DEBUGSTRING 0xFF + +/* error codes */ +#define FAILED_NO_DEVICE 1 +#define FAILED_OPEN 2 +#define FAILED_COMMAND_SEND 3 +#define FAILED_DATA_READ 4 +#define FAILED_INVALID_PARAMS 5 +#define FAILED_DATA_WRITE 6 + +/* GoodFET lowlevel data */ +typedef struct goodfet_s { + int data; + int status; + int err; + int rbyte; + int rcount; + fd_set readfds; + fd_set exceptfds; + struct termios old_tios_device; +} goodfet_t; + +/* GoodFET packet */ +typedef struct goodfet_packet_s { + uint8_t app; /* app number */ + uint8_t verb; /* verb number */ + uint16_t count; /* data size */ + uint8_t *data; /* the data */ +} goodfet_packet_t; + +/* global goodfet handle */ +static int gf_speed; +static uint32_t gf_toggling_time_ns = 10000; +static char *gf_device; +static goodfet_t *g_gf; + +/* allocate a goodfet struct */ +static goodfet_t *goodfet_new(void) +{ + return (goodfet_t *)calloc(1, sizeof(goodfet_t)); +} + +/* free a goodfet struct */ +static void goodfet_free(void *gf) +{ + if (gf == NULL) + return; + + free(gf); +} + +/* read data from the serial port */ +ssize_t goodfet_lowlevel_read +( + goodfet_t *gf, + void *buf, + size_t count, + struct timeval *timeout +) +{ + ssize_t ret = 0; + unsigned int i = 0; + int bytes = 0; + + if ((count <= 0) || (buf == 0)) { + LOG_ERROR("goodfet_lowlevel_read invalid params"); + gf->err = FAILED_INVALID_PARAMS; + return -gf->err; + } + + /* try to read as much data as was requested */ + while (i < count) { + /* check to see if we've run out of time */ + if ((timeout != 0) && (timeout->tv_sec <= 0) && (timeout->tv_usec <= 0)) { + LOG_ERROR("timeout break"); + break; + } + + /* clear the fd sets */ + FD_ZERO(&gf->readfds); + FD_ZERO(&gf->exceptfds); + + /* add the file descriptors to the test sets */ + FD_SET(gf->data, &gf->readfds); + FD_SET(gf->data, &gf->exceptfds); + + /* wait for input */ + ret = select(gf->data + 1, &gf->readfds, 0, &gf->exceptfds, timeout); + if (ret < 0) { + LOG_ERROR("select error"); + gf->err = FAILED_DATA_READ; + return -gf->err; + } + + /* we've got data ready to read */ + if ((ret > 0) && FD_ISSET(gf->data, &gf->readfds)) { + bytes = read(gf->data, (buf + i), (count - i)); + if (bytes < 0) { + LOG_ERROR("read error"); + gf->err = FAILED_DATA_READ; + return -gf->err; + } + i += bytes; + } + } + + return (ssize_t)i; +} + +/* write data to the goodfet */ +ssize_t goodfet_lowlevel_write(goodfet_t *gf, void *buf, size_t size) +{ + ssize_t ret = 0; + + if ((size <= 0) || (buf == 0)) { + gf->err = FAILED_INVALID_PARAMS; + return -gf->err; + } + + ret = write(gf->data, buf, size); + if (ret < 0) { + gf->err = FAILED_DATA_WRITE; + return -gf->err; + } + + return ret; +} + + +void goodfet_packet_free(goodfet_packet_t *p) +{ + if (p == NULL) + return; + + if (p->data != NULL) + free(p->data); + + free(p); +} + +/* packet reading states */ +#define PACKET_START 0 +#define PACKET_READ_APP 1 +#define PACKET_READ_VERB 2 +#define PACKET_READ_COUNT 3 +#define PACKET_READ_DATA 4 +#define PACKET_END 5 + +ssize_t goodfet_read_packet(goodfet_t *gf, goodfet_packet_t **p, struct timeval timeout) +{ + int bytes = 0; + int i = 0; + int state = PACKET_START; + uint8_t tmpbyte = 0; + uint16_t tmpshort = 0; + goodfet_packet_t *pkt = NULL; + struct timeval t; + + t.tv_sec = timeout.tv_sec; + t.tv_usec = timeout.tv_usec; + + while (state != PACKET_END) { + switch (state) { + case PACKET_START: + { + /* allocate the packet struct */ + *p = calloc(1, sizeof(goodfet_packet_t)); + pkt = *p; + + /* move to the next state */ + state = PACKET_READ_APP; + + break; + } + + case PACKET_READ_APP: + { + /* reset timeval struct */ + t.tv_sec = timeout.tv_sec; + t.tv_usec = timeout.tv_usec; + + /* read in the app byte */ + if (goodfet_lowlevel_read(gf, &tmpbyte, sizeof(uint8_t), &t) != sizeof(uint8_t)) { + gf->err = FAILED_DATA_READ; + return -gf->err; + } + + /* store the app */ + pkt->app = tmpbyte; + + /* move to the next state */ + state = PACKET_READ_VERB; + + break; + } + + case PACKET_READ_VERB: + { + /* reset timeval struct */ + t.tv_sec = timeout.tv_sec; + t.tv_usec = timeout.tv_usec; + + /* read in the app byte */ + if (goodfet_lowlevel_read(gf, &tmpbyte, sizeof(uint8_t), &t) != sizeof(uint8_t)) { + gf->err = FAILED_DATA_READ; + return -gf->err; + } + + /* store the verb */ + pkt->verb = tmpbyte; + + /* move to the next state */ + state = PACKET_READ_COUNT; + break; + } + + case PACKET_READ_COUNT: + { + /* reset timeval struct */ + t.tv_sec = timeout.tv_sec; + t.tv_usec = timeout.tv_usec; + + /* read in the app byte */ + if (goodfet_lowlevel_read(gf, &tmpshort, sizeof(uint16_t), &t) != sizeof(uint16_t)) { + gf->err = FAILED_DATA_READ; + return -gf->err; + } + + /* the count is now stored in big endian order--network order-- + so we need to convert it to the platform order using ntohs */ + pkt->count = ntohs(tmpshort); + + /* if the packet has payload, allocate a block of memory for it */ + if (pkt->count > 0) { + /* allocate a buffer for the data */ + pkt->data = calloc(pkt->count, sizeof(uint8_t)); + + /* move to the next state */ + state = PACKET_READ_DATA; + + /* set up the indexes */ + i = 0; + } else { + /* move to the end state */ + state = PACKET_END; + } + break; + } + + case PACKET_READ_DATA: + { + /* reset timeval struct */ + t.tv_sec = timeout.tv_sec; + t.tv_usec = timeout.tv_usec; + + /* read the bytes */ + bytes = 0; + if (i < pkt->count) { + /* read the data */ + bytes = goodfet_lowlevel_read(gf, &pkt->data[i], (pkt->count - i), &t); + + /* track how many bytes we've read */ + i += bytes; + } else { + /* move to the next state */ + state = PACKET_END; + } + break; + } + } + } + + return (ssize_t)i; +} + +ssize_t goodfet_get_next_packet(goodfet_t *gf, goodfet_packet_t **pkt) +{ + char *str = NULL; + ssize_t size = 0; + struct timeval t = { 1L, 0L }; + goodfet_packet_t *p; + + while ((size = goodfet_read_packet(gf, &p, t)) >= 0) { + switch (p->verb) { + case DEBUGSTRING: + /* copy the string so we can print it out */ + str = calloc(p->count + 1, sizeof(char)); + memcpy((void *)str, (void *)p->data, p->count); + LOG_ERROR("DEBUG: %s", str); + free(str); + str = NULL; + goodfet_packet_free(p); + p = NULL; + break; + case DEBUGHEX: + if (p->count == 2) + LOG_ERROR("DEBUG: %u", *((uint16_t *)(p->data))); + else if (p->count == 4) + LOG_ERROR("DEBUG: %u", *((uint32_t *)(p->data))); + goodfet_packet_free(p); + p = NULL; + break; + default: + (*pkt) = p; + return size; + } + } + + gf->err = FAILED_DATA_READ; + return -gf->err; +} + +ssize_t goodfet_write_packet(goodfet_t *gf, goodfet_packet_t *pkt) +{ + uint8_t *data; + ssize_t size; + + /* convert the packet to a buffer */ + size = 4 + pkt->count; + data = calloc(size, sizeof(uint8_t)); + data[0] = pkt->app; + data[1] = pkt->verb; + *((uint16_t *)&data[2]) = htons(pkt->count); + memcpy((void *)(&data[4]), (void *)pkt->data, (size_t)pkt->count); + + /* send the packet */ + if (goodfet_lowlevel_write(gf, (void *)data, size) != size) { + gf->err = FAILED_DATA_WRITE; + return -gf->err; + } + + /* free the memory */ + free(data); + + return size; +} + +static int goodfet_monitor_peek_8(uint16_t addr, uint8_t *val) +{ + uint8_t data[2]; + uint16_t tmp; + goodfet_packet_t pout; + goodfet_packet_t *pin; + + if (val == NULL) { + g_gf->err = FAILED_INVALID_PARAMS; + return -g_gf->err; + } + + pout.app = MONITOR; + pout.verb = PEEK; + pout.count = 2; + tmp = htons(addr); + data[0] = (tmp >> 8); + data[1] = tmp & 0x0ff; + pout.data = data; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) > 0) { + (*val) = pin->data[0]; + goodfet_packet_free(pin); + return ERROR_OK; + } + + LOG_ERROR("failed to read response to monitor peek command"); + g_gf->err = FAILED_DATA_READ; + return -g_gf->err; +} + +static void goodfet_monitor_info(void) +{ + uint8_t info[2]; + + /* get the MCU number */ + goodfet_monitor_peek_8(0x0ff0, &info[0]); + goodfet_monitor_peek_8(0x0ff1, &info[1]); + + LOG_INFO("GoodFET with %02x%02x MCU", info[0], info[1]); + + /* get the monitor clocking */ + goodfet_monitor_peek_8(0x0056, &info[0]); + goodfet_monitor_peek_8(0x0057, &info[1]); + + LOG_INFO("Clocked at 0x%04x", (uint16_t)(info[0] + (info[1] << 8))); +} + +static int goodfet_read(void) +{ + int val = 0; + goodfet_packet_t pout; + goodfet_packet_t *pin; + + pout.app = OPENOCD; + pout.verb = OPENOCD_READ; + pout.count = 0; + pout.data = NULL; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) > 0) { + val = pin->data[0]; + goodfet_packet_free(pin); + return val; + } + + LOG_ERROR("failed to read response to goodfet_read command"); + g_gf->err = FAILED_DATA_READ; + return -g_gf->err; +} + +static void goodfet_write(int tck, int tms, int tdi) +{ + uint8_t data[3]; + goodfet_packet_t pout; + goodfet_packet_t *pin; + + pout.app = OPENOCD; + pout.verb = OPENOCD_WRITE; + pout.count = 3; + data[0] = (uint8_t)tck; + data[1] = (uint8_t)tms; + data[2] = (uint8_t)tdi; + pout.data = data; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) == 0) { + goodfet_packet_free(pin); + return; + } + + LOG_ERROR("failed to read response to goodfet_write command"); + g_gf->err = FAILED_DATA_READ; +} + +static void goodfet_reset(int trst, int srst) +{ + uint8_t data[2]; + goodfet_packet_t pout; + goodfet_packet_t *pin; + + pout.app = OPENOCD; + pout.verb = OPENOCD_RESET; + pout.count = 2; + data[0] = (uint8_t)trst; + data[1] = (uint8_t)srst; + pout.data = data; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) == 0) { + goodfet_packet_free(pin); + return; + } + + LOG_ERROR("failed to read response to goodfet_reset command"); + g_gf->err = FAILED_DATA_READ; +} + +static void goodfet_led(int on) +{ + uint8_t data; + goodfet_packet_t pout; + goodfet_packet_t *pin; + + pout.app = OPENOCD; + pout.verb = OPENOCD_LED; + pout.count = 1; + data = (uint8_t)on; + pout.data = &data; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) == 0) { + goodfet_packet_free(pin); + return; + } + + LOG_ERROR("failed to read response to goodfet_led command"); + g_gf->err = FAILED_DATA_READ; +} + +static void goodfet_setup(void) +{ + goodfet_packet_t pout; + goodfet_packet_t *pin; + + pout.app = OPENOCD; + pout.verb = SETUP; + pout.count = 0; + pout.data = NULL; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) == 0) { + goodfet_packet_free(pin); + return; + } + + LOG_ERROR("failed to read response to goodfet_setup command"); + g_gf->err = FAILED_DATA_READ; +} + +static void goodfet_start(void) +{ + goodfet_packet_t pout; + goodfet_packet_t *pin; + + pout.app = OPENOCD; + pout.verb = START; + pout.count = 0; + pout.data = NULL; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) == 0) { + goodfet_packet_free(pin); + return; + } + + LOG_ERROR("failed to read response to goodfet_start command"); + g_gf->err = FAILED_DATA_READ; +} + +static void goodfet_stop(void) +{ + goodfet_packet_t pout; + goodfet_packet_t *pin; + + LOG_ERROR("goodfet_stop()"); + + pout.app = OPENOCD; + pout.verb = STOP; + pout.count = 0; + pout.data = NULL; + + /* send the monitor peek command */ + goodfet_write_packet(g_gf, &pout); + + /* read the response */ + if (goodfet_get_next_packet(g_gf, &pin) == 0) { + goodfet_packet_free(pin); + return; + } + + LOG_ERROR("failed to read response to goodfet_stop command"); + g_gf->err = FAILED_DATA_READ; +} + +static int goodfet_speed(int speed) +{ + gf_speed = speed; + return ERROR_OK; +} + +static int goodfet_khz(int khz, int *jtag_speed) +{ + if (khz == 0) { + LOG_DEBUG("RCLK not supported"); + return ERROR_FAIL; + } + + *jtag_speed = 499999 / (khz * gf_toggling_time_ns); + return ERROR_OK; +} + +static int goodfet_speed_div(int speed, int *khz) +{ + uint32_t denominator = (speed + 1) * gf_toggling_time_ns; + + *khz = (499999 + denominator) / denominator; + return ERROR_OK; +} + +static struct bitbang_interface goodfet_bitbang = { + .read = &goodfet_read, + .write = &goodfet_write, + .reset = &goodfet_reset, + .blink = &goodfet_led +}; + +/* + * NOTE: getting the serial driver configured correctly was a little tricky to + * figure out but thanks to the awesome Serial Programming Guide for POSIX + * Operating Systems <http://www.easysw.com/~mike/serial/serial.html> by + * Michael R. Sweet, I was able to figure it out. + */ +static void goodfet_configure_tios(struct termios *tios) +{ + /* set up 115.2kB baud rate */ + cfsetispeed(tios, B115200); + cfsetospeed(tios, B115200); + + /* enable receiver, make local */ + tios->c_cflag |= (CLOCAL | CREAD); + + /* set 8N1: 8-bit width, no parity, and one stop bit */ + tios->c_cflag &= ~PARENB; + tios->c_cflag &= ~CSTOPB; + tios->c_cflag &= ~CSIZE; + tios->c_cflag |= CS8; + + /* enable hardware flow control */ + /*tios->c_cflag |= CRTSCTS;*/ + + /* set up for raw input */ + tios->c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG); + + /* + * turn off all parity checking, marking, and stripping...also turn off + * all software flow control and all of the bullshit mapping of CR's to LF's + * and LF's to CR's...blah..who thought it would be this hard to receive + * 8-bit binary data over a serial port?!? I beat my head against this one + * for about a week before figuring out the correct settings for this flag! + */ + tios->c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP | IXON | IXOFF | IXANY | ICRNL | INLCR | IUCLC | BRKINT); + + /* set up raw output */ + tios->c_oflag &= ~OPOST; +} + +static void goodfet_configure_device(goodfet_t *gf) +{ + struct termios dataios; + + /* save the current termios settings for the two devices */ + tcgetattr(gf->data, &gf->old_tios_device); + + /* get the current data channel settings */ + bzero(&dataios, sizeof(dataios)); + tcgetattr(gf->data, &dataios); + + /* configure the data channel tios */ + goodfet_configure_tios(&dataios); + + /* set the new settings for the data device */ + tcsetattr(gf->data, TCSAFLUSH, &dataios); + + /* set the descriptor to non-blocking */ + fcntl(gf->data, F_SETFL, FNDELAY); +} + +/* flush the I/O buffers in the CopyNES */ +void goodfet_flush(goodfet_t *gf) +{ + /* flush I/O buffers on the serial device */ + tcflush(gf->data, TCIOFLUSH); +} + +/* init the GoodFET device */ +static int goodfet_init(void) +{ + char *str = NULL; + int flags = 0; + int attempts = 0; + struct timeval t = { 10L, 0L }; /* 10 second timeout */ + goodfet_packet_t *pkt = NULL; + + /*if (g_gf != NULL) { + LOG_ERROR("goodfet already initialized"); + return ERROR_FAIL; + }*/ + + /* allocate the goodfet struct */ + g_gf = goodfet_new(); + + /* make sure we have a goodfet device name */ + if (gf_device == NULL) { + LOG_ERROR("no GoodFET device specified"); + g_gf->err = FAILED_NO_DEVICE; + return ERROR_FAIL; + } + + /* open the serial device */ + g_gf->data = open(gf_device, O_RDWR | O_NOCTTY | O_NDELAY); + + if (g_gf->data == -1) { + LOG_ERROR("failed to open GoodFET device: %s", gf_device); + g_gf->err = FAILED_OPEN; + return ERROR_FAIL; + } + LOG_INFO("opened serial port"); + + /* configure the serial device */ + goodfet_configure_device(g_gf); + LOG_INFO("device configured"); + + for (;;) { + /* flush the buffers */ + goodfet_flush(g_gf); + + LOG_INFO("Attempting to reset the board: %d", attempts); + + /* get the current control signals state */ + ioctl(g_gf->data, TIOCMGET, &flags); + + /* explicitly set RST and DTR to halt the board */ + flags |= TIOCM_RTS; /* RTS = 1 */ + flags |= TIOCM_DTR; /* DTR = 1 */ + ioctl(g_gf->data, TIOCMSET, &flags); + + /* drop DTR, which is !RST, low to begin the app. */ + flags &= ~TIOCM_DTR; /* DTR = 0 */ + ioctl(g_gf->data, TIOCMSET, &flags); + + /* flush the buffers */ + goodfet_flush(g_gf); + + sleep(1); /* sleep for 1 second */ + + /* update number of attmepts */ + attempts++; + + /* read a packet */ + LOG_INFO("looking for initial signature packet"); + if (goodfet_read_packet(g_gf, &pkt, t) > 0) { + if ((pkt->app == MONITOR) && (pkt->verb == OK) && + (memcmp(pkt->data, "http://goodfet.sf.net/", pkt->count) == 0)) { + LOG_INFO("got OK packet"); + break; + } + } + + /* free the packet */ + goodfet_packet_free(pkt); + pkt = NULL; + + if (attempts > 100) { + LOG_ERROR("tried over 100 times to reset the GoodFET device"); + g_gf->err = FAILED_OPEN; + return ERROR_FAIL; + } + } + + /* copy the string so we can print it out */ + str = calloc(pkt->count + 1, sizeof(char)); + memcpy((void *)str, (void *)pkt->data, pkt->count); + LOG_INFO("%s", str); + free(str); + + /* free the packet */ + goodfet_packet_free(pkt); + + /* output monitor info */ + goodfet_monitor_info(); + + /* do any GoodFET initialization here */ + goodfet_setup(); + goodfet_start(); + goodfet_reset(0, 0); + goodfet_write(0, 0, 0); + goodfet_led(1); + + /* hook up the function pointers */ + bitbang_interface = &goodfet_bitbang; + + return ERROR_OK; +} + +static int goodfet_quit(void) +{ + goodfet_stop(); + + /* reset the termios settings */ + tcsetattr(g_gf->data, TCSAFLUSH, &g_gf->old_tios_device); + + /* close the device */ + close(g_gf->data); + + /* free the device string */ + if (gf_device != NULL) + free(gf_device); + + /* free the goodfet struct */ + if (g_gf != NULL) + goodfet_free(g_gf); + + return ERROR_OK; +} + +COMMAND_HANDLER(goodfet_handle_device_command) +{ + if (CMD_ARGC == 0) + return ERROR_OK; + + /* only if the cable name wasn't overwritten by cmdline */ + gf_device = calloc(strlen(CMD_ARGV[0]) + sizeof(char), sizeof(char)); + if (gf_device == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + strcpy(gf_device, CMD_ARGV[0]); + LOG_INFO("Setting GoodFET device to: %s", gf_device); + + return ERROR_OK; +} + +static const struct command_registration goodfet_command_handlers[] = { + { + .name = "goodfet_device", + .handler = goodfet_handle_device_command, + .mode = COMMAND_CONFIG, + .help = "Set the name of the serial device for the GoodFET", + .usage = "[serial device]", + }, + COMMAND_REGISTRATION_DONE +}; + +struct jtag_interface goodfet_interface = { + .name = "goodfet", + .commands = goodfet_command_handlers, + + .init = goodfet_init, + .quit = goodfet_quit, + + .khz = goodfet_khz, + .speed = goodfet_speed, + .speed_div = goodfet_speed_div, + .execute_queue = bitbang_execute_queue, +}; + diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index eb447cd..3eab119 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -128,6 +128,9 @@ extern struct jtag_interface aice_interface; #if BUILD_BCM2835GPIO == 1 extern struct jtag_interface bcm2835gpio_interface; #endif +#if BUILD_GOODFET == 1 +extern struct jtag_interface goodfet_interface; +#endif #endif /* standard drivers */ /** @@ -224,6 +227,9 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_BCM2835GPIO == 1 &bcm2835gpio_interface, #endif +#if BUILD_GOODFET == 1 + &goodfet_interface, +#endif #endif /* standard drivers */ NULL, }; diff --git a/tcl/interface/goodfet.cfg b/tcl/interface/goodfet.cfg new file mode 100644 index 0000000..6e41edb --- /dev/null +++ b/tcl/interface/goodfet.cfg @@ -0,0 +1,6 @@ +# +# GoodFET USB JTAG on /dev/ttyUSB0 +# + +interface goodfet +goodfet_device /dev/ttyUSB0 -- ------------------------------------------------------------------------------ LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/22/13. http://pubads.g.doubleclick.net/gampad/clk?id=64545871&iu=/4140/ostg.clktrk _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
