X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fft2232.c;h=c8a98d2d296d038c1f4555d5ec4727bef0183fd8;hp=38195c787294003be40e9825e22df2760a932295;hb=fa4680548150b51083239e3a5181a2ecd86a0da9;hpb=73c1cff7c242566d995e7b77de0fcec9fe50a6bb diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c index 38195c7872..c8a98d2d29 100644 --- a/src/jtag/drivers/ft2232.c +++ b/src/jtag/drivers/ft2232.c @@ -32,12 +32,24 @@ * 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. Since JTAG uses - * only one of the two ports on these devices, on integrated boards the - * second port often serves as a USB-to-serial adapter for the target's - * console UART even when the JTAG port is not in use. (Systems which - * support ARM's SWD in addition to JTAG, or instead of it, may use that - * second port for reading SWV trace data.) + * 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. @@ -69,6 +81,7 @@ /* project specific includes */ #include +#include #include #if IS_CYGWIN == 1 @@ -141,7 +154,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; @@ -161,6 +173,8 @@ struct ft2232_layout { /* 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 turtle_init(void); @@ -170,12 +184,15 @@ 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); /* 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); @@ -195,12 +212,18 @@ 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[] = { { .name = "usbjtag", .init = usbjtag_init, - .reset = usbjtag_reset, + .reset = ftx23_reset, }, { .name = "jtagkey", .init = jtagkey_init, @@ -215,16 +238,16 @@ static const struct ft2232_layout ft2232_layouts[] = .reset = jtagkey_reset, }, { .name = "signalyzer", - .init = usbjtag_init, - .reset = usbjtag_reset, + .init = signalyzer_init, + .reset = ftx23_reset, }, { .name = "evb_lm3s811", - .init = usbjtag_init, - .reset = usbjtag_reset, + .init = lm3s811_jtag_init, + .reset = ftx23_reset, }, { .name = "luminary_icdi", - .init = usbjtag_init, - .reset = usbjtag_reset, + .init = icdi_jtag_init, + .reset = ftx23_reset, }, { .name = "olimex-jtag", .init = olimex_jtag_init, @@ -284,15 +307,40 @@ static const struct ft2232_layout ft2232_layouts[] = .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 = 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 @@ -455,7 +503,6 @@ static int ft2232_write(uint8_t* buf, int size, uint32_t* bytes_written) else { *bytes_written = dw_bytes_written; - return ERROR_OK; } #elif BUILD_FT2232_LIBFTDI == 1 int retval; @@ -468,9 +515,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) @@ -544,8 +597,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"); @@ -564,8 +618,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"); @@ -602,7 +656,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; @@ -712,7 +766,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); @@ -1327,7 +1381,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) @@ -1952,7 +2007,7 @@ static int ft2232_execute_command(struct jtag_command *cmd) { 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; @@ -2020,7 +2075,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 */ @@ -2187,8 +2247,13 @@ static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int* try_mo { 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; @@ -2268,8 +2333,6 @@ 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) { @@ -2280,29 +2343,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 @@ -2321,7 +2367,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, cur_layout->channel); + more, &try_more, layout->channel); #endif if (retval >= 0) break; @@ -2349,10 +2395,14 @@ static int ft2232_init(void) return ERROR_JTAG_INIT_FAILED; } - ft2232_speed(jtag_get_speed()); + int jtag_speed_var; + retval = jtag_get_speed(&jtag_speed_var); + if (retval != ERROR_OK) + return retval; + ft2232_speed(jtag_speed_var); 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; @@ -2367,59 +2417,23 @@ 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) - { - /* 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; - } - else if (strcmp(ft2232_layout, "luminary_icdi") == 0) - { - /* Most Luminary eval boards support SWO trace output, - * and should use this "luminary_icdi" layout. - */ - 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) +{ + uint8_t buf[3]; + uint32_t bytes_written; enum reset_types jtag_reset_config = jtag_get_reset_config(); if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) @@ -2450,15 +2464,104 @@ static int usbjtag_init(void) 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_write(buf, sizeof(buf), &bytes_written) != 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 usbjtag_init(void) +{ + /* + * NOTE: This is now _specific_ to the "usbjtag" layout. + * Don't try cram any more layouts into this. + */ + ftx232_dbus_init(); + + 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) { uint8_t buf[3]; @@ -2473,7 +2576,7 @@ static int axm0432_jtag_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2520,7 +2623,7 @@ static int axm0432_jtag_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2546,8 +2649,7 @@ static int redbee_init(void) buf[1] = low_output; 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2586,8 +2688,7 @@ static int redbee_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2610,7 +2711,7 @@ static int jtagkey_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2669,7 +2770,7 @@ static int jtagkey_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2692,7 +2793,7 @@ static int olimex_jtag_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2736,7 +2837,7 @@ static int olimex_jtag_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2759,7 +2860,7 @@ static int flyswatter_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2782,7 +2883,7 @@ static int flyswatter_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2805,7 +2906,7 @@ static int turtle_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2822,7 +2923,7 @@ static int turtle_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2845,7 +2946,7 @@ static int comstick_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2865,7 +2966,7 @@ static int comstick_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2888,7 +2989,7 @@ static int stm32stick_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2908,7 +3009,7 @@ static int stm32stick_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2931,7 +3032,7 @@ static int sheevaplug_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2959,7 +3060,7 @@ static int sheevaplug_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); return ERROR_JTAG_INIT_FAILED; @@ -2982,7 +3083,7 @@ static int cortino_jtag_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); return ERROR_JTAG_INIT_FAILED; @@ -3002,7 +3103,7 @@ static int cortino_jtag_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); return ERROR_JTAG_INIT_FAILED; @@ -3011,6 +3112,66 @@ static int cortino_jtag_init(void) return ERROR_OK; } +static int lisa_l_init(void) +{ + uint8_t buf[3]; + uint32_t bytes_written; + + ftx232_dbus_init(); + + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + + high_output = 0x00; + high_direction = 0x18; + + /* 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, sizeof(buf), &bytes_written) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'lisa_l' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ftx232_dbus_write(); +} + +static int flossjtag_init(void) +{ + uint8_t buf[3]; + uint32_t bytes_written; + + ftx232_dbus_init(); + + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + + high_output = 0x00; + high_direction = 0x18; + + /* 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, sizeof(buf), &bytes_written) != ERROR_OK) + { + LOG_ERROR("couldn't initialize FT2232 with 'Floss-JTAG' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ftx232_dbus_write(); +} + static void olimex_jtag_blink(void) { /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 @@ -3063,6 +3224,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 @@ -3131,13 +3330,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) @@ -3282,7 +3496,7 @@ static int icebear_jtag_init(void) { 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)"); return ERROR_JTAG_INIT_FAILED; } @@ -3297,7 +3511,7 @@ static int icebear_jtag_init(void) { 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)) { + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)"); return ERROR_JTAG_INIT_FAILED; } @@ -3944,8 +4158,7 @@ static int signalyzer_h_init(void) buf[1] = low_output; buf[2] = low_direction; - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3959,8 +4172,7 @@ static int signalyzer_h_init(void) buf[1] = high_output; buf[2] = high_direction; - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -3974,8 +4186,7 @@ static int signalyzer_h_init(void) buf[1] = high_output; buf[2] = high_direction; - if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) - || (bytes_written != 3)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize Signalyzer-H layout"); return ERROR_JTAG_INIT_FAILED; @@ -4159,7 +4370,7 @@ static int ktlink_init(void) 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_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; @@ -4197,7 +4408,7 @@ static int ktlink_init(void) 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)) + if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); return ERROR_JTAG_INIT_FAILED; @@ -4297,6 +4508,7 @@ struct jtag_interface ft2232_interface = { .name = "ft2232", .supported = DEBUG_CAP_TMS_SEQ, .commands = ft2232_command_handlers, + .transports = jtag_only, .init = ft2232_init, .quit = ft2232_quit,