X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fft2232.c;h=881d7c772b79ac01f729326e65ee2db75ca4c56a;hp=30695a9ab0abada742bf80db447c6ebb845c917c;hb=eac1bc55d22b40d6afe7374b42779218ca1bb26b;hpb=6512e5e36b067ae458cb7f6a9fdfb08d38da3583 diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c index 30695a9ab0..881d7c772b 100644 --- a/src/jtag/drivers/ft2232.c +++ b/src/jtag/drivers/ft2232.c @@ -27,13 +27,52 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -/* This code uses information contained in the MPSSE specification which was +/** + * @file + * JTAG adapters based on the FT2232 full and high speed USB parts are + * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters + * are discrete, but development boards may integrate them as alternatives + * to more capable (and expensive) third party JTAG pods. + * + * JTAG uses only one of the two communications channels ("MPSSE engines") + * on these devices. Adapters based on FT4232 parts have four ports/channels + * (A/B/C/D), instead of just two (A/B). + * + * Especially on development boards integrating one of these chips (as + * opposed to discrete pods/dongles), the additional channels can be used + * for a variety of purposes, but OpenOCD only uses one channel at a time. + * + * - As a USB-to-serial adapter for the target's console UART ... + * which may be able to support ROM boot loaders that load initial + * firmware images to flash (or SRAM). + * + * - On systems which support ARM's SWD in addition to JTAG, or instead + * of it, that second port can be used for reading SWV/SWO trace data. + * + * - Additional JTAG links, e.g. to a CPLD or * FPGA. + * + * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG + * request/response interactions involve round trips over the USB link. + * A "smart" JTAG adapter has intelligence close to the scan chain, so it + * can for example poll quickly for a status change (usually taking on the + * order of microseconds not milliseconds) before beginning a queued + * transaction which require the previous one to have completed. + * + * There are dozens of adapters of this type, differing in details which + * this driver needs to understand. Those "layout" details are required + * as part of FT2232 driver configuration. + * + * This code uses information contained in the MPSSE specification which was * found here: * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf * Hereafter this is called the "MPSSE Spec". * * The datasheet for the ftdichip.com's FT2232D part is here: * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf + * + * Also note the issue with code 0x4b (clock data to TMS) noted in + * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html + * which can affect longer JTAG state paths. */ #ifdef HAVE_CONFIG_H @@ -41,8 +80,8 @@ #endif /* project specific includes */ -#include "interface.h" -#include "commands.h" +#include +#include #include #if IS_CYGWIN == 1 @@ -60,6 +99,17 @@ /* FT2232 access library includes */ #if BUILD_FT2232_FTD2XX == 1 #include +#include "ftd2xx_common.h" + +enum ftdi_interface +{ + INTERFACE_ANY = 0, + INTERFACE_A = 1, + INTERFACE_B = 2, + INTERFACE_C = 3, + INTERFACE_D = 4 +}; + #elif BUILD_FT2232_LIBFTDI == 1 #include #endif @@ -105,7 +155,6 @@ static int ft2232_stableclocks(int num_cycles, struct jtag_command* cmd); static char * ft2232_device_desc_A = NULL; static char* ft2232_device_desc = NULL; static char* ft2232_serial = NULL; -static char* ft2232_layout = NULL; static uint8_t ft2232_latency = 2; static unsigned ft2232_max_tck = FTDI_2232C_MAX_TCK; @@ -119,13 +168,17 @@ struct ft2232_layout { int (*init)(void); void (*reset)(int trst, int srst); void (*blink)(void); + int channel; }; /* init procedures for supported layouts */ static int usbjtag_init(void); static int jtagkey_init(void); +static int lm3s811_jtag_init(void); +static int icdi_jtag_init(void); static int olimex_jtag_init(void); static int flyswatter_init(void); +static int minimodule_init(void); static int turtle_init(void); static int comstick_init(void); static int stm32stick_init(void); @@ -133,14 +186,20 @@ static int axm0432_jtag_init(void); static int sheevaplug_init(void); static int icebear_jtag_init(void); static int cortino_jtag_init(void); +static int signalyzer_init(void); static int signalyzer_h_init(void); static int ktlink_init(void); +static int redbee_init(void); +static int lisa_l_init(void); +static int flossjtag_init(void); +static int xds100v2_init(void); /* reset procedures for supported layouts */ -static void usbjtag_reset(int trst, int srst); +static void ftx23_reset(int trst, int srst); static void jtagkey_reset(int trst, int srst); static void olimex_jtag_reset(int trst, int srst); static void flyswatter_reset(int trst, int srst); +static void minimodule_reset(int trst, int srst); static void turtle_reset(int trst, int srst); static void comstick_reset(int trst, int srst); static void stm32stick_reset(int trst, int srst); @@ -149,6 +208,8 @@ static void sheevaplug_reset(int trst, int srst); static void icebear_jtag_reset(int trst, int srst); static void signalyzer_h_reset(int trst, int srst); static void ktlink_reset(int trst, int srst); +static void redbee_reset(int trst, int srst); +static void xds100v2_reset(int trst, int srst); /* blink procedures for layouts that support a blinking led */ static void olimex_jtag_blink(void); @@ -156,36 +217,143 @@ static void flyswatter_jtag_blink(void); static void turtle_jtag_blink(void); static void signalyzer_h_blink(void); static void ktlink_blink(void); +static void lisa_l_blink(void); +static void flossjtag_blink(void); + +/* common transport support options */ + +//static const char *jtag_and_swd[] = { "jtag", "swd", NULL }; static const struct ft2232_layout ft2232_layouts[] = { - { "usbjtag", usbjtag_init, usbjtag_reset, NULL }, - { "jtagkey", jtagkey_init, jtagkey_reset, NULL }, - { "jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL }, - { "oocdlink", jtagkey_init, jtagkey_reset, NULL }, - { "signalyzer", usbjtag_init, usbjtag_reset, NULL }, - { "evb_lm3s811", usbjtag_init, usbjtag_reset, NULL }, - { "luminary_icdi", usbjtag_init, usbjtag_reset, NULL }, - { "olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink }, - { "flyswatter", flyswatter_init, flyswatter_reset, flyswatter_jtag_blink }, - { "turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink }, - { "comstick", comstick_init, comstick_reset, NULL }, - { "stm32stick", stm32stick_init, stm32stick_reset, NULL }, - { "axm0432_jtag", axm0432_jtag_init, axm0432_jtag_reset, NULL }, - { "sheevaplug", sheevaplug_init, sheevaplug_reset, NULL }, - { "icebear", icebear_jtag_init, icebear_jtag_reset, NULL }, - { "cortino", cortino_jtag_init, comstick_reset, NULL }, - { "signalyzer-h", signalyzer_h_init, signalyzer_h_reset, signalyzer_h_blink }, - { "ktlink", ktlink_init, ktlink_reset, ktlink_blink }, - { NULL, NULL, NULL, NULL }, + { .name = "usbjtag", + .init = usbjtag_init, + .reset = ftx23_reset, + }, + { .name = "jtagkey", + .init = jtagkey_init, + .reset = jtagkey_reset, + }, + { .name = "jtagkey_prototype_v1", + .init = jtagkey_init, + .reset = jtagkey_reset, + }, + { .name = "oocdlink", + .init = jtagkey_init, + .reset = jtagkey_reset, + }, + { .name = "signalyzer", + .init = signalyzer_init, + .reset = ftx23_reset, + }, + { .name = "evb_lm3s811", + .init = lm3s811_jtag_init, + .reset = ftx23_reset, + }, + { .name = "luminary_icdi", + .init = icdi_jtag_init, + .reset = ftx23_reset, + }, + { .name = "olimex-jtag", + .init = olimex_jtag_init, + .reset = olimex_jtag_reset, + .blink = olimex_jtag_blink + }, + { .name = "flyswatter", + .init = flyswatter_init, + .reset = flyswatter_reset, + .blink = flyswatter_jtag_blink + }, + { .name = "minimodule", + .init = minimodule_init, + .reset = minimodule_reset, + }, + { .name = "turtelizer2", + .init = turtle_init, + .reset = turtle_reset, + .blink = turtle_jtag_blink + }, + { .name = "comstick", + .init = comstick_init, + .reset = comstick_reset, + }, + { .name = "stm32stick", + .init = stm32stick_init, + .reset = stm32stick_reset, + }, + { .name = "axm0432_jtag", + .init = axm0432_jtag_init, + .reset = axm0432_jtag_reset, + }, + { .name = "sheevaplug", + .init = sheevaplug_init, + .reset = sheevaplug_reset, + }, + { .name = "icebear", + .init = icebear_jtag_init, + .reset = icebear_jtag_reset, + }, + { .name = "cortino", + .init = cortino_jtag_init, + .reset = comstick_reset, + }, + { .name = "signalyzer-h", + .init = signalyzer_h_init, + .reset = signalyzer_h_reset, + .blink = signalyzer_h_blink + }, + { .name = "ktlink", + .init = ktlink_init, + .reset = ktlink_reset, + .blink = ktlink_blink + }, + { .name = "redbee-econotag", + .init = redbee_init, + .reset = redbee_reset, + }, + { .name = "redbee-usb", + .init = redbee_init, + .reset = redbee_reset, + .channel = INTERFACE_B, + }, + { .name = "lisa-l", + .init = lisa_l_init, + .reset = ftx23_reset, + .blink = lisa_l_blink, + .channel = INTERFACE_B, + }, + { .name = "flossjtag", + .init = flossjtag_init, + .reset = ftx23_reset, + .blink = flossjtag_blink, + }, + { .name = "xds100v2", + .init = xds100v2_init, + .reset = xds100v2_reset, + }, + { .name = NULL, /* END OF TABLE */ }, }; -static uint8_t nTRST, nTRSTnOE, nSRST, nSRSTnOE; +/* bitmask used to drive nTRST; usually a GPIOLx signal */ +static uint8_t nTRST; +static uint8_t nTRSTnOE; +/* bitmask used to drive nSRST; usually a GPIOLx signal */ +static uint8_t nSRST; +static uint8_t nSRSTnOE; +/** the layout being used with this debug session */ static const struct ft2232_layout *layout; + +/** default bitmask values driven on DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ static uint8_t low_output = 0x0; + +/* note that direction bit == 1 means that signal is an output */ + +/** default direction bitmask for DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ static uint8_t low_direction = 0x0; +/** default value bitmask for CBUS GPIOH(0..4) */ static uint8_t high_output = 0x0; +/** default direction bitmask for CBUS GPIOH(0..4) */ static uint8_t high_direction = 0x0; #if BUILD_FT2232_FTD2XX == 1 @@ -212,6 +380,12 @@ static int require_send; a comment would have been nice. */ +#if BUILD_FT2232_FTD2XX == 1 +#define FT2232_BUFFER_READ_QUEUE_SIZE (64*64) +#else +#define FT2232_BUFFER_READ_QUEUE_SIZE (64*4) +#endif + #define FT2232_BUFFER_SIZE 131072 static uint8_t* ft2232_buffer = NULL; @@ -338,17 +512,16 @@ static int ft2232_write(uint8_t* buf, int size, uint32_t* bytes_written) { #if BUILD_FT2232_FTD2XX == 1 FT_STATUS status; - DWORD dw_bytes_written; + DWORD dw_bytes_written = 0; if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK) { *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %lu", status); + LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } else { *bytes_written = dw_bytes_written; - return ERROR_OK; } #elif BUILD_FT2232_LIBFTDI == 1 int retval; @@ -361,9 +534,15 @@ static int ft2232_write(uint8_t* buf, int size, uint32_t* bytes_written) else { *bytes_written = retval; - return ERROR_OK; } #endif + + if (*bytes_written != (uint32_t)size) + { + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; } static int ft2232_read(uint8_t* buf, uint32_t size, uint32_t* bytes_read) @@ -380,7 +559,7 @@ static int ft2232_read(uint8_t* buf, uint32_t size, uint32_t* bytes_read) *bytes_read, &dw_bytes_read)) != FT_OK) { *bytes_read = 0; - LOG_ERROR("FT_Read returned: %lu", status); + LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read += dw_bytes_read; @@ -437,8 +616,9 @@ static int ft2232h_ft4232h_adaptive_clocking(bool enable) LOG_DEBUG("%2.2x", buf); uint32_t bytes_written; - int retval = ft2232_write(&buf, 1, &bytes_written); - if ((ERROR_OK != retval) || (bytes_written != 1)) + int retval; + + if ((retval = ft2232_write(&buf, sizeof(buf), &bytes_written)) != ERROR_OK) { LOG_ERROR("couldn't write command to %s adaptive clocking" , enable ? "enable" : "disable"); @@ -457,8 +637,8 @@ static int ft2232h_ft4232h_clk_divide_by_5(bool enable) { uint32_t bytes_written; uint8_t buf = enable ? 0x8b : 0x8a; - int retval = ft2232_write(&buf, 1, &bytes_written); - if ((ERROR_OK != retval) || (bytes_written != 1)) + + if (ft2232_write(&buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't write command to %s clk divide by 5" , enable ? "enable" : "disable"); @@ -495,7 +675,7 @@ static int ft2232_speed(int speed) buf[2] = (speed >> 8) & 0xff; /* valueH */ LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if ((retval = ft2232_write(buf, sizeof(buf), &bytes_written)) != ERROR_OK) { LOG_ERROR("couldn't set FT2232 TCK speed"); return retval; @@ -605,7 +785,7 @@ static void ft2232_debug_dump_buffer(void) for (i = 0; i < ft2232_buffer_size; i++) { - line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]); + line_p += snprintf(line_p, sizeof(line) - (line_p - line), "%2.2x ", ft2232_buffer[i]); if (i % 16 == 15) { LOG_DEBUG("%s", line); @@ -1165,7 +1345,6 @@ static int ft2232_large_scan(struct scan_command* cmd, enum scan_type type, uint LOG_DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, (int)bytes_read); - receive_pointer += bytes_read; } return ERROR_OK; @@ -1220,7 +1399,8 @@ static int ft2232_predict_scan_in(int scan_size, enum scan_type type) return predicted_size; } -static void usbjtag_reset(int trst, int srst) +/* semi-generic FT2232/FT4232 reset code */ +static void ftx23_reset(int trst, int srst) { enum reset_types jtag_reset_config = jtag_get_reset_config(); if (trst == 1) @@ -1391,6 +1571,24 @@ static void flyswatter_reset(int trst, int srst) LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); } +static void minimodule_reset(int trst, int srst) +{ + if (srst == 1) + { + low_output &= ~nSRST; + } + else if (srst == 0) + { + low_output |= nSRST; + } + + /* command "set data bits low byte" */ + buffer_write(0x80); + buffer_write(low_output); + buffer_write(low_direction); + LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); +} + static void turtle_reset(int trst, int srst) { trst = trst; @@ -1491,6 +1689,66 @@ static void sheevaplug_reset(int trst, int srst) LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } +static void redbee_reset(int trst, int srst) +{ + if (trst == 1) + { + tap_set_state(TAP_RESET); + high_output &= ~nTRST; + } + else if (trst == 0) + { + high_output |= nTRST; + } + + if (srst == 1) + { + high_output &= ~nSRST; + } + else if (srst == 0) + { + high_output |= nSRST; + } + + /* command "set data bits low byte" */ + buffer_write(0x82); + buffer_write(high_output); + buffer_write(high_direction); + LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " + "high_direction: 0x%2.2x", trst, srst, high_output, + high_direction); +} + +static void xds100v2_reset(int trst, int srst) +{ + if (trst == 1) + { + tap_set_state(TAP_RESET); + high_output &= ~nTRST; + } + else if (trst == 0) + { + high_output |= nTRST; + } + + if (srst == 1) + { + high_output |= nSRST; + } + else if (srst == 0) + { + high_output &= ~nSRST; + } + + /* command "set data bits low byte" */ + buffer_write(0x82); + buffer_write(high_output); + buffer_write(high_direction); + LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " + "high_direction: 0x%2.2x", trst, srst, high_output, + high_direction); +} + static int ft2232_execute_runtest(struct jtag_command *cmd) { int retval; @@ -1592,6 +1850,72 @@ static int ft2232_execute_statemove(struct jtag_command *cmd) return retval; } +/** + * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG + * (or SWD) state machine. + */ +static int ft2232_execute_tms(struct jtag_command *cmd) +{ + int retval = ERROR_OK; + unsigned num_bits = cmd->cmd.tms->num_bits; + const uint8_t *bits = cmd->cmd.tms->bits; + unsigned count; + + DEBUG_JTAG_IO("TMS: %d bits", num_bits); + + /* only send the maximum buffer size that FT2232C can handle */ + count = 3 * DIV_ROUND_UP(num_bits, 4); + if (ft2232_buffer_size + 3*count + 1 > FT2232_BUFFER_SIZE) { + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + + require_send = 0; + first_unsent = cmd; + } + + /* Shift out in batches of at most 6 bits; there's a report of an + * FT2232 bug in this area, where shifting exactly 7 bits can make + * problems with TMS signaling for the last clock cycle: + * + * http://developer.intra2net.com/mailarchive/html/ + * libftdi/2009/msg00292.html + * + * Command 0x4b is: "Clock Data to TMS/CS Pin (no Read)" + * + * Note that pathmoves in JTAG are not often seven bits, so that + * isn't a particularly likely situation outside of "special" + * signaling such as switching between JTAG and SWD modes. + */ + while (num_bits) { + if (num_bits <= 6) { + buffer_write(0x4b); + buffer_write(num_bits - 1); + buffer_write(*bits & 0x3f); + break; + } + + /* Yes, this is lazy ... we COULD shift out more data + * bits per operation, but doing it in nybbles is easy + */ + buffer_write(0x4b); + buffer_write(3); + buffer_write(*bits & 0xf); + num_bits -= 4; + + count = (num_bits > 4) ? 4 : num_bits; + + buffer_write(0x4b); + buffer_write(count - 1); + buffer_write((*bits >> 4) & 0xf); + num_bits -= count; + + bits++; + } + + require_send = 1; + return retval; +} + static int ft2232_execute_pathmove(struct jtag_command *cmd) { int predicted_size = 0; @@ -1744,20 +2068,23 @@ static int ft2232_execute_stableclocks(struct jtag_command *cmd) static int ft2232_execute_command(struct jtag_command *cmd) { int retval; - retval = ERROR_OK; switch (cmd->type) { case JTAG_RESET: retval = ft2232_execute_reset(cmd); break; case JTAG_RUNTEST: retval = ft2232_execute_runtest(cmd); break; - case JTAG_STATEMOVE: retval = ft2232_execute_statemove(cmd); break; + case JTAG_TLR_RESET: retval = ft2232_execute_statemove(cmd); break; case JTAG_PATHMOVE: retval = ft2232_execute_pathmove(cmd); break; case JTAG_SCAN: retval = ft2232_execute_scan(cmd); break; case JTAG_SLEEP: retval = ft2232_execute_sleep(cmd); break; case JTAG_STABLECLOCKS: retval = ft2232_execute_stableclocks(cmd); break; + case JTAG_TMS: + retval = ft2232_execute_tms(cmd); + break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); + retval = ERROR_JTAG_QUEUE_FAILED; + break; } return retval; } @@ -1784,12 +2111,20 @@ static int ft2232_execute_queue(void) while (cmd) { + /* fill the write buffer with the desired command */ if (ft2232_execute_command(cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; - /* Start reading input before FT2232 TX buffer fills up */ + /* Start reading input before FT2232 TX buffer fills up. + * Sometimes this happens because we don't know the + * length of the last command before we execute it. So + * we simple inform the user. + */ cmd = cmd->next; - if (ft2232_expect_read > 256) + + if (ft2232_expect_read >= FT2232_BUFFER_READ_QUEUE_SIZE ) { + if (ft2232_expect_read > (FT2232_BUFFER_READ_QUEUE_SIZE+1) ) + LOG_DEBUG("read buffer size looks too high %d/%d",ft2232_expect_read,(FT2232_BUFFER_READ_QUEUE_SIZE+1)); if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; first_unsent = cmd; @@ -1814,7 +2149,12 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor char* openex_string = NULL; uint8_t latency_timer; - LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", ft2232_layout, vid, pid); + if (layout == NULL) { + LOG_WARNING("No ft2232 layout specified'"); + return ERROR_JTAG_INIT_FAILED; + } + + LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", layout->name, vid, pid); #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ @@ -1862,7 +2202,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor } else { /* drat, give the user a meaningfull message. * telling the use we tried *BOTH* methods. */ - LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'\n", + LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'", ft2232_device_desc, ft2232_device_desc_A); } @@ -1875,11 +2215,13 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor if (more) { - LOG_WARNING("unable to open ftdi device (trying more): %lu", status); + LOG_WARNING("unable to open ftdi device (trying more): %s", + ftd2xx_status_string(status)); *try_more = 1; return ERROR_JTAG_INIT_FAILED; } - LOG_ERROR("unable to open ftdi device: %lu", status); + LOG_ERROR("unable to open ftdi device: %s", + ftd2xx_status_string(status)); status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); if (status == FT_OK) { @@ -1895,7 +2237,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor if (status == FT_OK) { - LOG_ERROR("ListDevices: %lu\n", num_devices); + LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); for (i = 0; i < num_devices; i++) LOG_ERROR("%" PRIu32 ": \"%s\"", i, desc_array[i]); } @@ -1907,21 +2249,35 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor } else { - LOG_ERROR("ListDevices: NONE\n"); + LOG_ERROR("ListDevices: NONE"); } return ERROR_JTAG_INIT_FAILED; } if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK) { - LOG_ERROR("unable to set latency timer: %lu", status); + LOG_ERROR("unable to set latency timer: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK) { - LOG_ERROR("unable to get latency timer: %lu", status); - return ERROR_JTAG_INIT_FAILED; + /* ftd2xx 1.04 (linux) has a bug when calling FT_GetLatencyTimer + * so ignore errors if using this driver version */ + DWORD dw_version; + + status = FT_GetDriverVersion(ftdih, &dw_version); + LOG_ERROR("unable to get latency timer: %s", + ftd2xx_status_string(status)); + + if ((status == FT_OK) && (dw_version == 0x10004)) { + LOG_ERROR("ftd2xx 1.04 detected - this has known issues " \ + "with FT_GetLatencyTimer, upgrade to a newer version"); + } + else { + return ERROR_JTAG_INIT_FAILED; + } } else { @@ -1930,19 +2286,22 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK) { - LOG_ERROR("unable to set timeouts: %lu", status); + LOG_ERROR("unable to set timeouts: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK) { - LOG_ERROR("unable to enable bit i/o mode: %lu", status); + LOG_ERROR("unable to enable bit i/o mode: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } if ((status = FT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID, SerialNumber, Description, NULL)) != FT_OK) { - LOG_ERROR("unable to get FT_GetDeviceInfo: %lu", status); + LOG_ERROR("unable to get FT_GetDeviceInfo: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } else @@ -1952,8 +2311,8 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; unsigned type_index = ((unsigned)ftdi_device <= no_of_known_types) ? ftdi_device : FT_DEVICE_UNKNOWN; - LOG_INFO("device: %lu \"%s\"", ftdi_device, type_str[type_index]); - LOG_INFO("deviceID: %lu", deviceID); + LOG_INFO("device: %" PRIu32 " \"%s\"", (uint32_t)ftdi_device, type_str[type_index]); + LOG_INFO("deviceID: %" PRIu32, (uint32_t)deviceID); LOG_INFO("SerialNumber: %s", SerialNumber); LOG_INFO("Description: %s", Description); } @@ -1967,7 +2326,8 @@ static int ft2232_purge_ftd2xx(void) if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK) { - LOG_ERROR("error purging ftd2xx device: %lu", status); + LOG_ERROR("error purging ftd2xx device: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } @@ -1977,17 +2337,25 @@ static int ft2232_purge_ftd2xx(void) #endif /* BUILD_FT2232_FTD2XX == 1 */ #if BUILD_FT2232_LIBFTDI == 1 -static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int* try_more) +static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int* try_more, int channel) { uint8_t latency_timer; + if (layout == NULL) { + LOG_WARNING("No ft2232 layout specified'"); + return ERROR_JTAG_INIT_FAILED; + } + LOG_DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)", - ft2232_layout, vid, pid); + layout->name, vid, pid); if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; - if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0) + /* default to INTERFACE_A */ + if(channel == INTERFACE_ANY) { channel = INTERFACE_A; } + + if (ftdi_set_interface(&ftdic, channel) < 0) { LOG_ERROR("unable to select FT2232 channel A: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; @@ -2054,13 +2422,51 @@ static int ft2232_purge_libftdi(void) #endif /* BUILD_FT2232_LIBFTDI == 1 */ +static int ft2232_set_data_bits_low_byte( uint8_t value, uint8_t direction ) +{ + uint8_t buf[3]; + uint32_t bytes_written; + + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = value; /* value */ + buf[2] = direction; /* direction */ + + LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) + { + LOG_ERROR("couldn't initialize data bits low byte"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +static int ft2232_set_data_bits_high_byte( uint8_t value, uint8_t direction ) +{ + uint8_t buf[3]; + uint32_t bytes_written; + + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = value; /* value */ + buf[2] = direction; /* direction */ + + LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) + { + LOG_ERROR("couldn't initialize data bits high byte"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + static int ft2232_init(void) { uint8_t buf[1]; int retval; uint32_t bytes_written; - const struct ft2232_layout* cur_layout = ft2232_layouts; - int i; if (tap_get_tms_path_len(TAP_IRPAUSE,TAP_IRPAUSE) == 7) { @@ -2071,29 +2477,12 @@ static int ft2232_init(void) LOG_DEBUG("ft2232 interface using shortest path jtag state transitions"); } - if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0)) - { - ft2232_layout = "usbjtag"; - LOG_WARNING("No ft2232 layout specified, using default 'usbjtag'"); - } - - while (cur_layout->name) - { - if (strcmp(cur_layout->name, ft2232_layout) == 0) - { - layout = cur_layout; - break; - } - cur_layout++; - } - - if (!layout) - { - LOG_ERROR("No matching layout found for %s", ft2232_layout); + if (layout == NULL) { + LOG_WARNING("No ft2232 layout specified'"); return ERROR_JTAG_INIT_FAILED; } - for (i = 0; 1; i++) + for (int i = 0; 1; i++) { /* * "more indicates that there are more IDs to try, so we should @@ -2112,7 +2501,7 @@ static int ft2232_init(void) more, &try_more); #elif BUILD_FT2232_LIBFTDI == 1 retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], - more, &try_more); + more, &try_more, layout->channel); #endif if (retval >= 0) break; @@ -2140,10 +2529,8 @@ static int ft2232_init(void) return ERROR_JTAG_INIT_FAILED; } - ft2232_speed(jtag_get_speed()); - buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */ - if (((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) || (bytes_written != 1)) + if ((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) { LOG_ERROR("couldn't write to FT2232 to disable loopback"); return ERROR_JTAG_INIT_FAILED; @@ -2158,52 +2545,21 @@ static int ft2232_init(void) return ERROR_OK; } -static int usbjtag_init(void) +/** Updates defaults for DBUS signals: the four JTAG signals + * (TCK, TDI, TDO, TMS) and * the four GPIOL signals. + */ +static inline void ftx232_dbus_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x08; low_direction = 0x0b; +} - if (strcmp(ft2232_layout, "usbjtag") == 0) - { - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - } - else if (strcmp(ft2232_layout, "signalyzer") == 0) - { - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - } - else if (strcmp(ft2232_layout, "evb_lm3s811") == 0) - { - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = 0x20; - nSRSTnOE = 0x20; - low_output = 0x88; - low_direction = 0x8b; - } - else if (strcmp(ft2232_layout, "luminary_icdi") == 0) - { - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = 0x20; - nSRSTnOE = 0x20; - low_output = 0x88; - low_direction = 0xcb; - } - else - { - LOG_ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout); - return ERROR_JTAG_INIT_FAILED; - } - +/** Initializes DBUS signals: the four JTAG signals (TCK, TDI, TDO, TMS), + * the four GPIOL signals. Initialization covers value and direction, + * as customized for each layout. + */ +static int ftx232_dbus_write(void) +{ enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { @@ -2228,35 +2584,111 @@ static int usbjtag_init(void) } /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, xRST high) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'USBJTAG' layout"); + LOG_ERROR("couldn't initialize FT2232 DBUS"); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; } -static int axm0432_jtag_init(void) +static int usbjtag_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; + /* + * NOTE: This is now _specific_ to the "usbjtag" layout. + * Don't try cram any more layouts into this. + */ + ftx232_dbus_init(); - low_output = 0x08; + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + + return ftx232_dbus_write(); +} + +static int lm3s811_jtag_init(void) +{ + ftx232_dbus_init(); + + /* There are multiple revisions of LM3S811 eval boards: + * - Rev B (and older?) boards have no SWO trace support. + * - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN; + * they should use the "luminary_icdi" layout instead. + */ + nTRST = 0x0; + nTRSTnOE = 0x00; + nSRST = 0x20; + nSRSTnOE = 0x20; + low_output = 0x88; + low_direction = 0x8b; + + return ftx232_dbus_write(); +} + +static int icdi_jtag_init(void) +{ + ftx232_dbus_init(); + + /* Most Luminary eval boards support SWO trace output, + * and should use this "luminary_icdi" layout. + * + * ADBUS 0..3 are used for JTAG as usual. GPIOs are used + * to switch between JTAG and SWD, or switch the ft2232 UART + * on the second MPSSE channel/interface (BDBUS) + * between (i) the stellaris UART (on Luminary boards) + * or (ii) SWO trace data (generic). + * + * We come up in JTAG mode and may switch to SWD later (with + * SWO/trace option if SWD is active). + * + * DBUS == GPIO-Lx + * CBUS == GPIO-Hx + */ + + +#define ICDI_JTAG_EN (1 << 7) /* ADBUS 7 (a.k.a. DBGMOD) */ +#define ICDI_DBG_ENn (1 << 6) /* ADBUS 6 */ +#define ICDI_SRST (1 << 5) /* ADBUS 5 */ + + + /* GPIOs on second channel/interface (UART) ... */ +#define ICDI_SWO_EN (1 << 4) /* BDBUS 4 */ +#define ICDI_TX_SWO (1 << 1) /* BDBUS 1 */ +#define ICDI_VCP_RX (1 << 0) /* BDBUS 0 (to stellaris UART) */ + + nTRST = 0x0; + nTRSTnOE = 0x00; + nSRST = ICDI_SRST; + nSRSTnOE = ICDI_SRST; + + low_direction |= ICDI_JTAG_EN | ICDI_DBG_ENn; + low_output |= ICDI_JTAG_EN; + low_output &= ~ICDI_DBG_ENn; + + return ftx232_dbus_write(); +} + +static int signalyzer_init(void) +{ + ftx232_dbus_init(); + + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x20; + nSRSTnOE = 0x20; + return ftx232_dbus_write(); +} + +static int axm0432_jtag_init(void) +{ + low_output = 0x08; low_direction = 0x2b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2297,13 +2729,8 @@ static int axm0432_jtag_init(void) high_output |= nSRST; } - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2312,21 +2739,62 @@ static int axm0432_jtag_init(void) return ERROR_OK; } -static int jtagkey_init(void) +static int redbee_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; + low_output = 0x08; + low_direction = 0x2b; + /* initialize low byte for jtag */ + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x08; + nTRSTnOE = 0x0; /* No output enable for TRST*/ + nSRST = 0x04; + nSRSTnOE = 0x0; /* No output enable for SRST*/ + + high_output = 0x0; + high_direction = 0x0c; + + enum reset_types jtag_reset_config = jtag_get_reset_config(); + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + { + LOG_ERROR("can't set nTRSTOE to push-pull on redbee"); + } + else + { + high_output |= nTRST; + } + + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + { + LOG_ERROR("can't set nSRST to push-pull on redbee"); + } + else + { + high_output |= nSRST; + } + + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +static int jtagkey_init(void) +{ low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2379,13 +2847,8 @@ static int jtagkey_init(void) high_output &= ~nSRST; } - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2396,19 +2859,11 @@ static int jtagkey_init(void) static int olimex_jtag_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2446,13 +2901,8 @@ static int olimex_jtag_init(void) /* turn red LED on */ high_output |= 0x08; - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2463,19 +2913,11 @@ static int olimex_jtag_init(void) static int flyswatter_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x18; low_direction = 0xfb; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE[12]=out, n[ST]srst = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2492,13 +2934,8 @@ static int flyswatter_init(void) /* turn red LED3 on, LED2 off */ high_output |= 0x08; - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2507,21 +2944,44 @@ static int flyswatter_init(void) return ERROR_OK; } -static int turtle_init(void) +static int minimodule_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; + low_output = 0x18;//check if srst should be 1 or 0 initially. (0x08) (flyswatter was 0x18) + low_direction = 0xfb;//0xfb; + /* initialize low byte for jtag */ + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + + nSRST = 0x20; + + high_output = 0x00; + high_direction = 0x05; + + /* turn red LED3 on, LED2 off */ + //high_output |= 0x08; + + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +static int turtle_init(void) +{ low_output = 0x08; low_direction = 0x5b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2532,13 +2992,8 @@ static int turtle_init(void) high_output = 0x00; high_direction = 0x0C; - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; - buf[2] = high_direction; - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2549,19 +3004,11 @@ static int turtle_init(void) static int comstick_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x08; low_direction = 0x0b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2575,13 +3022,8 @@ static int comstick_init(void) high_output = 0x03; high_direction = 0x03; - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; - buf[2] = high_direction; - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2592,19 +3034,11 @@ static int comstick_init(void) static int stm32stick_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x88; low_direction = 0x8b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2618,13 +3052,8 @@ static int stm32stick_init(void) high_output = 0x01; high_direction = 0x03; - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; - buf[2] = high_direction; - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2635,19 +3064,11 @@ static int stm32stick_init(void) static int sheevaplug_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2669,13 +3090,8 @@ static int sheevaplug_init(void) high_output |= nSRSTnOE; high_output &= ~nSRST; - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs - xRST */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2686,19 +3102,11 @@ static int sheevaplug_init(void) static int cortino_jtag_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_output = 0x08; low_direction = 0x1b; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */ - buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2712,15 +3120,119 @@ static int cortino_jtag_init(void) high_output = 0x03; high_direction = 0x03; - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; - buf[2] = high_direction; - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); + return ERROR_JTAG_INIT_FAILED; + } - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + return ERROR_OK; +} + +static int lisa_l_init(void) +{ + ftx232_dbus_init(); + + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + + high_output = 0x00; + high_direction = 0x18; + + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); + LOG_ERROR("couldn't initialize FT2232 with 'lisa_l' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ftx232_dbus_write(); +} + +static int flossjtag_init(void) +{ + ftx232_dbus_init(); + + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + + high_output = 0x00; + high_direction = 0x18; + + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'Floss-JTAG' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ftx232_dbus_write(); +} + +/* + * The reference schematic from TI for the XDS100v2 has a CPLD on which opens + * the door for a number of different configurations + * + * Known Implementations: + * http://processors.wiki.ti.com/images/9/93/TMS570LS20216_USB_STICK_Schematic.pdf + * + * http://processors.wiki.ti.com/index.php/XDS100 (rev2) + * * CLPD logic: Rising edge to enable outputs (XDS100_PWR_RST) + * * ACBUS3 to transition 0->1 (OE rising edge) + * * CPLD logic: Put the EMU0/1 pins in Hi-Z: + * * ADBUS5/GPIOL1 = EMU_EN = 1 + * * ADBUS6/GPIOL2 = EMU0 = 0 + * * ACBUS4/SPARE0 = EMU1 = 0 + * * CPLD logic: Disable loopback + * * ACBUS6/SPARE2 = LOOPBACK = 0 + */ +#define XDS100_nEMU_EN (1<<5) +#define XDS100_nEMU0 (1<<6) + +#define XDS100_PWR_RST (1<<3) +#define XDS100_nEMU1 (1<<4) +#define XDS100_LOOPBACK (1<<6) +static int xds100v2_init(void) +{ + /* These are in the lower byte */ + nTRST = 0x10; + nTRSTnOE = 0x10; + + /* These aren't actually used on 14 pin connectors */ + /* These are in the upper byte */ + nSRST = 0x01; + nSRSTnOE = 0x01; + + low_output = 0x08 | nTRST | XDS100_nEMU_EN; + low_direction = 0x0b | nTRSTnOE | XDS100_nEMU_EN | XDS100_nEMU0; + + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'xds100v2' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + high_output = 0; + high_direction = nSRSTnOE | XDS100_LOOPBACK | XDS100_PWR_RST | XDS100_nEMU1; + + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) + { + LOG_ERROR("couldn't put CPLD in to reset with 'xds100v2' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + high_output |= XDS100_PWR_RST; + + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) + { + LOG_ERROR("couldn't bring CPLD out of reset with 'xds100v2' layout"); return ERROR_JTAG_INIT_FAILED; } @@ -2732,16 +3244,7 @@ static void olimex_jtag_blink(void) /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 * ACBUS3 is bit 3 of the GPIOH port */ - if (high_output & 0x08) - { - /* set port pin high */ - high_output &= 0x07; - } - else - { - /* set port pin low */ - high_output |= 0x08; - } + high_output ^= 0x08; buffer_write(0x82); buffer_write(high_output); @@ -2779,6 +3282,44 @@ static void turtle_jtag_blink(void) buffer_write(high_direction); } +static void lisa_l_blink(void) +{ + /* + * Lisa/L has two LEDs connected to BCBUS3 and BCBUS4 + */ + if (high_output & 0x10) + { + high_output = 0x08; + } + else + { + high_output = 0x10; + } + + buffer_write(0x82); + buffer_write(high_output); + buffer_write(high_direction); +} + +static void flossjtag_blink(void) +{ + /* + * Floss-JTAG has two LEDs connected to ACBUS3 and ACBUS4 + */ + if (high_output & 0x10) + { + high_output = 0x08; + } + else + { + high_output = 0x10; + } + + buffer_write(0x82); + buffer_write(high_output); + buffer_write(high_direction); +} + static int ft2232_quit(void) { #if BUILD_FT2232_FTD2XX == 1 @@ -2847,13 +3388,28 @@ COMMAND_HANDLER(ft2232_handle_serial_command) COMMAND_HANDLER(ft2232_handle_layout_command) { - if (CMD_ARGC == 0) - return ERROR_OK; + if (CMD_ARGC != 1) { + LOG_ERROR("Need exactly one argument to ft2232_layout"); + return ERROR_FAIL; + } - ft2232_layout = malloc(strlen(CMD_ARGV[0]) + 1); - strcpy(ft2232_layout, CMD_ARGV[0]); + if (layout) { + LOG_ERROR("already specified ft2232_layout %s", + layout->name); + return (strcmp(layout->name, CMD_ARGV[0]) != 0) + ? ERROR_FAIL + : ERROR_OK; + } - return ERROR_OK; + for (const struct ft2232_layout *l = ft2232_layouts; l->name; l++) { + if (strcmp(l->name, CMD_ARGV[0]) == 0) { + layout = l; + return ERROR_OK; + } + } + + LOG_ERROR("No FT2232 layout '%s' found", CMD_ARGV[0]); + return ERROR_FAIL; } COMMAND_HANDLER(ft2232_handle_vid_pid_command) @@ -2972,9 +3528,6 @@ static int ft2232_stableclocks(int num_cycles, struct jtag_command* cmd) * ADBUS7 - GND */ static int icebear_jtag_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; - low_direction = 0x0b; /* output: TCK TDI TMS; input: TDO */ low_output = 0x08; /* high: TMS; low: TCK TDI */ nTRST = 0x10; @@ -2993,12 +3546,7 @@ static int icebear_jtag_init(void) { low_output |= nSRST; /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; - buf[2] = low_direction; - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) { + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)"); return ERROR_JTAG_INIT_FAILED; } @@ -3006,14 +3554,8 @@ static int icebear_jtag_init(void) { high_output = 0x0; high_direction = 0x00; - - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) { + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)"); return ERROR_JTAG_INIT_FAILED; } @@ -3131,7 +3673,8 @@ static int signalyzer_h_led_set(unsigned char channel, unsigned char led, if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, ((uint32_t)(channel << 8) | led))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3139,7 +3682,8 @@ static int signalyzer_h_led_set(unsigned char channel, unsigned char led, (SIGNALYZER_DATA_BUFFER_ADDR + 1), ((uint32_t)(on_time << 8) | off_time))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3147,14 +3691,16 @@ static int signalyzer_h_led_set(unsigned char channel, unsigned char led, (SIGNALYZER_DATA_BUFFER_ADDR + 2), ((uint32_t)cycles))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_LED_SET)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3210,8 +3756,6 @@ static int signalyzer_h_init(void) char *end_of_desc; uint16_t read_buf[12] = { 0 }; - uint8_t buf[3]; - uint32_t bytes_written; /* turn on center green led */ signalyzer_h_led_set(SIGNALYZER_CHAN_C, SIGNALYZER_LED_GREEN, @@ -3245,7 +3789,8 @@ static int signalyzer_h_init(void) if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_VERSION)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3255,8 +3800,8 @@ static int signalyzer_h_init(void) (SIGNALYZER_DATA_BUFFER_ADDR + i), &read_buf[i])) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_read returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } } @@ -3269,21 +3814,24 @@ static int signalyzer_h_init(void) if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0404)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3291,28 +3839,32 @@ static int signalyzer_h_init(void) if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, ((uint32_t)(signalyzer_h_side << 8) | 0x01))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write( (SIGNALYZER_DATA_BUFFER_ADDR + 1), 0xA000)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write( (SIGNALYZER_DATA_BUFFER_ADDR + 2), 0x0008)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_I2C)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3321,7 +3873,8 @@ static int signalyzer_h_init(void) if ((status = signalyzer_h_ctrl_read(SIGNALYZER_COMMAND_ADDR, &read_buf[0])) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %lu", status); + LOG_ERROR("signalyzer_h_ctrl_read returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3335,8 +3888,8 @@ static int signalyzer_h_init(void) (SIGNALYZER_DATA_BUFFER_ADDR + i), &read_buf[i])) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_read returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } } @@ -3400,16 +3953,16 @@ static int signalyzer_h_init(void) ((uint32_t)(signalyzer_h_side << 8) | 0x01))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_POWERCONTROL_SET)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3418,8 +3971,8 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3427,16 +3980,16 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3445,8 +3998,8 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3454,8 +4007,8 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x4040)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3463,8 +4016,8 @@ static int signalyzer_h_init(void) SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } #endif @@ -3535,8 +4088,8 @@ static int signalyzer_h_init(void) ((uint32_t)(signalyzer_h_side << 8) | 0x01))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3544,8 +4097,8 @@ static int signalyzer_h_init(void) SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_POWERCONTROL_SET)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3556,8 +4109,8 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3565,8 +4118,8 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0060)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3574,8 +4127,8 @@ static int signalyzer_h_init(void) SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3586,8 +4139,8 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR, (uint32_t)(signalyzer_h_side << 8))) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3595,8 +4148,8 @@ static int signalyzer_h_init(void) SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } @@ -3604,8 +4157,8 @@ static int signalyzer_h_init(void) SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE)) != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", - status); + LOG_ERROR("signalyzer_h_ctrl_write returned: %s", + ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } #endif @@ -3656,12 +4209,7 @@ static int signalyzer_h_init(void) } /* initialize low byte of controller for jtag operation */ - buf[0] = 0x80; - buf[1] = low_output; - buf[2] = low_direction; - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3671,12 +4219,7 @@ static int signalyzer_h_init(void) if (ftdi_device == FT_DEVICE_2232H) { /* initialize high byte of controller for jtag operation */ - buf[0] = 0x82; - buf[1] = high_output; - buf[2] = high_direction; - - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3686,12 +4229,7 @@ static int signalyzer_h_init(void) if (ftdi_device == TYPE_2232H) { /* initialize high byte of controller for jtag operation */ - buf[0] = 0x82; - buf[1] = high_output; - buf[2] = high_direction; - - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3862,20 +4400,13 @@ static void signalyzer_h_blink(void) *******************************************************************/ static int ktlink_init(void) { - uint8_t buf[3]; - uint32_t bytes_written; uint8_t swd_en = 0x20; //0x20 SWD disable, 0x00 SWD enable (ADBUS5) low_output = 0x08 | swd_en; // value; TMS=1,TCK=0,TDI=0,SWD=swd_en low_direction = 0x3B; // out=1; TCK/TDI/TMS=out,TDO=in,SWD=out,RTCK=in,SRSTIN=in - // initialize low port - buf[0] = 0x80; // command "set data bits low byte" - buf[1] = low_output; - buf[2] = low_direction; - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize low byte for jtag */ + if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; @@ -3907,13 +4438,8 @@ static int ktlink_init(void) high_output &= ~nSRST; } - // initialize high port - buf[0] = 0x82; // command "set data bits high byte" - buf[1] = high_output; // value - buf[2] = high_direction; - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + /* initialize high byte for jtag */ + if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; @@ -3959,10 +4485,7 @@ static void ktlink_reset(int trst, int srst) static void ktlink_blink(void) { /* LED connected to ACBUS7 */ - if (high_output & 0x80) - high_output &= 0x7F; - else - high_output |= 0x80; + high_output ^= 0x80; buffer_write(0x82); // command "set data bits high byte" buffer_write(high_output); @@ -3975,14 +4498,14 @@ static const struct command_registration ft2232_command_handlers[] = { .handler = &ft2232_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the USB device description of the FTDI FT2232 device", - .usage = "", + .usage = "description_string", }, { .name = "ft2232_serial", .handler = &ft2232_handle_serial_command, .mode = COMMAND_CONFIG, .help = "set the serial number of the FTDI FT2232 device", - .usage = "", + .usage = "serial_string", }, { .name = "ft2232_layout", @@ -3990,32 +4513,35 @@ static const struct command_registration ft2232_command_handlers[] = { .mode = COMMAND_CONFIG, .help = "set the layout of the FT2232 GPIO signals used " "to control output-enables and reset signals", - .usage = "", + .usage = "layout_name", }, { .name = "ft2232_vid_pid", .handler = &ft2232_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor ID and product ID of the FTDI FT2232 device", - .usage = " [...]", + .usage = "(vid pid)* ", }, { .name = "ft2232_latency", .handler = &ft2232_handle_latency_command, .mode = COMMAND_CONFIG, .help = "set the FT2232 latency timer to a new value", - .usage = " [...]", + .usage = "value", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface ft2232_interface = { - .name = "ft2232", - .commands = ft2232_command_handlers, - .init = &ft2232_init, - .quit = &ft2232_quit, - .speed = &ft2232_speed, - .speed_div = &ft2232_speed_div, - .khz = &ft2232_khz, - .execute_queue = &ft2232_execute_queue, - }; + .name = "ft2232", + .supported = DEBUG_CAP_TMS_SEQ, + .commands = ft2232_command_handlers, + .transports = jtag_only, + + .init = ft2232_init, + .quit = ft2232_quit, + .speed = ft2232_speed, + .speed_div = ft2232_speed_div, + .khz = ft2232_khz, + .execute_queue = ft2232_execute_queue, +};