X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fft2232.c;h=70050babe8e9eac3bb3936cdebe9d0ec1804f77a;hp=50ff6548d467e60d4e9f00d0e15cb5b34d3b00bb;hb=265b0a9fca4121c1acee8246e88328dd8bd583fd;hpb=38228317921901e87beb70cba0c170092470e3e5 diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index 50ff6548d4..70050babe8 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -33,23 +33,14 @@ #include "config.h" #endif -#if IS_CYGWIN == 1 -#include "windows.h" -#endif - -#include "replacements.h" - /* project specific includes */ -#include "log.h" -#include "types.h" #include "jtag.h" -#include "configuration.h" #include "time_support.h" -/* system includes */ -#include -#include -#include +#if IS_CYGWIN == 1 +#include +#endif + /* FT2232 access library includes */ #if BUILD_FT2232_FTD2XX == 1 @@ -58,32 +49,20 @@ #include #endif -/* enable this to debug io latency - */ -#if 0 -#define _DEBUG_USB_IO_ -#endif +static int ft2232_execute_queue(void); -/* enable this to debug communication - */ -#if 0 -#define _DEBUG_USB_COMMS_ -#endif - -int ft2232_execute_queue(void); - -int ft2232_speed(int speed); -int ft2232_speed_div(int speed, int* khz); -int ft2232_khz(int khz, int* jtag_speed); -int ft2232_register_commands(struct command_context_s* cmd_ctx); -int ft2232_init(void); -int ft2232_quit(void); +static int ft2232_speed(int speed); +static int ft2232_speed_div(int speed, int* khz); +static int ft2232_khz(int khz, int* jtag_speed); +static int ft2232_register_commands(struct command_context_s* cmd_ctx); +static int ft2232_init(void); +static 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); +static int ft2232_handle_device_desc_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc); +static int ft2232_handle_serial_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc); +static int ft2232_handle_layout_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc); +static int ft2232_handle_vid_pid_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc); +static int ft2232_handle_latency_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc); /** @@ -97,10 +76,11 @@ int ft2232_handle_latency_command(struct command_context_s* cmd_ctx, char* cmd, static int ft2232_stableclocks(int num_cycles, jtag_command_t* cmd); -char* ft2232_device_desc = NULL; -char* ft2232_serial = NULL; -char* ft2232_layout = NULL; -unsigned char ft2232_latency = 2; +static char * ft2232_device_desc_A = NULL; +static char* ft2232_device_desc = NULL; +static char* ft2232_serial = NULL; +static char* ft2232_layout = NULL; +static unsigned char ft2232_latency = 2; #define MAX_USB_IDS 8 /* vid = pid = 0 marks the end of the list */ @@ -116,30 +96,33 @@ typedef struct ft2232_layout_s } ft2232_layout_t; /* init procedures for supported layouts */ -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); -int axm0432_jtag_init(void); -int sheevaplug_init(void); +static int usbjtag_init(void); +static int jtagkey_init(void); +static int olimex_jtag_init(void); +static int flyswatter_init(void); +static int turtle_init(void); +static int comstick_init(void); +static int stm32stick_init(void); +static int axm0432_jtag_init(void); +static int sheevaplug_init(void); +static int icebear_jtag_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); -void axm0432_jtag_reset(int trst, int srst); -void sheevaplug_reset(int trst, int srst); +static void usbjtag_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 turtle_reset(int trst, int srst); +static void comstick_reset(int trst, int srst); +static void stm32stick_reset(int trst, int srst); +static void axm0432_jtag_reset(int trst, int srst); +static void sheevaplug_reset(int trst, int srst); +static void icebear_jtag_reset(int trst, int srst); /* blink procedures for layouts that support a blinking led */ -void olimex_jtag_blink(void); -void turtle_jtag_blink(void); +static void olimex_jtag_blink(void); +static void flyswatter_jtag_blink(void); +static void turtle_jtag_blink(void); ft2232_layout_t ft2232_layouts[] = { @@ -150,13 +133,14 @@ ft2232_layout_t ft2232_layouts[] = { "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 }, + { "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 }, - { NULL, NULL, NULL }, + { "icebear", icebear_jtag_init, icebear_jtag_reset, NULL }, + { NULL, NULL, NULL, NULL }, }; static u8 nTRST, nTRSTnOE, nSRST, nSRSTnOE; @@ -198,7 +182,7 @@ jtag_interface_t ft2232_interface = .quit = ft2232_quit, }; -int ft2232_write(u8* buf, int size, u32* bytes_written) +static int ft2232_write(u8* buf, int size, u32* bytes_written) { #if BUILD_FT2232_FTD2XX == 1 FT_STATUS status; @@ -231,7 +215,7 @@ int ft2232_write(u8* buf, int size, u32* bytes_written) } -int ft2232_read(u8* buf, int size, u32* bytes_read) +static int ft2232_read(u8* buf, u32 size, u32* bytes_read) { #if BUILD_FT2232_FTD2XX == 1 DWORD dw_bytes_read; @@ -279,7 +263,7 @@ int ft2232_read(u8* buf, int size, u32* bytes_read) } -int ft2232_speed(int speed) +static int ft2232_speed(int speed) { u8 buf[3]; int retval; @@ -300,7 +284,7 @@ int ft2232_speed(int speed) } -int ft2232_speed_div(int speed, int* khz) +static int ft2232_speed_div(int speed, int* khz) { /* Take a look in the FT2232 manual, * AN2232C-01 Command Processor for @@ -312,7 +296,7 @@ int ft2232_speed_div(int speed, int* khz) } -int ft2232_khz(int khz, int* jtag_speed) +static int ft2232_khz(int khz, int* jtag_speed) { if (khz==0) { @@ -353,7 +337,7 @@ int ft2232_khz(int khz, int* jtag_speed) } -int ft2232_register_commands(struct command_context_s* cmd_ctx) +static 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, "the USB device description of the FTDI FT2232 device"); @@ -381,7 +365,7 @@ void ft2232_end_state(tap_state_t state) } -void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size) +static void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size) { int num_bytes = (scan_size + 7) / 8; int bits_left = scan_size; @@ -405,7 +389,7 @@ void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size) } -void ft2232_debug_dump_buffer(void) +static void ft2232_debug_dump_buffer(void) { int i; char line[256]; @@ -426,15 +410,15 @@ void ft2232_debug_dump_buffer(void) } -int ft2232_send_and_recv(jtag_command_t* first, jtag_command_t* last) +static int ft2232_send_and_recv(jtag_command_t* first, jtag_command_t* last) { jtag_command_t* cmd; u8* buffer; int scan_size; enum scan_type type; int retval; - u32 bytes_written; - u32 bytes_read; + u32 bytes_written=0; + u32 bytes_read=0; #ifdef _DEBUG_USB_IO_ struct timeval start, inter, inter2, end; @@ -482,9 +466,10 @@ int ft2232_send_and_recv(jtag_command_t* first, jtag_command_t* last) timeval_subtract(&d_inter2, &inter2, &start); timeval_subtract(&d_end, &end, &start); - LOG_INFO("inter: %i.%06i, inter2: %i.%06i end: %i.%06i", d_inter.tv_sec, d_inter.tv_usec, d_inter2.tv_sec, - d_inter2.tv_usec, d_end.tv_sec, - d_end.tv_usec); + LOG_INFO("inter: %u.%06u, inter2: %u.%06u end: %u.%06u", + (unsigned)d_inter.tv_sec, (unsigned)d_inter.tv_usec, + (unsigned)d_inter2.tv_sec, (unsigned)d_inter2.tv_usec, + (unsigned)d_end.tv_sec, (unsigned)d_end.tv_usec); #endif ft2232_buffer_size = bytes_read; @@ -544,7 +529,7 @@ int ft2232_send_and_recv(jtag_command_t* first, jtag_command_t* last) } -void ft2232_add_pathmove(pathmove_command_t* cmd) +static void ft2232_add_pathmove(pathmove_command_t* cmd) { int num_states = cmd->num_states; int state_count = 0; @@ -740,7 +725,7 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8* buffer, int scan_size } -int ft2232_large_scan(scan_command_t* cmd, enum scan_type type, u8* buffer, int scan_size) +static 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; @@ -950,7 +935,7 @@ int ft2232_large_scan(scan_command_t* cmd, enum scan_type type, u8* buffer, int } -int ft2232_predict_scan_out(int scan_size, enum scan_type type) +static int ft2232_predict_scan_out(int scan_size, enum scan_type type) { int predicted_size = 3; int num_bytes = (scan_size - 1) / 8; @@ -977,7 +962,7 @@ int ft2232_predict_scan_out(int scan_size, enum scan_type type) } -int ft2232_predict_scan_in(int scan_size, enum scan_type type) +static int ft2232_predict_scan_in(int scan_size, enum scan_type type) { int predicted_size = 0; @@ -999,7 +984,7 @@ int ft2232_predict_scan_in(int scan_size, enum scan_type type) } -void usbjtag_reset(int trst, int srst) +static void usbjtag_reset(int trst, int srst) { if (trst == 1) { @@ -1038,7 +1023,7 @@ void usbjtag_reset(int trst, int srst) } -void jtagkey_reset(int trst, int srst) +static void jtagkey_reset(int trst, int srst) { if (trst == 1) { @@ -1079,7 +1064,7 @@ void jtagkey_reset(int trst, int srst) } -void olimex_jtag_reset(int trst, int srst) +static void olimex_jtag_reset(int trst, int srst) { if (trst == 1) { @@ -1114,7 +1099,7 @@ void olimex_jtag_reset(int trst, int srst) } -void axm0432_jtag_reset(int trst, int srst) +static void axm0432_jtag_reset(int trst, int srst) { if (trst == 1) { @@ -1144,7 +1129,7 @@ void axm0432_jtag_reset(int trst, int srst) } -void flyswatter_reset(int trst, int srst) +static void flyswatter_reset(int trst, int srst) { if (trst == 1) { @@ -1172,7 +1157,7 @@ void flyswatter_reset(int trst, int srst) } -void turtle_reset(int trst, int srst) +static void turtle_reset(int trst, int srst) { trst = trst; @@ -1193,7 +1178,7 @@ void turtle_reset(int trst, int srst) } -void comstick_reset(int trst, int srst) +static void comstick_reset(int trst, int srst) { if (trst == 1) { @@ -1222,7 +1207,7 @@ void comstick_reset(int trst, int srst) } -void stm32stick_reset(int trst, int srst) +static void stm32stick_reset(int trst, int srst) { if (trst == 1) { @@ -1257,7 +1242,7 @@ void stm32stick_reset(int trst, int srst) -void sheevaplug_reset(int trst, int srst) +static void sheevaplug_reset(int trst, int srst) { if (trst == 1) high_output &= ~nTRST; @@ -1276,247 +1261,336 @@ 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); } -int ft2232_execute_queue() +static int ft2232_execute_end_state(jtag_command_t *cmd) { - jtag_command_t* cmd = jtag_command_queue; /* currently processed command */ - u8* buffer; - int scan_size; /* size of IR or DR scan */ - enum scan_type type; - int i; - int predicted_size = 0; - int retval; + int retval; + retval = ERROR_OK; - first_unsent = cmd; /* next command that has to be sent */ - require_send = 0; + DEBUG_JTAG_IO("end_state: %i", cmd->cmd.end_state->end_state); - /* 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; + if (cmd->cmd.end_state->end_state != TAP_INVALID) + ft2232_end_state(cmd->cmd.end_state->end_state); - ft2232_buffer_size = 0; - ft2232_expect_read = 0; + return retval; +} - /* blink, if the current layout has that feature */ - if (layout->blink) - layout->blink(); - while (cmd) +static int ft2232_execute_runtest(jtag_command_t *cmd) +{ + int retval; + int i; + int predicted_size = 0; + retval = ERROR_OK; + + DEBUG_JTAG_IO("runtest %i cycles, end in %i", + cmd->cmd.runtest->num_cycles, + cmd->cmd.runtest->end_state); + /* only send the maximum buffer size that FT2232C can handle */ + predicted_size = 0; + if (tap_get_state() != TAP_IDLE) + predicted_size += 3; + predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7); + if ( (cmd->cmd.runtest->end_state != TAP_INVALID) && (cmd->cmd.runtest->end_state != TAP_IDLE) ) + predicted_size += 3; + if ( (cmd->cmd.runtest->end_state == TAP_INVALID) && (tap_get_end_state() != TAP_IDLE) ) + predicted_size += 3; + if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - 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; + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + require_send = 0; + first_unsent = cmd; + } + if (tap_get_state() != TAP_IDLE) + { + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; + BUFFER_ADD = 0x6; /* scan 7 bits */ - 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; - } + /* TMS data bits */ + BUFFER_ADD = tap_get_tms_path(tap_get_state(), TAP_IDLE); + tap_set_state(TAP_IDLE); + require_send = 1; + } + i = cmd->cmd.runtest->num_cycles; + while (i > 0) + { + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; - if ( (cmd->cmd.reset->trst == 1) || ( cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST) ) ) - { - tap_set_state(TAP_RESET); - } - layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - require_send = 1; + /* scan 7 bits */ + BUFFER_ADD = (i > 7) ? 6 : (i - 1); + + /* TMS data bits */ + BUFFER_ADD = 0x0; + tap_set_state(TAP_IDLE); + i -= (i > 7) ? 7 : i; + /* LOG_DEBUG("added TMS scan (no read)"); */ + } + + if (cmd->cmd.runtest->end_state != TAP_INVALID) + ft2232_end_state(cmd->cmd.runtest->end_state); + if ( tap_get_state() != tap_get_end_state() ) + { + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; + /* scan 7 bit */ + BUFFER_ADD = 0x6; + /* TMS data bits */ + BUFFER_ADD = tap_get_tms_path( tap_get_state(), tap_get_end_state() ); + tap_set_state( tap_get_end_state() ); + /* LOG_DEBUG("added TMS scan (no read)"); */ + } + require_send = 1; #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); + LOG_DEBUG( "runtest: %i, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name( tap_get_end_state() ) ); #endif - break; - case JTAG_RUNTEST: - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 0; - if (tap_get_state() != TAP_IDLE) - predicted_size += 3; - predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7); - if ( (cmd->cmd.runtest->end_state != -1) && (cmd->cmd.runtest->end_state != TAP_IDLE) ) - predicted_size += 3; - if ( (cmd->cmd.runtest->end_state == -1) && (tap_get_end_state() != TAP_IDLE) ) - 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; - } - if (tap_get_state() != TAP_IDLE) - { - /* command "Clock Data to TMS/CS Pin (no Read)" */ - BUFFER_ADD = 0x4b; - BUFFER_ADD = 0x6; /* scan 7 bits */ - - /* TMS data bits */ - BUFFER_ADD = tap_get_tms_path(tap_get_state(), TAP_IDLE); - tap_set_state(TAP_IDLE); - require_send = 1; - } - i = cmd->cmd.runtest->num_cycles; - while (i > 0) - { - /* command "Clock Data to TMS/CS Pin (no Read)" */ - BUFFER_ADD = 0x4b; + return retval; +} - /* scan 7 bits */ - BUFFER_ADD = (i > 7) ? 6 : (i - 1); +static int ft2232_execute_statemove(jtag_command_t *cmd) +{ + int retval; + int predicted_size = 0; + retval = ERROR_OK; - /* TMS data bits */ - BUFFER_ADD = 0x0; - tap_set_state(TAP_IDLE); - i -= (i > 7) ? 7 : i; - /* LOG_DEBUG("added TMS scan (no read)"); */ - } + DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); - if (cmd->cmd.runtest->end_state != -1) - ft2232_end_state(cmd->cmd.runtest->end_state); + /* 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; + } + if (cmd->cmd.statemove->end_state != TAP_INVALID) + ft2232_end_state(cmd->cmd.statemove->end_state); - if ( tap_get_state() != tap_get_end_state() ) - { - /* command "Clock Data to TMS/CS Pin (no Read)" */ - BUFFER_ADD = 0x4b; - /* scan 7 bit */ - BUFFER_ADD = 0x6; - /* TMS data bits */ - BUFFER_ADD = tap_get_tms_path( tap_get_state(), tap_get_end_state() ); - tap_set_state( tap_get_end_state() ); - /* LOG_DEBUG("added TMS scan (no read)"); */ - } - require_send = 1; -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG( "runtest: %i, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name( tap_get_end_state() ) ); -#endif - break; + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; - case JTAG_STATEMOVE: - /* 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; - } - if (cmd->cmd.statemove->end_state != -1) - ft2232_end_state(cmd->cmd.statemove->end_state); + BUFFER_ADD = 0x6; /* scan 7 bits */ - /* command "Clock Data to TMS/CS Pin (no Read)" */ - BUFFER_ADD = 0x4b; + /* TMS data bits */ + BUFFER_ADD = tap_get_tms_path( tap_get_state(), tap_get_end_state() ); + /* LOG_DEBUG("added TMS scan (no read)"); */ + tap_set_state( tap_get_end_state() ); + require_send = 1; +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG( "statemove: %s", tap_state_name( tap_get_end_state() ) ); +#endif + + return retval; +} - BUFFER_ADD = 0x6; /* scan 7 bits */ +static int ft2232_execute_pathmove(jtag_command_t *cmd) +{ + int retval; + int predicted_size = 0; + retval = ERROR_OK; - /* TMS data bits */ - BUFFER_ADD = tap_get_tms_path( tap_get_state(), tap_get_end_state() ); - /* LOG_DEBUG("added TMS scan (no read)"); */ - tap_set_state( tap_get_end_state() ); - require_send = 1; + DEBUG_JTAG_IO("pathmove: %i states, end in %i", + cmd->cmd.pathmove->num_states, + cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + /* only send the maximum buffer size that FT2232C can handle */ + predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7); + 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; + } + ft2232_add_pathmove(cmd->cmd.pathmove); + require_send = 1; #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG( "statemove: %s", tap_state_name( tap_get_end_state() ) ); + LOG_DEBUG( "pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, + tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]) ); #endif - break; + return retval; +} - case JTAG_PATHMOVE: - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7); - 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; - } - ft2232_add_pathmove(cmd->cmd.pathmove); - require_send = 1; +static int ft2232_execute_scan(jtag_command_t *cmd) +{ + int retval; + u8* buffer; + int scan_size; /* size of IR or DR scan */ + enum scan_type type; + int predicted_size = 0; + retval = ERROR_OK; + + 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 ( (predicted_size + 1) > FT2232_BUFFER_SIZE ) + { + LOG_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 != TAP_INVALID) + 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); + return retval; + } + else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) + { + LOG_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); + /* LOG_DEBUG("new read size: %i", ft2232_expect_read); */ + if (cmd->cmd.scan->end_state != TAP_INVALID) + ft2232_end_state(cmd->cmd.scan->end_state); + ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); + require_send = 1; + if (buffer) + free(buffer); #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG( "pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, - tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]) ); + LOG_DEBUG( "%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, + tap_state_name( tap_get_end_state() ) ); #endif - break; + return retval; + +} + +static int ft2232_execute_reset(jtag_command_t *cmd) +{ + int retval; + int predicted_size = 0; + retval = ERROR_OK; + + DEBUG_JTAG_IO("reset trst: %i srst %i", + cmd->cmd.reset->trst, cmd->cmd.reset->srst); + + /* 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; + } + + if ( (cmd->cmd.reset->trst == 1) || ( cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST) ) ) + { + tap_set_state(TAP_RESET); + } + layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + require_send = 1; - case JTAG_SCAN: - 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 ( (predicted_size + 1) > FT2232_BUFFER_SIZE ) - { - LOG_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) - { - LOG_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); - /* LOG_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); - require_send = 1; - if (buffer) - free(buffer); #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG( "%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, - tap_state_name( tap_get_end_state() ) ); + LOG_DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif - break; + return retval; +} - case JTAG_SLEEP: - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) +static int ft2232_execute_sleep(jtag_command_t *cmd) +{ + int retval; + retval = ERROR_OK; + + DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us); + + 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); + first_unsent = cmd->next; + jtag_sleep(cmd->cmd.sleep->us); #ifdef _DEBUG_JTAG_IO_ LOG_DEBUG( "sleep %i usec while in %s", cmd->cmd.sleep->us, tap_state_name( tap_get_state() ) ); #endif - break; - case JTAG_STABLECLOCKS: + return retval; +} - /* this is only allowed while in a stable state. A check for a stable - * state was done in jtag_add_clocks() - */ - if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; +static int ft2232_execute_stableclocks(jtag_command_t *cmd) +{ + int retval; + retval = ERROR_OK; + + /* this is only allowed while in a stable state. A check for a stable + * state was done in jtag_add_clocks() + */ + if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG( "clocks %i while in %s", cmd->cmd.stableclocks->num_cycles, tap_state_name( tap_get_state() ) ); + LOG_DEBUG( "clocks %i while in %s", cmd->cmd.stableclocks->num_cycles, tap_state_name( tap_get_state() ) ); #endif - break; + return retval; +} + +static int ft2232_execute_command(jtag_command_t *cmd) +{ + int retval; + retval = ERROR_OK; + + switch (cmd->type) + { + case JTAG_END_STATE: retval = ft2232_execute_end_state(cmd); break; + 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_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; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); - } + exit(-1); + } + return retval; +} + +static int ft2232_execute_queue() +{ + jtag_command_t* cmd = jtag_command_queue; /* currently processed command */ + int retval; + + first_unsent = cmd; /* next command that has to be sent */ + require_send = 0; + + /* 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) + { + if (ft2232_execute_command(cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + /* Start reading input before FT2232 TX buffer fills up */ cmd = cmd->next; + if (ft2232_expect_read > 256) + { + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + first_unsent = cmd; + } } if (require_send > 0) @@ -1569,7 +1643,28 @@ static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int* try_more) return ERROR_JTAG_INIT_FAILED; } - if ( ( status = FT_OpenEx(openex_string, openex_flags, &ftdih) ) != FT_OK ) + status = FT_OpenEx(openex_string, openex_flags, &ftdih); + if( status != FT_OK ){ + // under Win32, the FTD2XX driver appends an "A" to the end + // of the description, if we tried by the desc, then + // try by the alternate "A" description. + if( openex_string == ft2232_device_desc ){ + // Try the alternate method. + openex_string = ft2232_device_desc_A; + status = FT_OpenEx(openex_string, openex_flags, &ftdih); + if( status == FT_OK ){ + // yea, the "alternate" method worked! + } 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", + ft2232_device_desc, + ft2232_device_desc_A ); + } + } + } + + if ( status != FT_OK ) { DWORD num_devices; @@ -1584,7 +1679,7 @@ static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int* try_more) if (status == FT_OK) { char** desc_array = malloc( sizeof(char*) * (num_devices + 1) ); - int i; + u32 i; for (i = 0; i < num_devices; i++) desc_array[i] = malloc(64); @@ -1732,7 +1827,7 @@ static int ft2232_purge_libftdi(void) #endif /* BUILD_FT2232_LIBFTDI == 1 */ -int ft2232_init(void) +static int ft2232_init(void) { u8 buf[1]; int retval; @@ -1814,7 +1909,7 @@ int ft2232_init(void) } -int usbjtag_init(void) +static int usbjtag_init(void) { u8 buf[3]; u32 bytes_written; @@ -1889,7 +1984,7 @@ int usbjtag_init(void) } -int axm0432_jtag_init(void) +static int axm0432_jtag_init(void) { u8 buf[3]; u32 bytes_written; @@ -1959,7 +2054,7 @@ int axm0432_jtag_init(void) } -int jtagkey_init(void) +static int jtagkey_init(void) { u8 buf[3]; u32 bytes_written; @@ -2041,7 +2136,7 @@ int jtagkey_init(void) } -int olimex_jtag_init(void) +static int olimex_jtag_init(void) { u8 buf[3]; u32 bytes_written; @@ -2108,7 +2203,7 @@ int olimex_jtag_init(void) } -int flyswatter_init(void) +static int flyswatter_init(void) { u8 buf[3]; u32 bytes_written; @@ -2136,7 +2231,7 @@ int flyswatter_init(void) high_output = 0x00; high_direction = 0x0c; - /* turn red LED1 on, LED2 off */ + /* turn red LED3 on, LED2 off */ high_output |= 0x08; /* initialize high port */ @@ -2155,7 +2250,7 @@ int flyswatter_init(void) } -int turtle_init(void) +static int turtle_init(void) { u8 buf[3]; u32 bytes_written; @@ -2196,7 +2291,7 @@ int turtle_init(void) } -int comstick_init(void) +static int comstick_init(void) { u8 buf[3]; u32 bytes_written; @@ -2240,7 +2335,7 @@ int comstick_init(void) } -int stm32stick_init(void) +static int stm32stick_init(void) { u8 buf[3]; u32 bytes_written; @@ -2284,7 +2379,7 @@ int stm32stick_init(void) } -int sheevaplug_init(void) +static int sheevaplug_init(void) { u8 buf[3]; u32 bytes_written; @@ -2335,7 +2430,7 @@ int sheevaplug_init(void) return ERROR_OK; } -void olimex_jtag_blink(void) +static void olimex_jtag_blink(void) { /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 * ACBUS3 is bit 3 of the GPIOH port @@ -2357,7 +2452,20 @@ void olimex_jtag_blink(void) } -void turtle_jtag_blink(void) +static void flyswatter_jtag_blink(void) +{ + /* + * Flyswatter has two LEDs connected to ACBUS2 and ACBUS3 + */ + high_output ^= 0x0c; + + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; +} + + +static void turtle_jtag_blink(void) { /* * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3 @@ -2377,7 +2485,7 @@ void turtle_jtag_blink(void) } -int ft2232_quit(void) +static int ft2232_quit(void) { #if BUILD_FT2232_FTD2XX == 1 FT_STATUS status; @@ -2398,11 +2506,31 @@ int ft2232_quit(void) } -int ft2232_handle_device_desc_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) +static int ft2232_handle_device_desc_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) { + char *cp; + char buf[200]; if (argc == 1) { ft2232_device_desc = strdup(args[0]); + cp = strchr( ft2232_device_desc, 0 ); + // under Win32, the FTD2XX driver appends an "A" to the end + // of the description, this examines the given desc + // and creates the 'missing' _A or non_A variable. + if( (cp[-1] == 'A') && (cp[-2]==' ') ){ + // it was, so make this the "A" version. + ft2232_device_desc_A = ft2232_device_desc; + // and *CREATE* the non-A version. + strcpy( buf, ft2232_device_desc ); + cp = strchr( buf, 0 ); + cp[-2] = 0; + ft2232_device_desc = strdup( buf ); + } else { + // A not defined + // so create it + sprintf( buf, "%s A", ft2232_device_desc ); + ft2232_device_desc_A = strdup( buf ); + } } else { @@ -2413,7 +2541,7 @@ int ft2232_handle_device_desc_command(struct command_context_s* cmd_ctx, char* c } -int ft2232_handle_serial_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) +static int ft2232_handle_serial_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) { if (argc == 1) { @@ -2428,7 +2556,7 @@ int ft2232_handle_serial_command(struct command_context_s* cmd_ctx, char* cmd, c } -int ft2232_handle_layout_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) +static int ft2232_handle_layout_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) { if (argc == 0) return ERROR_OK; @@ -2440,7 +2568,7 @@ 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) +static int ft2232_handle_vid_pid_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) { int i; @@ -2473,7 +2601,7 @@ int ft2232_handle_vid_pid_command(struct command_context_s* cmd_ctx, char* cmd, } -int ft2232_handle_latency_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) +static int ft2232_handle_latency_command(struct command_context_s* cmd_ctx, char* cmd, char** args, int argc) { if (argc == 1) { @@ -2527,3 +2655,105 @@ static int ft2232_stableclocks(int num_cycles, jtag_command_t* cmd) return retval; } + +/* --------------------------------------------------------------------- + * Support for IceBear JTAG adapter from Section5: + * http://section5.ch/icebear + * + * Author: Sten, debian@sansys-electronic.com + */ + +/* Icebear pin layout + * + * ADBUS5 (nEMU) nSRST | 2 1| GND (10k->VCC) + * GND GND | 4 3| n.c. + * ADBUS3 TMS | 6 5| ADBUS6 VCC + * ADBUS0 TCK | 8 7| ADBUS7 (GND) + * ADBUS4 nTRST |10 9| ACBUS0 (GND) + * ADBUS1 TDI |12 11| ACBUS1 (GND) + * ADBUS2 TDO |14 13| GND GND + * + * ADBUS0 O L TCK ACBUS0 GND + * ADBUS1 O L TDI ACBUS1 GND + * ADBUS2 I TDO ACBUS2 n.c. + * ADBUS3 O H TMS ACBUS3 n.c. + * ADBUS4 O H nTRST + * ADBUS5 O H nSRST + * ADBUS6 - VCC + * ADBUS7 - GND + */ +static int icebear_jtag_init(void) { + u8 buf[3]; + u32 bytes_written; + + low_direction = 0x0b; /* output: TCK TDI TMS; input: TDO */ + low_output = 0x08; /* high: TMS; low: TCK TDI */ + nTRST = 0x10; + nSRST = 0x20; + + if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) { + low_direction &= ~nTRST; /* nTRST high impedance */ + } + else { + low_direction |= nTRST; + low_output |= nTRST; + } + + low_direction |= nSRST; + 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) ) { + LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)"); + return ERROR_JTAG_INIT_FAILED; + } + + 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) ) { + LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +static void icebear_jtag_reset(int trst, int srst) { + + if (trst == 1) { + low_direction |= nTRST; + low_output &= ~nTRST; + } + else if (trst == 0) { + if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) + low_direction &= ~nTRST; + else + low_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; + LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); +}