This is an automated email from Gerrit. Matej Kogovsek ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4215
-- gerrit commit d3edbba0b4a51fb9338b22f4cf29cc258c46ad7c Author: Matej Kogovsek <[email protected]> Date: Sun Sep 3 12:19:41 2017 +0200 Added support for FT232R bitbang JTAG interface. Change-Id: Ib88a9e270f5c2a50902a137bcc97fdefd5aad1c6 Signed-off-by: Matej Kogovsek <[email protected]> diff --git a/configure.ac b/configure.ac index c680bda..8f7a46c 100644 --- a/configure.ac +++ b/configure.ac @@ -135,6 +135,7 @@ m4_define([HIDAPI_USB1_ADAPTERS], m4_define([LIBFTDI_ADAPTERS], [[[usb_blaster], [Altera USB-Blaster Compatible], [USB_BLASTER]], [[presto], [ASIX Presto Adapter], [PRESTO]], + [[ft232r], [Bitbang mode of FT232R based devices], [FT232R]], [[openjtag], [OpenJTAG Adapter], [OPENJTAG]]]) m4_define([LIBJAYLINK_ADAPTERS], diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 3e5974d..b3b4d21 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -80,6 +80,9 @@ if USB_BLASTER_DRIVER %C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la include %D%/usb_blaster/Makefile.am endif +if FT232R +DRIVERFILES += %D%/ft232r.c +endif if AMTJTAGACCEL DRIVERFILES += %D%/amt_jtagaccel.c endif diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c new file mode 100644 index 0000000..a0f5bc3 --- /dev/null +++ b/src/jtag/drivers/ft232r.c @@ -0,0 +1,748 @@ +/*************************************************************************** + * Copyright (C) 2010 Serge Vakulenko * + * [email protected] * + * * + * 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#define _DEBUG_JTAG_IO_ +#ifdef _DEBUG_JTAG_IO_ +# define JTAG_DEBUG LOG_DEBUG +#else +# define JTAG_DEBUG(...) /*empty*/ +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if IS_CYGWIN == 1 +#include "windows.h" +#undef LOG_ERROR +#endif + +/* project specific includes */ +#include <jtag/interface.h> +#include <jtag/commands.h> +#include <helper/time_support.h> + +/* system includes */ +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <usb.h> +#include <sys/time.h> +#include <time.h> + +/* + * Bit 7 (0x80, pin 6, RI ): unused. + * Bit 6 (0x40, pin 10,DCD): /SYSRST output. + * Bit 5 (0x20, pin 9, DSR): unused. + * Bit 4 (0x10, pin 2, DTR): /TRST output. + * Bit 3 (0x08, pin 11,CTS): TMS output. + * Bit 2 (0x04, pin 3, RTS): TDO input. + * Bit 1 (0x02, pin 5, RXD): TDI output. + * Bit 0 (0x01, pin 1, TXD): TCK output. + * + * Sync bit bang mode is implemented as described in FTDI Application + * Note AN232R-01: "Bit Bang Modes for the FT232R and FT245R". + */ +#define TCK (1 << 0) +#define TDI (1 << 1) +#define READ_TDO (1 << 2) +#define TMS (1 << 3) +#define NTRST (1 << 4) +#define NSYSRST (1 << 6) + +/* + * USB endpoints. + */ +#define IN_EP 0x02 +#define OUT_EP 0x81 + +/* Requests */ +#define SIO_RESET 0 /* Reset the port */ +#define SIO_MODEM_CTRL 1 /* Set the modem control register */ +#define SIO_SET_FLOW_CTRL 2 /* Set flow control register */ +#define SIO_SET_BAUD_RATE 3 /* Set baud rate */ +#define SIO_SET_DATA 4 /* Set the data characteristics of the port */ +#define SIO_POLL_MODEM_STATUS 5 +#define SIO_SET_EVENT_CHAR 6 +#define SIO_SET_ERROR_CHAR 7 +#define SIO_SET_LATENCY_TIMER 9 +#define SIO_GET_LATENCY_TIMER 10 +#define SIO_SET_BITMODE 11 +#define SIO_READ_PINS 12 +#define SIO_READ_EEPROM 0x90 +#define SIO_WRITE_EEPROM 0x91 +#define SIO_ERASE_EEPROM 0x92 + +static char *ft232r_device_desc; +static uint16_t ft232r_vid = 0x0403; /* FTDI */ +static uint16_t ft232r_pid = 0x6001; /* FT232R */ +static usb_dev_handle *adapter; + +static uint8_t ft232r_output[4000]; +static int ft232r_output_len; + +/* + * Perform sync bitbang output/input transaction. + * Before call, an array ft232r_output[] should be filled with data to send. + * Counter ft232r_output_len contains the number of bytes to send. + * On return, received data is put back to array ft232r_output[]. + */ +static int ft232r_send_recv(void) +{ + int bytes_to_write, bytes_written, n, txdone, rxdone; + int empty_rxfifo, bytes_to_read, bytes_read; + uint8_t reply[64]; + + /* FIFO TX buffer of FT232R chip has 128 bytes. + * FIFO RX buffer has 256 bytes. First two bytes + * contain modem and line status. + * Unfortunately, transfer sizes bigger than 64 bytes + * frequently cause hang ups. */ + assert(ft232r_output_len > 0); + + /* RX buffer is empty, except two status bytes. */ + empty_rxfifo = sizeof(reply) - 2; + + /* Indexes in data buffer. */ + txdone = 0; + rxdone = 0; + while (rxdone < ft232r_output_len) { + /* Try to send as much as possible, + * but avoid overflow of receive buffer. */ + bytes_to_write = 64; + if (bytes_to_write > ft232r_output_len - txdone) + bytes_to_write = ft232r_output_len - txdone; + if (bytes_to_write > empty_rxfifo) + bytes_to_write = empty_rxfifo; + + /* Write data. */ + bytes_written = 0; + while (bytes_written < bytes_to_write) { + JTAG_DEBUG("usb bulk write %d bytes", + bytes_to_write - bytes_written); + n = usb_bulk_write(adapter, IN_EP, + (char *) ft232r_output + txdone + bytes_written, + bytes_to_write - bytes_written, 1000); + if (n < 0) { + LOG_ERROR("usb bulk write failed"); + return ERROR_JTAG_DEVICE_ERROR; + } + if (n != bytes_to_write) + JTAG_DEBUG("usb bulk written %d bytes of %d", + n, bytes_to_write - bytes_written); + bytes_written += n; + } + txdone += bytes_written; + empty_rxfifo -= bytes_written; + + if (empty_rxfifo == 0 || txdone == ft232r_output_len) { + /* Get reply. */ + bytes_to_read = sizeof(reply) - empty_rxfifo - 2; + bytes_read = 0; + while (bytes_read < bytes_to_read) { + n = usb_bulk_read(adapter, OUT_EP, + (char *) reply, + bytes_to_read - bytes_read + 2, 2000); + if (n < 0) { + LOG_ERROR("usb bulk read failed"); + return ERROR_JTAG_DEVICE_ERROR; + } + if (n != bytes_to_read + 2) + LOG_ERROR("usb bulk read %d bytes of %d", + n, bytes_to_read - bytes_read + 2); + else + JTAG_DEBUG("usb bulk read %d bytes", n); + + if (n > 2) { + /* Copy data. */ + memcpy(ft232r_output + rxdone, reply + 2, n - 2); + bytes_read += n; + rxdone += n - 2; + } + } + empty_rxfifo = sizeof(reply) - 2; + } + } + ft232r_output_len = 0; + return ERROR_OK; +} + +/* + * Add one TCK/TMS/TDI sample to send buffer. + */ +static void ft232r_write(int tck, int tms, int tdi) +{ + unsigned out_value = NTRST | NSYSRST; + if (tck) + out_value |= TCK; + if (tms) + out_value |= TMS; + if (tdi) + out_value |= TDI; + + if (ft232r_output_len >= (int) sizeof(ft232r_output)) { + LOG_ERROR("ft232r_write: buffer overflow"); + return; + } + ft232r_output[ft232r_output_len++] = out_value; +} + +/* + * Control /TRST and /SYSRST pins. + * Perform immediate bitbang transaction. + */ +static void ft232r_reset(int trst, int srst) +{ + unsigned out_value = NTRST | NSYSRST; + LOG_DEBUG("ft232r_reset(%d,%d)", trst, srst); + + if (trst == 1) + out_value &= ~NTRST; /* switch /TRST low */ + else if (trst == 0) + out_value |= NTRST; /* switch /TRST high */ + + if (srst == 1) + out_value &= ~NSYSRST; /* switch /SYSRST low */ + else if (srst == 0) + out_value |= NSYSRST; /* switch /SYSRST high */ + + ft232r_output[ft232r_output_len++] = out_value; + ft232r_send_recv(); +} + +static int ft232r_speed(int divisor) +{ + int baud = (divisor == 0) ? 3000000 : + (divisor == 1) ? 2000000 : + 3000000 / divisor; + LOG_DEBUG("ft232r_speed(%d) rate %d bits/sec", divisor, baud); + + if (usb_control_msg(adapter, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, + SIO_SET_BAUD_RATE, divisor, + 0, 0, 0, 1000) != 0) { + LOG_ERROR("cannot set baud rate"); + return ERROR_JTAG_DEVICE_ERROR; + } + return ERROR_OK; +} + +static int ft232r_init(void) +{ + struct usb_bus *bus; + struct usb_device *dev; + char string[256]; + + /* Open by device description */ + if (ft232r_device_desc == NULL) { + LOG_WARNING("no ft232r device description specified, " + "using default 'FT232R USB UART'"); + ft232r_device_desc = "FT232R USB UART"; + } + + usb_init(); + usb_find_busses(); + usb_find_devices(); + for (bus = usb_get_busses(); bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if (dev->descriptor.idVendor == ft232r_vid && + dev->descriptor.idProduct == ft232r_pid) { + adapter = usb_open(dev); + if (!adapter) + continue; + + /* Check description. */ + if (usb_get_string_simple(adapter, + dev->descriptor.iProduct, + string, sizeof(string)) <= 0 || + strncmp(string, ft232r_device_desc, + sizeof(string)) != 0) { + usb_close(adapter); + continue; + } + goto found; + } + } + } + LOG_ERROR("USB adapter not found: vid=%04x, pid=%04x\n", + ft232r_vid, ft232r_pid); + return ERROR_JTAG_INIT_FAILED; +found: + usb_detach_kernel_driver_np(adapter, 0); + + if (usb_claim_interface(adapter, 0)) { + LOG_ERROR("usb_claim_interface failed"); + return ERROR_JTAG_INIT_FAILED; + } + + /* Reset the device. */ + if (usb_control_msg(adapter, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, + SIO_RESET, 0, 0, 0, 0, 1000) != 0) { + LOG_ERROR("unable to reset device"); + return ERROR_JTAG_INIT_FAILED; + } + + /* Sync bit bang mode. */ + if (usb_control_msg(adapter, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, + SIO_SET_BITMODE, TCK | TDI | TMS | NTRST | NSYSRST | 0x400, + 0, 0, 0, 1000) != 0) { + LOG_ERROR("cannot set sync bitbang mode"); + return ERROR_JTAG_INIT_FAILED; + } + + /* Exactly 500 nsec between updates. */ + unsigned divisor = 1; + unsigned char latency_timer = 1; + + /* Frequency divisor is 14-bit non-zero value. */ + if (usb_control_msg(adapter, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, + SIO_SET_BAUD_RATE, divisor, + 0, 0, 0, 1000) != 0) { + LOG_ERROR("cannot set baud rate"); + return ERROR_JTAG_INIT_FAILED; + } + if (usb_control_msg(adapter, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, + SIO_SET_LATENCY_TIMER, latency_timer, 0, 0, 0, 1000) != 0) { + LOG_ERROR("unable to set latency timer"); + return ERROR_JTAG_INIT_FAILED; + } + return ERROR_OK; +} + +static int ft232r_quit(void) +{ + if (usb_release_interface(adapter, 0) != 0) + LOG_ERROR("usb release interface failed"); + + usb_close(adapter); + return ERROR_OK; +} + +static int ft232r_speed_div(int divisor, int *khz) +{ + /* Maximum 3 Mbaud for bit bang mode. */ + if (divisor == 0) + *khz = 3000; + else if (divisor == 1) + *khz = 2000; + else + *khz = 3000 / divisor; + return ERROR_OK; +} + +static int ft232r_khz(int khz, int *divisor) +{ + if (khz == 0) { + LOG_DEBUG("RCLK not supported"); + return ERROR_FAIL; + } + + /* Calculate frequency divisor. */ + if (khz > 2500) + *divisor = 0; /* Special case: 3 MHz */ + else if (khz > 1700) + *divisor = 1; /* Special case: 2 MHz */ + else { + *divisor = (2*3000 / khz + 1) / 2; + if (*divisor > 0x3FFF) + *divisor = 0x3FFF; + } + return ERROR_OK; +} + +COMMAND_HANDLER(ft232r_handle_device_desc_command) +{ + if (CMD_ARGC == 1) + ft232r_device_desc = strdup(CMD_ARGV[0]); + else + LOG_ERROR("require exactly one argument to " + "ft232r_device_desc <description>"); + return ERROR_OK; +} + +COMMAND_HANDLER(ft232r_handle_vid_pid_command) +{ + if (CMD_ARGC > 2) { + LOG_WARNING("ignoring extra IDs in ft232r_vid_pid " + "(maximum is 1 pair)"); + CMD_ARGC = 2; + } + if (CMD_ARGC == 2) { + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], ft232r_vid); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], ft232r_pid); + } else + LOG_WARNING("incomplete ft232r_vid_pid configuration"); + + return ERROR_OK; +} + +COMMAND_HANDLER(ft232r_handle_pin_command) +{ + if (CMD_ARGC == 2) { +#if 0 + uint8_t mask; + unsigned int state; + if (!strcmp(CMD_ARGV[0], "pin6")) + mask = NCE; + else if (!strcmp(CMD_ARGV[0], "pin8")) + mask = NCS; + else { + LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"", + CMD_NAME); + return ERROR_COMMAND_SYNTAX_ERROR; + } + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], state); + if (state == 0) { + out_value &= ~mask; + ft232r_write_data(); + } else if (state == 1) { + out_value |= mask; + ft232r_write_data(); + } else { + LOG_ERROR("%s: pin state must be 0 or 1", CMD_NAME); + return ERROR_COMMAND_SYNTAX_ERROR; + } +#endif + return ERROR_OK; + } else { + LOG_ERROR("%s takes exactly two arguments", CMD_NAME); + return ERROR_COMMAND_SYNTAX_ERROR; + } +} + +static const struct command_registration ft232r_command_handlers[] = { + { + .name = "ft232r_device_desc", + .handler = ft232r_handle_device_desc_command, + .mode = COMMAND_CONFIG, + .help = "set the USB device description of the FT232R adapter", + .usage = "description-string", + }, + { + .name = "ft232r_vid_pid", + .handler = ft232r_handle_vid_pid_command, + .mode = COMMAND_CONFIG, + .help = "the vendor ID and product ID of the FT232R adapter", + .usage = "vid pid", + }, + { + .name = "ft232r", + .handler = ft232r_handle_pin_command, + .mode = COMMAND_ANY, + .help = "set pin state for the unused GPIO pins", + .usage = "(pin6|pin8) (0|1)", + }, + COMMAND_REGISTRATION_DONE +}; + +/* + * Synchronous bitbang protocol implementation. + */ + +static void syncbb_end_state(tap_state_t state) +{ + if (tap_is_state_stable(state)) + tap_set_end_state(state); + else { + LOG_ERROR("BUG: %i is not a valid end state", state); + exit(-1); + } +} + +static void syncbb_state_move(int skip) +{ + int i = 0, tms = 0; + uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); + int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); + + for (i = skip; i < tms_count; i++) { + tms = (tms_scan >> i) & 1; + ft232r_write(0, tms, 0); + ft232r_write(1, tms, 0); + } + ft232r_write(0, tms, 0); + + tap_set_state(tap_get_end_state()); +} + +/** + * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG + * (or SWD) state machine. + */ +static int syncbb_execute_tms(struct jtag_command *cmd) +{ + unsigned num_bits = cmd->cmd.tms->num_bits; + const uint8_t *bits = cmd->cmd.tms->bits; + + DEBUG_JTAG_IO("TMS: %d bits", num_bits); + + int tms = 0; + for (unsigned i = 0; i < num_bits; i++) { + tms = ((bits[i/8] >> (i % 8)) & 1); + ft232r_write(0, tms, 0); + ft232r_write(1, tms, 0); + } + ft232r_write(0, tms, 0); + + return ERROR_OK; +} + +static void syncbb_path_move(struct pathmove_command *cmd) +{ + int num_states = cmd->num_states; + int state_count; + int tms = 0; + + state_count = 0; + while (num_states) { + if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) { + tms = 0; + } else + if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) { + tms = 1; + } else { + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", + tap_state_name(tap_get_state()), + tap_state_name(cmd->path[state_count])); + exit(-1); + } + + ft232r_write(0, tms, 0); + ft232r_write(1, tms, 0); + + tap_set_state(cmd->path[state_count]); + state_count++; + num_states--; + } + + ft232r_write(0, tms, 0); + + tap_set_end_state(tap_get_state()); +} + +static void syncbb_runtest(int num_cycles) +{ + int i; + + tap_state_t saved_end_state = tap_get_end_state(); + + /* only do a state_move when we're not already in IDLE */ + if (tap_get_state() != TAP_IDLE) { + syncbb_end_state(TAP_IDLE); + syncbb_state_move(0); + } + + /* execute num_cycles */ + for (i = 0; i < num_cycles; i++) { + ft232r_write(0, 0, 0); + ft232r_write(1, 0, 0); + } + ft232r_write(0, 0, 0); + + /* finish in end_state */ + syncbb_end_state(saved_end_state); + if (tap_get_state() != tap_get_end_state()) + syncbb_state_move(0); +} + +/** + * Function syncbb_stableclocks + * issues a number of clock cycles while staying in a stable state. + * Because the TMS value required to stay in the RESET state is a 1, whereas + * the TMS value required to stay in any of the other stable states is a 0, + * this function checks the current stable state to decide on the value of TMS + * to use. + */ +static void syncbb_stableclocks(int num_cycles) +{ + int tms = (tap_get_state() == TAP_RESET ? 1 : 0); + int i; + + /* send num_cycles clocks onto the cable */ + for (i = 0; i < num_cycles; i++) { + ft232r_write(1, tms, 0); + ft232r_write(0, tms, 0); + } +} + +static void syncbb_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) +{ + tap_state_t saved_end_state = tap_get_end_state(); + int bit_cnt, bit0_index; + + if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) { + if (ir_scan) + syncbb_end_state(TAP_IRSHIFT); + else + syncbb_end_state(TAP_DRSHIFT); + + syncbb_state_move(0); + syncbb_end_state(saved_end_state); + } + + bit0_index = ft232r_output_len; + for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { + int tms = (bit_cnt == scan_size-1) ? 1 : 0; + int tdi; + int bytec = bit_cnt/8; + int bcval = 1 << (bit_cnt % 8); + + /* if we're just reading the scan, but don't care about the output + * default to outputting 'low', this also makes valgrind traces more readable, + * as it removes the dependency on an uninitialised value + */ + tdi = 0; + if ((type != SCAN_IN) && (buffer[bytec] & bcval)) + tdi = 1; + + ft232r_write(0, tms, tdi); + ft232r_write(1, tms, tdi); + } + + if (tap_get_state() != tap_get_end_state()) { + /* we *KNOW* the above loop transitioned out of + * the shift state, so we skip the first state + * and move directly to the end state. + */ + syncbb_state_move(1); + } + ft232r_send_recv(); + + if (type != SCAN_OUT) + for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { + int bytec = bit_cnt/8; + int bcval = 1 << (bit_cnt % 8); + int val = ft232r_output[bit0_index + bit_cnt*2 + 1]; + + if (val & READ_TDO) + buffer[bytec] |= bcval; + else + buffer[bytec] &= ~bcval; + } +} + +static int syncbb_execute_queue(void) +{ + struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + int scan_size; + enum scan_type type; + uint8_t *buffer; + int retval; + + /* return ERROR_OK, unless a jtag_read_buffer returns a failed check + * that wasn't handled by a caller-provided error handler + */ + retval = ERROR_OK; + +/* ft232r_blink(1);*/ + + while (cmd) { + switch (cmd->type) { + case JTAG_RESET: + JTAG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); + + if ((cmd->cmd.reset->trst == 1) || + (cmd->cmd.reset->srst && + (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) { + tap_set_state(TAP_RESET); + } + ft232r_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + break; + + case JTAG_RUNTEST: + JTAG_DEBUG("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, + tap_state_name(cmd->cmd.runtest->end_state)); + + syncbb_end_state(cmd->cmd.runtest->end_state); + syncbb_runtest(cmd->cmd.runtest->num_cycles); + break; + + case JTAG_STABLECLOCKS: + /* this is only allowed while in a stable state. A check for a stable + * state was done in jtag_add_clocks() + */ + syncbb_stableclocks(cmd->cmd.stableclocks->num_cycles); + break; + + case JTAG_TLR_RESET: /* renamed from JTAG_STATEMOVE */ + JTAG_DEBUG("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state)); + + syncbb_end_state(cmd->cmd.statemove->end_state); + syncbb_state_move(0); + break; + + case JTAG_PATHMOVE: + JTAG_DEBUG("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, + tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); + + syncbb_path_move(cmd->cmd.pathmove); + break; + + case JTAG_SCAN: + JTAG_DEBUG("%s scan end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", + tap_state_name(cmd->cmd.scan->end_state)); + + syncbb_end_state(cmd->cmd.scan->end_state); + scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); + type = jtag_scan_type(cmd->cmd.scan); + syncbb_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); + if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + if (buffer) + free(buffer); + break; + + case JTAG_SLEEP: + JTAG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us); + + jtag_sleep(cmd->cmd.sleep->us); + break; + + case JTAG_TMS: + retval = syncbb_execute_tms(cmd); + break; + default: + LOG_ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); + } + if (ft232r_output_len > 0) + ft232r_send_recv(); + cmd = cmd->next; + } +/* ft232r_blink(0);*/ + + return retval; +} + +struct jtag_interface ft232r_interface = { + .name = "ft232r", + .commands = ft232r_command_handlers, + .transports = jtag_only, + .supported = DEBUG_CAP_TMS_SEQ, + + .execute_queue = syncbb_execute_queue, + + .speed = ft232r_speed, + .init = ft232r_init, + .quit = ft232r_quit, + .speed_div = ft232r_speed_div, + .khz = ft232r_khz, +}; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 174c63a..ddeadb4 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -60,6 +60,9 @@ extern struct jtag_interface usb_blaster_interface; #if BUILD_JTAG_VPI == 1 extern struct jtag_interface jtag_vpi_interface; #endif +#if BUILD_FT232R == 1 +extern struct jtag_interface ft232r_interface; +#endif #if BUILD_AMTJTAGACCEL == 1 extern struct jtag_interface amt_jtagaccel_interface; #endif @@ -159,6 +162,9 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_JTAG_VPI == 1 &jtag_vpi_interface, #endif +#if BUILD_FT232R == 1 + &ft232r_interface, +#endif #if BUILD_AMTJTAGACCEL == 1 &amt_jtagaccel_interface, #endif diff --git a/tcl/interface/ft232r.cfg b/tcl/interface/ft232r.cfg new file mode 100644 index 0000000..707bf8f --- /dev/null +++ b/tcl/interface/ft232r.cfg @@ -0,0 +1,3 @@ +interface ft232r +ft232r_device_desc "FT232R USB UART" +adapter_khz 1000 -- ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
