X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fft2232.c;h=1ac61abb705b0890f7c8ec36786abf3d83c764d3;hp=7d2fac08900a0f4123d107fb7535d89dce7fe6f5;hb=96261e827782235709fcdfb2c1bbb93fedc977be;hpb=5fcd1d704cea078f6651e8e928ce7ff67b283882 diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index 7d2fac0890..1ac61abb70 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -70,13 +70,20 @@ int ft2232_init(void); int ft2232_quit(void); int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); char *ft2232_device_desc = NULL; +char *ft2232_serial = NULL; char *ft2232_layout = NULL; -u16 ft2232_vid = 0x0403; -u16 ft2232_pid = 0x6010; +unsigned char ft2232_latency = 2; + +#define MAX_USB_IDS 8 +/* vid = pid = 0 marks the end of the list */ +static u16 ft2232_vid[MAX_USB_IDS+1] = { 0x0403, 0 }; +static u16 ft2232_pid[MAX_USB_IDS+1] = { 0x6010, 0 }; typedef struct ft2232_layout_s { @@ -90,22 +97,37 @@ typedef struct ft2232_layout_s int usbjtag_init(void); int jtagkey_init(void); int olimex_jtag_init(void); +int flyswatter_init(void); +int turtle_init(void); +int comstick_init(void); +int stm32stick_init(void); /* reset procedures for supported layouts */ void usbjtag_reset(int trst, int srst); void jtagkey_reset(int trst, int srst); void olimex_jtag_reset(int trst, int srst); +void flyswatter_reset(int trst, int srst); +void turtle_reset(int trst, int srst); +void comstick_reset(int trst, int srst); +void stm32stick_reset(int trst, int srst); /* blink procedures for layouts that support a blinking led */ void olimex_jtag_blink(void); +void turtle_jtag_blink(void); ft2232_layout_t 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}, {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink}, + {"flyswatter", flyswatter_init, flyswatter_reset, NULL}, + {"turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink}, + {"comstick", comstick_init, comstick_reset, NULL}, + {"stm32stick", stm32stick_init, stm32stick_reset, NULL}, {NULL, NULL, NULL}, }; @@ -138,8 +160,6 @@ jtag_interface_t ft2232_interface = .execute_queue = ft2232_execute_queue, - .support_pathmove = 1, - .speed = ft2232_speed, .register_commands = ft2232_register_commands, .init = ft2232_init, @@ -154,7 +174,7 @@ int ft2232_write(u8 *buf, int size, u32* bytes_written) if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK) { *bytes_written = dw_bytes_written; - ERROR("FT_Write returned: %i", status); + ERROR("FT_Write returned: %lu", status); return ERROR_JTAG_DEVICE_ERROR; } else @@ -183,15 +203,20 @@ int ft2232_read(u8* buf, int size, u32* bytes_read) #if BUILD_FT2232_FTD2XX == 1 DWORD dw_bytes_read; FT_STATUS status; - if ((status = FT_Read(ftdih, buf, size, &dw_bytes_read)) != FT_OK) + int timeout = 5; + *bytes_read = 0; + + while ((*bytes_read < size) && timeout--) { - *bytes_read = dw_bytes_read; - ERROR("FT_Read returned: %i", status); - return ERROR_JTAG_DEVICE_ERROR; + if ((status = FT_Read(ftdih, buf + *bytes_read, size - + *bytes_read, &dw_bytes_read)) != FT_OK) + { + *bytes_read = 0; + ERROR("FT_Read returned: %lu", status); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_read += dw_bytes_read; } - *bytes_read = dw_bytes_read; - return ERROR_OK; - #elif BUILD_FT2232_LIBFTDI == 1 int retval; int timeout = 100; @@ -207,8 +232,15 @@ int ft2232_read(u8* buf, int size, u32* bytes_read) } *bytes_read += retval; } - return ERROR_OK; #endif + + if (*bytes_read < size) + { + ERROR("couldn't read the requested number of bytes from FT2232 device (%i < %i)", *bytes_read, size); + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; } int ft2232_speed(int speed) @@ -218,7 +250,7 @@ int ft2232_speed(int speed) u32 bytes_written; buf[0] = 0x86; /* command "set divisor" */ - buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=1.5MHz, ...*/ + buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=2.0MHz, ...*/ buf[2] = (speed >> 8) & 0xff; /* valueH */ DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); @@ -227,6 +259,8 @@ int ft2232_speed(int speed) ERROR("couldn't set FT2232 TCK speed"); return retval; } + + jtag_speed = speed; return ERROR_OK; } @@ -235,14 +269,18 @@ int ft2232_register_commands(struct command_context_s *cmd_ctx) { register_command(cmd_ctx, NULL, "ft2232_device_desc", ft2232_handle_device_desc_command, COMMAND_CONFIG, NULL); + register_command(cmd_ctx, NULL, "ft2232_serial", ft2232_handle_serial_command, + COMMAND_CONFIG, NULL); register_command(cmd_ctx, NULL, "ft2232_layout", ft2232_handle_layout_command, COMMAND_CONFIG, NULL); register_command(cmd_ctx, NULL, "ft2232_vid_pid", ft2232_handle_vid_pid_command, COMMAND_CONFIG, NULL); + register_command(cmd_ctx, NULL, "ft2232_latency", ft2232_handle_latency_command, + COMMAND_CONFIG, NULL); return ERROR_OK; } -void ft2232_end_state(state) +void ft2232_end_state(enum tap_state state) { if (tap_move_map[state] != -1) end_state = state; @@ -375,7 +413,12 @@ int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last) ft2232_expect_read = 0; ft2232_read_pointer = 0; - + + /* return ERROR_OK, unless a jtag_read_buffer returns a failed check + * that wasn't handled by a caller-provided error handler + */ + retval = ERROR_OK; + cmd = first; while (cmd != last) { @@ -388,7 +431,8 @@ int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last) scan_size = jtag_scan_size(cmd->cmd.scan); buffer = calloc(CEIL(scan_size, 8), 1); ft2232_read_scan(type, buffer, scan_size); - jtag_read_buffer(buffer, cmd->cmd.scan); + if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; free(buffer); } break; @@ -400,7 +444,7 @@ int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last) ft2232_buffer_size = 0; - return ERROR_OK; + return retval; } void ft2232_add_pathmove(pathmove_command_t *cmd) @@ -415,12 +459,14 @@ void ft2232_add_pathmove(pathmove_command_t *cmd) tms_byte = 0x0; int bit_count = 0; + int num_states_batch = num_states > 7 ? 7 : num_states; + /* command "Clock Data to TMS/CS Pin (no Read)" */ BUFFER_ADD = 0x4b; /* number of states remaining */ - BUFFER_ADD = (num_states % 7) - 1; + BUFFER_ADD = num_states_batch - 1; - while (num_states % 7) + while (num_states_batch--) { if (tap_transitions[cur_state].low == cmd->path[state_count]) buf_set_u32(&tms_byte, bit_count++, 1, 0x0); @@ -450,7 +496,7 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size int cur_byte = 0; int last_bit; - if ((!ir_scan && (cur_state != TAP_SD)) || (ir_scan && (cur_state != TAP_SI))) + if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI)))) { /* command "Clock Data to TMS/CS Pin (no Read)" */ BUFFER_ADD = 0x4b; @@ -467,48 +513,231 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD); cur_state = TAP_SD; } - //DEBUG("added TMS scan (no read)"); + /* DEBUG("added TMS scan (no read)"); */ } /* add command for complete bytes */ - if (num_bytes > 1) + while (num_bytes > 1) { + int thisrun_bytes; if (type == SCAN_IO) { /* Clock Data Bytes In and Out LSB First */ BUFFER_ADD = 0x39; - //DEBUG("added TDI bytes (io %i)", num_bytes); + /* DEBUG("added TDI bytes (io %i)", num_bytes); */ } else if (type == SCAN_OUT) { /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ BUFFER_ADD = 0x19; - //DEBUG("added TDI bytes (o)"); + /* DEBUG("added TDI bytes (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ BUFFER_ADD = 0x28; - //DEBUG("added TDI bytes (i %i)", num_bytes); + /* DEBUG("added TDI bytes (i %i)", num_bytes); */ + } + thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); + num_bytes -= thisrun_bytes; + BUFFER_ADD = (thisrun_bytes - 1) & 0xff; + BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff; + if (type != SCAN_IN) + { + /* add complete bytes */ + while(thisrun_bytes-- > 0) + { + BUFFER_ADD = buffer[cur_byte]; + cur_byte++; + bits_left -= 8; + } + } + else /* (type == SCAN_IN) */ + { + bits_left -= 8 * (thisrun_bytes); } - BUFFER_ADD = (num_bytes-2) & 0xff; - BUFFER_ADD = ((num_bytes-2) >> 8) & 0xff; } + + /* the most signifcant bit is scanned during TAP movement */ if (type != SCAN_IN) + last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; + else + last_bit = 0; + + /* process remaining bits but the last one */ + if (bits_left > 1) { - /* add complete bytes */ - while(num_bytes-- > 1) + if (type == SCAN_IO) + { + /* Clock Data Bits In and Out LSB First */ + BUFFER_ADD = 0x3b; + /* DEBUG("added TDI bits (io) %i", bits_left - 1); */ + } + else if (type == SCAN_OUT) + { + /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x1b; + /* DEBUG("added TDI bits (o)"); */ + } + else if (type == SCAN_IN) { + /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x2a; + /* DEBUG("added TDI bits (i %i)", bits_left - 1); */ + } + BUFFER_ADD = bits_left - 2; + if (type != SCAN_IN) BUFFER_ADD = buffer[cur_byte]; - cur_byte++; - bits_left -= 8; + } + + if ((ir_scan && (end_state == TAP_SI)) || + (!ir_scan && (end_state == TAP_SD))) + { + if (type == SCAN_IO) + { + /* Clock Data Bits In and Out LSB First */ + BUFFER_ADD = 0x3b; + /* DEBUG("added TDI bits (io) %i", bits_left - 1); */ + } + else if (type == SCAN_OUT) + { + /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x1b; + /* DEBUG("added TDI bits (o)"); */ + } + else if (type == SCAN_IN) + { + /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x2a; + /* DEBUG("added TDI bits (i %i)", bits_left - 1); */ + } + BUFFER_ADD = 0x0; + BUFFER_ADD = last_bit; + } + else + { + /* move from Shift-IR/DR to end state */ + if (type != SCAN_OUT) + { + /* Clock Data to TMS/CS Pin with Read */ + BUFFER_ADD = 0x6b; + /* DEBUG("added TMS scan (read)"); */ + } + else + { + /* Clock Data to TMS/CS Pin (no Read) */ + BUFFER_ADD = 0x4b; + /* DEBUG("added TMS scan (no read)"); */ } + BUFFER_ADD = 0x6; + BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7); + cur_state = end_state; + } +} + +int ft2232_large_scan(scan_command_t *cmd, enum scan_type type, u8 *buffer, int scan_size) +{ + int num_bytes = (scan_size + 7) / 8; + int bits_left = scan_size; + int cur_byte = 0; + int last_bit; + u8 *receive_buffer = malloc(CEIL(scan_size, 8)); + u8 *receive_pointer = receive_buffer; + u32 bytes_written; + u32 bytes_read; + int retval; + int thisrun_read = 0; + + if (cmd->ir_scan) + { + ERROR("BUG: large IR scans are not supported"); + exit(-1); + } + + if (cur_state != TAP_SD) + { + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; + /* scan 7 bit */ + BUFFER_ADD = 0x6; + /* TMS data bits */ + BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD); + cur_state = TAP_SD; } - if (type == SCAN_IN) + + if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) { - bits_left -= 8 * (num_bytes - 1); + ERROR("couldn't write MPSSE commands to FT2232"); + exit(-1); } + DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written); + ft2232_buffer_size = 0; + + /* add command for complete bytes */ + while (num_bytes > 1) + { + int thisrun_bytes; + + if (type == SCAN_IO) + { + /* Clock Data Bytes In and Out LSB First */ + BUFFER_ADD = 0x39; + /* DEBUG("added TDI bytes (io %i)", num_bytes); */ + } + else if (type == SCAN_OUT) + { + /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x19; + /* DEBUG("added TDI bytes (o)"); */ + } + else if (type == SCAN_IN) + { + /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x28; + /* DEBUG("added TDI bytes (i %i)", num_bytes); */ + } + thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); + thisrun_read = thisrun_bytes; + num_bytes -= thisrun_bytes; + BUFFER_ADD = (thisrun_bytes - 1) & 0xff; + BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff; + if (type != SCAN_IN) + { + /* add complete bytes */ + while(thisrun_bytes-- > 0) + { + BUFFER_ADD = buffer[cur_byte]; + cur_byte++; + bits_left -= 8; + } + } + else /* (type == SCAN_IN) */ + { + bits_left -= 8 * (thisrun_bytes); + } + if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) + { + ERROR("couldn't write MPSSE commands to FT2232"); + exit(-1); + } + DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written); + ft2232_buffer_size = 0; + + if (type != SCAN_OUT) + { + if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK) + { + ERROR("couldn't read from FT2232"); + exit(-1); + } + DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read); + receive_pointer += bytes_read; + } + } + + thisrun_read = 0; + /* the most signifcant bit is scanned during TAP movement */ if (type != SCAN_IN) last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; @@ -522,47 +751,100 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size { /* Clock Data Bits In and Out LSB First */ BUFFER_ADD = 0x3b; - //DEBUG("added TDI bits (io) %i", bits_left - 1); + /* DEBUG("added TDI bits (io) %i", bits_left - 1); */ } else if (type == SCAN_OUT) { /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ BUFFER_ADD = 0x1b; - //DEBUG("added TDI bits (o)"); + /* DEBUG("added TDI bits (o)"); */ } else if (type == SCAN_IN) { /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ BUFFER_ADD = 0x2a; - //DEBUG("added TDI bits (i %i)", bits_left - 1); + /* DEBUG("added TDI bits (i %i)", bits_left - 1); */ } BUFFER_ADD = bits_left - 2; if (type != SCAN_IN) BUFFER_ADD = buffer[cur_byte]; + + if (type != SCAN_OUT) + thisrun_read += 2; } - /* move from Shift-IR/DR to end state */ - if (type != SCAN_OUT) + if (end_state == TAP_SD) { - /* Clock Data to TMS/CS Pin with Read */ - BUFFER_ADD = 0x6b; - //DEBUG("added TMS scan (read)"); + if (type == SCAN_IO) + { + /* Clock Data Bits In and Out LSB First */ + BUFFER_ADD = 0x3b; + /* DEBUG("added TDI bits (io) %i", bits_left - 1); */ + } + else if (type == SCAN_OUT) + { + /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x1b; + /* DEBUG("added TDI bits (o)"); */ + } + else if (type == SCAN_IN) + { + /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x2a; + /* DEBUG("added TDI bits (i %i)", bits_left - 1); */ + } + BUFFER_ADD = 0x0; + BUFFER_ADD = last_bit; } else { - /* Clock Data to TMS/CS Pin (no Read) */ - BUFFER_ADD = 0x4b; - //DEBUG("added TMS scan (no read)"); + /* move from Shift-IR/DR to end state */ + if (type != SCAN_OUT) + { + /* Clock Data to TMS/CS Pin with Read */ + BUFFER_ADD = 0x6b; + /* DEBUG("added TMS scan (read)"); */ + } + else + { + /* Clock Data to TMS/CS Pin (no Read) */ + BUFFER_ADD = 0x4b; + /* DEBUG("added TMS scan (no read)"); */ + } + BUFFER_ADD = 0x6; + BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7); + cur_state = end_state; } - BUFFER_ADD = 0x6; - BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7); - cur_state = end_state; - + + if (type != SCAN_OUT) + thisrun_read += 1; + + if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) + { + ERROR("couldn't write MPSSE commands to FT2232"); + exit(-1); + } + DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written); + ft2232_buffer_size = 0; + + if (type != SCAN_OUT) + { + if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK) + { + ERROR("couldn't read from FT2232"); + exit(-1); + } + DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read); + receive_pointer += bytes_read; + } + + return ERROR_OK; } int ft2232_predict_scan_out(int scan_size, enum scan_type type) { int predicted_size = 3; + int num_bytes = (scan_size - 1) / 8; if (cur_state != TAP_SD) predicted_size += 3; @@ -570,14 +852,14 @@ int ft2232_predict_scan_out(int scan_size, enum scan_type type) if (type == SCAN_IN) /* only from device to host */ { /* complete bytes */ - predicted_size += (CEIL(scan_size, 8) > 1) ? 3 : 0; + predicted_size += (CEIL(num_bytes, 65536)) * 3; /* remaining bits - 1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 2 : 0; } else /* host to device, or bidirectional */ { /* complete bytes */ - predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) + 3 - 1) : 0; + predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3; /* remaining bits -1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 3 : 0; } @@ -599,7 +881,7 @@ int ft2232_predict_scan_in(int scan_size, enum scan_type type) predicted_size += 1; } - //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); + /* DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); */ return predicted_size; } @@ -718,48 +1000,164 @@ void olimex_jtag_reset(int trst, int srst) DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); } -int ft2232_execute_queue() +void flyswatter_reset(int trst, int srst) { - jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ - jtag_command_t *first_unsent = cmd; /* next command that has to be sent */ - u8 *buffer; - int scan_size; /* size of IR or DR scan */ - enum scan_type type; - int i; - int predicted_size = 0; - int require_send = 0; + if (trst == 1) + { + cur_state = TAP_TLR; + low_output &= ~nTRST; + } + else if (trst == 0) + { + low_output |= nTRST; + } - ft2232_buffer_size = 0; - ft2232_expect_read = 0; - - /* blink, if the current layout has that feature */ - if (layout->blink) - layout->blink(); + if (srst == 1) + { + low_output |= nSRST; + } + else if (srst == 0) + { + low_output &= ~nSRST; + } - while (cmd) + /* command "set data bits low byte" */ + BUFFER_ADD = 0x80; + BUFFER_ADD = low_output; + BUFFER_ADD = low_direction; + DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); +} + +void turtle_reset(int trst, int srst) +{ + trst = trst; + + if (srst == 1) { - switch(cmd->type) - { - case JTAG_END_STATE: - if (cmd->cmd.end_state->end_state != -1) - ft2232_end_state(cmd->cmd.end_state->end_state); - break; - case JTAG_RESET: - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) - { - ft2232_send_and_recv(first_unsent, cmd); - require_send = 0; - first_unsent = cmd; - } + low_output |= nSRST; + } + else if (srst == 0) + { + low_output &= ~nSRST; + } + + /* command "set data bits low byte" */ + BUFFER_ADD = 0x80; + BUFFER_ADD = low_output; + BUFFER_ADD = low_direction; + DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction); +} - layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - require_send = 1; - -#ifdef _DEBUG_JTAG_IO_ - DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); -#endif +void comstick_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + 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 high byte" */ + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; + DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); +} + +void stm32stick_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + high_output &= ~nTRST; + } + else if (trst == 0) + { + high_output |= nTRST; + } + + if (srst == 1) + { + low_output &= ~nSRST; + } + else if (srst == 0) + { + low_output |= nSRST; + } + + /* command "set data bits low byte" */ + BUFFER_ADD = 0x80; + BUFFER_ADD = low_output; + BUFFER_ADD = low_direction; + + /* command "set data bits high byte" */ + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; + DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); +} + +int ft2232_execute_queue() +{ + jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ + jtag_command_t *first_unsent = cmd; /* next command that has to be sent */ + u8 *buffer; + int scan_size; /* size of IR or DR scan */ + enum scan_type type; + int i; + int predicted_size = 0; + int require_send = 0; + int retval; + + /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check + * that wasn't handled by a caller-provided error handler + */ + retval = ERROR_OK; + + ft2232_buffer_size = 0; + ft2232_expect_read = 0; + + /* blink, if the current layout has that feature */ + if (layout->blink) + layout->blink(); + + while (cmd) + { + switch(cmd->type) + { + case JTAG_END_STATE: + if (cmd->cmd.end_state->end_state != -1) + ft2232_end_state(cmd->cmd.end_state->end_state); + break; + case JTAG_RESET: + /* only send the maximum buffer size that FT2232C can handle */ + predicted_size = 3; + if (ft2232_buffer_size + predicted_size + 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; + } + + layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + require_send = 1; + +#ifdef _DEBUG_JTAG_IO_ + DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); +#endif break; case JTAG_RUNTEST: /* only send the maximum buffer size that FT2232C can handle */ @@ -773,7 +1171,8 @@ int ft2232_execute_queue() predicted_size += 3; if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - ft2232_send_and_recv(first_unsent, cmd); + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } @@ -799,7 +1198,7 @@ int ft2232_execute_queue() BUFFER_ADD = 0x0; cur_state = TAP_RTI; i -= (i > 7) ? 7 : i; - //DEBUG("added TMS scan (no read)"); + /* DEBUG("added TMS scan (no read)"); */ } if (cmd->cmd.runtest->end_state != -1) ft2232_end_state(cmd->cmd.runtest->end_state); @@ -812,7 +1211,7 @@ int ft2232_execute_queue() /* TMS data bits */ BUFFER_ADD = TAP_MOVE(cur_state, end_state); cur_state = end_state; - //DEBUG("added TMS scan (no read)"); + /* DEBUG("added TMS scan (no read)"); */ } require_send = 1; #ifdef _DEBUG_JTAG_IO_ @@ -824,7 +1223,8 @@ int ft2232_execute_queue() predicted_size = 3; if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - ft2232_send_and_recv(first_unsent, cmd); + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } @@ -836,7 +1236,7 @@ int ft2232_execute_queue() BUFFER_ADD = 0x6; /* TMS data bits */ BUFFER_ADD = TAP_MOVE(cur_state, end_state); - //DEBUG("added TMS scan (no read)"); + /* DEBUG("added TMS scan (no read)"); */ cur_state = end_state; require_send = 1; #ifdef _DEBUG_JTAG_IO_ @@ -848,7 +1248,8 @@ int ft2232_execute_queue() predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7); if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - ft2232_send_and_recv(first_unsent, cmd); + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } @@ -862,15 +1263,34 @@ int ft2232_execute_queue() scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); predicted_size = ft2232_predict_scan_out(scan_size, type); - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) + if ((predicted_size + 1) > FT2232_BUFFER_SIZE) + { + DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); + /* unsent commands before this */ + if (first_unsent != cmd) + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + + /* current command */ + if (cmd->cmd.scan->end_state != -1) + ft2232_end_state(cmd->cmd.scan->end_state); + ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size); + require_send = 0; + first_unsent = cmd->next; + if (buffer) + free(buffer); + break; + } + else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - DEBUG("ftd2xx buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd); - ft2232_send_and_recv(first_unsent, cmd); + DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd); + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; require_send = 0; first_unsent = cmd; } ft2232_expect_read += ft2232_predict_scan_in(scan_size, type); - //DEBUG("new read size: %i", ft2232_expect_read); + /* DEBUG("new read size: %i", ft2232_expect_read); */ if (cmd->cmd.scan->end_state != -1) ft2232_end_state(cmd->cmd.scan->end_state); ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); @@ -882,7 +1302,8 @@ int ft2232_execute_queue() #endif break; case JTAG_SLEEP: - ft2232_send_and_recv(first_unsent, cmd); + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; first_unsent = cmd->next; jtag_sleep(cmd->cmd.sleep->us); #ifdef _DEBUG_JTAG_IO_ @@ -897,73 +1318,67 @@ int ft2232_execute_queue() } if (require_send > 0) - ft2232_send_and_recv(first_unsent, cmd); + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; - return ERROR_OK; + return retval; } -int ft2232_init(void) -{ - u8 latency_timer; - u8 buf[1]; - int retval; - u32 bytes_written; - #if BUILD_FT2232_FTD2XX == 1 +static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int *try_more) +{ FT_STATUS status; -#endif + DWORD openex_flags = 0; + char *openex_string = NULL; + u8 latency_timer; - ft2232_layout_t *cur_layout = ft2232_layouts; - - if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0)) - { - ft2232_layout = "usbjtag"; - 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++; - } + DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", + ft2232_layout, vid, pid); - if (!layout) +#if IS_WIN32 == 0 + /* Add non-standard Vid/Pid to the linux driver */ + if ((status = FT_SetVIDPID(vid, pid)) != FT_OK) { - ERROR("No matching layout found for %s", ft2232_layout); - return ERROR_JTAG_INIT_FAILED; + WARNING("couldn't add %4.4x:%4.4x", + vid, pid); } - -#if BUILD_FT2232_FTD2XX == 1 - DEBUG("'ft2232' interface using FTD2XX with '%s' layout", ft2232_layout); -#elif BUILD_FT2232_LIBFTDI == 1 - DEBUG("'ft2232' interface using libftdi with '%s' layout", ft2232_layout); #endif -#if BUILD_FT2232_FTD2XX == 1 - /* Open by device description */ - if (ft2232_device_desc == NULL) + if (ft2232_device_desc && ft2232_serial) { - WARNING("no ftd2xx device description specified, using default 'Dual RS232'"); - ft2232_device_desc = "Dual RS232"; + WARNING("can't open by device description and serial number, giving precedence to serial"); + ft2232_device_desc = NULL; } -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - if ((status = FT_SetVIDPID(ft2232_vid, ft2232_pid)) != FT_OK) + if (ft2232_device_desc) { - WARNING("couldn't add %4.4x:%4.4x", ft2232_vid, ft2232_pid); + openex_string = ft2232_device_desc; + openex_flags = FT_OPEN_BY_DESCRIPTION; + } + else if (ft2232_serial) + { + openex_string = ft2232_serial; + openex_flags = FT_OPEN_BY_SERIAL_NUMBER; + } + else + { + ERROR("neither device description nor serial number specified"); + ERROR("please add \"ft2232_device_desc \" or \"ft2232_serial \" to your .cfg file"); + + return ERROR_JTAG_INIT_FAILED; } -#endif - if ((status = FT_OpenEx(ft2232_device_desc, FT_OPEN_BY_DESCRIPTION, &ftdih)) != FT_OK) + if ((status = FT_OpenEx(openex_string, openex_flags, &ftdih)) != FT_OK) { DWORD num_devices; - ERROR("unable to open ftdi device: %i", status); + if (more) { + WARNING("unable to open ftdi device (trying more): %lu", + status); + *try_more = 1; + return ERROR_JTAG_INIT_FAILED; + } + ERROR("unable to open ftdi device: %lu", status); status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); if (status == FT_OK) { @@ -974,11 +1389,11 @@ int ft2232_init(void) desc_array[i] = malloc(64); desc_array[num_devices] = NULL; - status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); + status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags); if (status == FT_OK) { - ERROR("ListDevices: %d\n", num_devices); + ERROR("ListDevices: %lu\n", num_devices); for (i = 0; i < num_devices; i++) ERROR("%i: %s", i, desc_array[i]); } @@ -989,40 +1404,82 @@ int ft2232_init(void) } else { - printf("ListDevices: NONE\n"); + ERROR("ListDevices: NONE\n"); } return ERROR_JTAG_INIT_FAILED; } - if ((status = FT_SetLatencyTimer(ftdih, 2)) != FT_OK) + if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK) { - ERROR("unable to set latency timer: %i", status); + ERROR("unable to set latency timer: %lu", status); return ERROR_JTAG_INIT_FAILED; } if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK) { - ERROR("unable to get latency timer: %i", status); + ERROR("unable to get latency timer: %lu", status); return ERROR_JTAG_INIT_FAILED; } else { DEBUG("current latency timer: %i", latency_timer); } + + if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK) + { + ERROR("unable to set timeouts: %lu", status); + return ERROR_JTAG_INIT_FAILED; + } if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK) { - ERROR("unable to enable bit i/o mode: %i", status); + ERROR("unable to enable bit i/o mode: %lu", status); return ERROR_JTAG_INIT_FAILED; } -#elif BUILD_FT2232_LIBFTDI == 1 + + return ERROR_OK; +} + +static int ft2232_purge_ftd2xx(void) +{ + FT_STATUS status; + + if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK) + { + ERROR("error purging ftd2xx device: %lu", status); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} +#endif /* BUILD_FT2232_FTD2XX == 1 */ + +#if BUILD_FT2232_LIBFTDI == 1 +static int ft2232_init_libftdi(u16 vid, u16 pid, int more, int *try_more) +{ + u8 latency_timer; + + DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)", + ft2232_layout, vid, pid); + if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; /* context, vendor id, product id */ - if (ftdi_usb_open(&ftdic, ft2232_vid, ft2232_pid) < 0) + if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc, + ft2232_serial) < 0) { + if (more) + WARNING("unable to open ftdi device (trying more): %s", + ftdic.error_str); + else + ERROR("unable to open ftdi device: %s", ftdic.error_str); + *try_more = 1; + return ERROR_JTAG_INIT_FAILED; + } + + if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0) { - ERROR("unable to open ftdi device: %s", ftdic.error_str); + ERROR("unable to select FT2232 channel A: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } @@ -1032,7 +1489,7 @@ int ft2232_init(void) return ERROR_JTAG_INIT_FAILED; } - if (ftdi_set_latency_timer(&ftdic, 2) < 0) + if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0) { ERROR("unable to set latency timer"); return ERROR_JTAG_INIT_FAILED; @@ -1048,12 +1505,78 @@ int ft2232_init(void) DEBUG("current latency timer: %i", latency_timer); } - ftdic.bitbang_mode = 0; /* Reset controller */ - ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */ + ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */ + + return ERROR_OK; +} + +static int ft2232_purge_libftdi(void) +{ + if (ftdi_usb_purge_buffers(&ftdic) < 0) + { + ERROR("ftdi_purge_buffers: %s", ftdic.error_str); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} +#endif /* BUILD_FT2232_LIBFTDI == 1 */ + +int ft2232_init(void) +{ + u8 buf[1]; + int retval; + u32 bytes_written; + ft2232_layout_t *cur_layout = ft2232_layouts; + int i; + + if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0)) + { + ft2232_layout = "usbjtag"; + 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) + { + ERROR("No matching layout found for %s", ft2232_layout); + return ERROR_JTAG_INIT_FAILED; + } + + for (i = 0; 1; i++) { + /* + * "more indicates that there are more IDs to try, so we should + * not print an error for an ID mismatch (but for anything + * else, we should). + * + * try_more indicates that the error code returned indicates an + * ID mismatch (and nothing else) and that we should proceeed + * with the next ID pair. + */ + int more = ft2232_vid[i+1] || ft2232_pid[i+1]; + int try_more = 0; - ftdic.bitbang_mode = 2; /* MPSSE mode */ - ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */ +#if BUILD_FT2232_FTD2XX == 1 + retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i], + more, &try_more); +#elif BUILD_FT2232_LIBFTDI == 1 + retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], + more, &try_more); #endif + if (retval >= 0) + break; + if (!more || !try_more) + return retval; + } ft2232_buffer_size = 0; ft2232_buffer = malloc(FT2232_BUFFER_SIZE); @@ -1071,17 +1594,9 @@ int ft2232_init(void) } #if BUILD_FT2232_FTD2XX == 1 - if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK) - { - ERROR("error purging ftd2xx device: %i", status); - return ERROR_JTAG_INIT_FAILED; - } + return ft2232_purge_ftd2xx(); #elif BUILD_FT2232_LIBFTDI == 1 - if (ftdi_usb_purge_buffers(&ftdic) < 0) - { - ERROR("ftdi_purge_buffers: %s", ftdic.error_str); - return ERROR_JTAG_INIT_FAILED; - } + return ft2232_purge_libftdi(); #endif return ERROR_OK; @@ -1109,6 +1624,15 @@ int usbjtag_init(void) 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 { ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout); @@ -1179,7 +1703,8 @@ int jtagkey_init(void) nSRST = 0x02; nSRSTnOE = 0x08; } - else if (strcmp(layout->name, "jtagkey_prototype_v1") == 0) + else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) || + (strcmp(layout->name, "oocdlink") == 0)) { nTRST = 0x02; nTRSTnOE = 0x1; @@ -1298,6 +1823,178 @@ int olimex_jtag_init(void) return ERROR_OK; } +int flyswatter_init(void) +{ + u8 buf[3]; + u32 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 */ + 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)) + { + ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x10; + nTRSTnOE = 0x0; /* not output enable for nTRST */ + nSRST = 0x20; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + high_output = 0x00; + high_direction = 0x0c; + + /* turn red LED1 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) */ + 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)) + { + ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int turtle_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + 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 */ + 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)) + { + ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nSRST = 0x40; + + 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; + 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)) + { + ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int comstick_init(void) +{ + u8 buf[3]; + u32 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 */ + 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)) + { + ERROR("couldn't initialize FT2232 with 'comstick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x01; + nTRSTnOE = 0x00; /* no output enable for nTRST */ + nSRST = 0x02; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + 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; + 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)) + { + ERROR("couldn't initialize FT2232 with 'comstick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int stm32stick_init(void) +{ + u8 buf[3]; + u32 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 */ + 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)) + { + ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x01; + nTRSTnOE = 0x00; /* no output enable for nTRST */ + nSRST = 0x80; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + 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; + 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)) + { + ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + void olimex_jtag_blink(void) { /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 @@ -1319,6 +2016,26 @@ void olimex_jtag_blink(void) BUFFER_ADD = high_direction; } +void turtle_jtag_blink(void) +{ + /* + * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3 + */ + if (high_output & 0x08) + { + high_output = 0x04; + } + else + { + high_output = 0x08; + } + + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; +} + + int ft2232_quit(void) { #if BUILD_FT2232_FTD2XX == 1 @@ -1334,6 +2051,7 @@ int ft2232_quit(void) #endif free(ft2232_buffer); + ft2232_buffer = NULL; return ERROR_OK; } @@ -1352,6 +2070,20 @@ int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *c return ERROR_OK; } +int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 1) + { + ft2232_serial = strdup(args[0]); + } + else + { + ERROR("expected exactly one argument to ft2232_serial "); + } + + return ERROR_OK; +} + int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { if (argc == 0) @@ -1365,15 +2097,45 @@ int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, c int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { - if (argc >= 2) + int i; + + if (argc > MAX_USB_IDS*2) { + WARNING("ignoring extra IDs in ft2232_vid_pid " + "(maximum is %d pairs)", MAX_USB_IDS); + argc = MAX_USB_IDS*2; + } + if (argc < 2 || (argc & 1)) { - ft2232_vid = strtol(args[0], NULL, 0); - ft2232_pid = strtol(args[1], NULL, 0); + WARNING("incomplete ft2232_vid_pid configuration directive"); + if (argc < 2) + return ERROR_OK; + } + + for (i = 0; i+1 < argc; i += 2) { + ft2232_vid[i >> 1] = strtol(args[i], NULL, 0); + ft2232_pid[i >> 1] = strtol(args[i+1], NULL, 0); + } + /* + * Explicitly terminate, in case there are multiples instances of + * ft2232_vid_pid. + */ + ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0; + + return ERROR_OK; +} + +int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 1) + { + ft2232_latency = atoi(args[0]); } else { - WARNING("incomplete ft2232_vid_pid configuration directive"); + ERROR("expected exactly one argument to ft2232_latency "); } return ERROR_OK; } + +