X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fft2232.c;h=096111bc8e0fbcc123c41db7c7a93d290089d466;hp=862003f5b292cbaeb1b5bee92ac4e14218278919;hb=e9297b40b994f071474210e7d9e224d50e25fcaf;hpb=15294929e299c2e06282723c12965da2de14327a diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index 862003f5b2..096111bc8e 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -52,13 +52,13 @@ /* enable this to debug io latency */ -#if 0 +#if 1 #define _DEBUG_USB_IO_ #endif /* enable this to debug communication */ -#if 0 +#if 1 #define _DEBUG_USB_COMMS_ #endif @@ -70,10 +70,12 @@ 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); char *ft2232_device_desc = NULL; +char *ft2232_serial = NULL; char *ft2232_layout = NULL; u16 ft2232_vid = 0x0403; u16 ft2232_pid = 0x6010; @@ -83,19 +85,34 @@ typedef struct ft2232_layout_s char* name; int(*init)(void); void(*reset)(int trst, int srst); + void(*blink)(void); } ft2232_layout_t; +/* init procedures for supported layouts */ int usbjtag_init(void); int jtagkey_init(void); +int olimex_jtag_init(void); +int m5960_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 m5960_reset(int trst, int srst); + +/* blink procedures for layouts that support a blinking led */ +void olimex_jtag_blink(void); ft2232_layout_t ft2232_layouts[] = { - {"usbjtag", usbjtag_init, usbjtag_reset}, - {"jtagkey", jtagkey_init, jtagkey_reset}, - {"jtagkey_prototype_v1", jtagkey_init, jtagkey_reset}, - {"signalyzer", usbjtag_init, usbjtag_reset}, + {"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}, + {"m5960", m5960_init, m5960_reset, NULL}, {NULL, NULL, NULL}, }; @@ -128,7 +145,7 @@ jtag_interface_t ft2232_interface = .execute_queue = ft2232_execute_queue, - .support_statemove = 1, + .support_pathmove = 1, .speed = ft2232_speed, .register_commands = ft2232_register_commands, @@ -173,15 +190,19 @@ 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, size, &dw_bytes_read)) != FT_OK) + { + *bytes_read = 0; + ERROR("FT_Read returned: %i", 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; @@ -197,8 +218,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) @@ -225,6 +253,8 @@ 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, @@ -440,7 +470,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; @@ -461,8 +491,9 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size } /* 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 */ @@ -481,24 +512,206 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size BUFFER_ADD = 0x28; //DEBUG("added TDI bytes (i %i)", num_bytes); } - BUFFER_ADD = (num_bytes-2) & 0xff; - BUFFER_ADD = ((num_bytes-2) >> 8) & 0xff; + 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); + } } + + /* 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; } - if (type == SCAN_IN) + else { - bits_left -= 8 * (num_bytes - 1); + /* 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 ((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; + + /* 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; @@ -529,30 +742,83 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size 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; @@ -560,14 +826,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; } @@ -674,6 +940,68 @@ void jtagkey_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); } +void olimex_jtag_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + high_output &= ~nTRSTnOE; + else + high_output &= ~nTRST; + } + else if (trst == 0) + { + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + high_output |= nTRSTnOE; + else + 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 m5960_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + low_output &= ~nTRST; + } + else if (trst == 0) + { + 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; + 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 */ @@ -687,6 +1015,10 @@ int ft2232_execute_queue() ft2232_buffer_size = 0; ft2232_expect_read = 0; + + /* blink, if the current layout has that feature */ + if (layout->blink) + layout->blink(); while (cmd) { @@ -814,9 +1146,26 @@ 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("ftd2xx buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd); + DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); + /* unsent commands before this */ + if (first_unsent != cmd) + ft2232_send_and_recv(first_unsent, cmd); + + /* 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("ft2232 buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd); ft2232_send_and_recv(first_unsent, cmd); require_send = 0; first_unsent = cmd; @@ -863,6 +1212,8 @@ int ft2232_init(void) #if BUILD_FT2232_FTD2XX == 1 FT_STATUS status; + DWORD openex_flags = 0; + char *openex_string = NULL; #endif ft2232_layout_t *cur_layout = ft2232_layouts; @@ -896,13 +1247,6 @@ int ft2232_init(void) #endif #if BUILD_FT2232_FTD2XX == 1 - /* Open by device description */ - if (ft2232_device_desc == NULL) - { - WARNING("no ftd2xx device description specified, using default 'Dual RS232'"); - ft2232_device_desc = "Dual RS232"; - } - #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ if ((status = FT_SetVIDPID(ft2232_vid, ft2232_pid)) != FT_OK) @@ -911,7 +1255,31 @@ int ft2232_init(void) } #endif - if ((status = FT_OpenEx(ft2232_device_desc, FT_OPEN_BY_DESCRIPTION, &ftdih)) != FT_OK) + if (ft2232_device_desc && ft2232_serial) + { + WARNING("can't open by device description and serial number, giving precedence to serial"); + ft2232_device_desc = NULL; + } + + if (ft2232_device_desc) + { + 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; + } + + if ((status = FT_OpenEx(openex_string, openex_flags, &ftdih)) != FT_OK) { DWORD num_devices; @@ -926,7 +1294,7 @@ 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) { @@ -961,6 +1329,12 @@ int ft2232_init(void) { DEBUG("current latency timer: %i", latency_timer); } + + if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK) + { + ERROR("unable to set timeouts: %i", status); + return ERROR_JTAG_INIT_FAILED; + } if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK) { @@ -1061,6 +1435,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); @@ -1131,7 +1514,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; @@ -1170,7 +1554,73 @@ int jtagkey_init(void) } /* initialize high port */ - buf[0] = 0x82; /* command "set data bits low byte" */ + 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 'JTAGkey' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int olimex_jtag_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x08; + low_direction = 0x1b; + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ + 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 'JTAGkey' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x01; + nTRSTnOE = 0x4; + nSRST = 0x02; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + high_output = 0x0; + high_direction = 0x0f; + + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + { + high_output |= nTRSTnOE; + high_output &= ~nTRST; + } + else + { + high_output &= ~nTRSTnOE; + high_output |= nTRST; + } + + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + { + ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD"); + } + else + { + high_output &= ~nSRST; + } + + /* turn red LED on */ + high_output |= 0x08; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ buf[1] = high_output; /* value */ buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); @@ -1184,6 +1634,73 @@ int jtagkey_init(void) return ERROR_OK; } +int m5960_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 'm5960' 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 'm5960' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +void olimex_jtag_blink(void) +{ + /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 + * ACBUS3 is bit 3 of the GPIOH port + */ + if (high_output & 0x08) + { + /* set port pin high */ + high_output &= 0x07; + } + else + { + /* set port pin low */ + high_output |= 0x08; + } + + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; +} + int ft2232_quit(void) { #if BUILD_FT2232_FTD2XX == 1 @@ -1217,6 +1734,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)