X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fjlink.c;h=f984639b27e5d0f040fd37ac3e8efebd455a47d9;hp=022afe5fd4ee37d6f51d7fd5aea2c92d08cf71ec;hb=004c7124c44819960da97de85f422f630f04d7ba;hpb=f13f52d303d9f338bbb27f604ce57f4bb728f915 diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c index 022afe5fd4..f984639b27 100644 --- a/src/jtag/jlink.c +++ b/src/jtag/jlink.c @@ -25,14 +25,10 @@ #include "config.h" #endif -#include "replacements.h" - #include "jtag.h" #include -#include -#include "log.h" #define VID 0x1366 #define PID 0x0101 @@ -42,8 +38,9 @@ #define JLINK_USB_TIMEOUT 1000 -#define JLINK_IN_BUFFER_SIZE 8192 -#define JLINK_OUT_BUFFER_SIZE 8192 +// See Section 1.3.2 of the Segger JLink USB protocol manual +#define JLINK_IN_BUFFER_SIZE 2048 +#define JLINK_OUT_BUFFER_SIZE 2*2048+4 #define JLINK_EMU_RESULT_BUFFER_SIZE 64 /* Global USB buffers */ @@ -52,14 +49,19 @@ static u8 usb_out_buffer[JLINK_OUT_BUFFER_SIZE]; static u8 usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE]; /* Constants for JLink command */ -#define EMU_CMD_VERSION 0x01 -#define EMU_CMD_SET_SPEED 0x05 -#define EMU_CMD_GET_STATE 0x07 -#define EMU_CMD_HW_JTAG3 0xcf -#define EMU_CMD_HW_RESET0 0xdc -#define EMU_CMD_HW_RESET1 0xdd -#define EMU_CMD_HW_TRST0 0xde -#define EMU_CMD_HW_TRST1 0xdf +#define EMU_CMD_VERSION 0x01 +#define EMU_CMD_SET_SPEED 0x05 +#define EMU_CMD_GET_STATE 0x07 +#define EMU_CMD_HW_CLOCK 0xc8 +#define EMU_CMD_HW_TMS0 0xc9 +#define EMU_CMD_HW_TMS1 0xca +#define EMU_CMD_HW_JTAG3 0xcf +#define EMU_CMD_GET_MAX_MEM_BLOCK 0xd4 +#define EMU_CMD_HW_RESET0 0xdc +#define EMU_CMD_HW_RESET1 0xdd +#define EMU_CMD_HW_TRST0 0xde +#define EMU_CMD_HW_TRST1 0xdf +#define EMU_CMD_GET_CAPS 0xe8 /* max speed 12MHz v5.0 jlink */ #define JLINK_MAX_SPEED 12000 @@ -113,6 +115,8 @@ static int jlink_get_version_info(void); static void jlink_debug_buffer(u8 *buffer, int length); #endif +static enum tap_state jlink_last_state = TAP_RESET; + static jlink_jtag_t* jlink_jtag_handle; /***************************************************************************/ @@ -177,7 +181,7 @@ static void jlink_execute_scan(jtag_command_t *cmd) enum scan_type type; u8 *buffer; - DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state); + DEBUG_JTAG_IO("scan end in %s", tap_state_name(cmd->cmd.scan->end_state)); if (cmd->cmd.scan->end_state != TAP_INVALID) jlink_end_state(cmd->cmd.scan->end_state); @@ -200,10 +204,13 @@ static void jlink_execute_reset(jtag_command_t *cmd) jlink_tap_execute(); - if (cmd->cmd.reset->trst == 1) + if ( (cmd->cmd.reset->trst == 1) || ( cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST) ) ) + { tap_set_state(TAP_RESET); + } jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + jlink_tap_execute(); } static void jlink_execute_sleep(jtag_command_t *cmd) @@ -327,7 +334,9 @@ static int jlink_init(void) LOG_INFO("J-Link JTAG Interface ready"); jlink_reset(0, 0); + jtag_sleep(3000); jlink_tap_init(); + jlink_speed(jtag_speed); return ERROR_OK; } @@ -360,8 +369,9 @@ static void jlink_state_move(void) int i; int tms = 0; u8 tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); + u8 tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - for (i = 0; i < 7; i++) + for (i = 0; i < tms_scan_bits; i++) { tms = (tms_scan >> i) & 1; jlink_tap_append_step(tms, 0); @@ -407,6 +417,7 @@ static void jlink_runtest(int num_cycles) { jlink_end_state(TAP_IDLE); jlink_state_move(); +// num_cycles--; } /* execute num_cycles */ @@ -463,18 +474,21 @@ static void jlink_reset(int trst, int srst) { jlink_simple_command(EMU_CMD_HW_RESET1); } - else if (srst == 1) + if (srst == 1) { jlink_simple_command(EMU_CMD_HW_RESET0); } - if (trst == 0) + if (trst == 1) { - jlink_simple_command(EMU_CMD_HW_TRST1); + jlink_simple_command(EMU_CMD_HW_TRST0); } - else if (trst == 1) + if (trst == 0) { - jlink_simple_command(EMU_CMD_HW_TRST0); + jlink_simple_command(EMU_CMD_HW_TRST1); + jtag_sleep(5000); + jlink_end_state(TAP_RESET); + jlink_state_move(); } } @@ -522,6 +536,7 @@ static int jlink_get_version_info(void) { int result; int len; + u32 jlink_caps, jlink_max_size; /* query hardware version */ jlink_simple_command(EMU_CMD_VERSION); @@ -529,8 +544,7 @@ static int jlink_get_version_info(void) result = jlink_usb_read(jlink_jtag_handle, 2); if (2 != result) { - LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", - result); + LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", result); return ERROR_JTAG_DEVICE_ERROR; } @@ -538,14 +552,41 @@ static int jlink_get_version_info(void) result = jlink_usb_read(jlink_jtag_handle, len); if (result != len) { - LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", - result); + LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", result); return ERROR_JTAG_DEVICE_ERROR; } usb_in_buffer[result] = 0; LOG_INFO("%s", (char *)usb_in_buffer); + /* query hardware capabilities */ + jlink_simple_command(EMU_CMD_GET_CAPS); + + result = jlink_usb_read(jlink_jtag_handle, 4); + if (4 != result) + { + LOG_ERROR("J-Link command EMU_CMD_GET_CAPS failed (%d)\n", result); + return ERROR_JTAG_DEVICE_ERROR; + } + + jlink_caps = buf_get_u32(usb_in_buffer, 0, 32); + LOG_INFO("JLink caps 0x%x", jlink_caps); + + + /* query hardware maximum memory block */ + jlink_simple_command(EMU_CMD_GET_MAX_MEM_BLOCK); + + result = jlink_usb_read(jlink_jtag_handle, 4); + if (4 != result) + { + LOG_ERROR("J-Link command EMU_CMD_GET_MAX_MEM_BLOCK failed (%d)\n", result); + return ERROR_JTAG_DEVICE_ERROR; + } + + jlink_max_size = buf_get_u32(usb_in_buffer, 0, 32); + LOG_INFO("JLink max mem block %i", jlink_max_size); + + return ERROR_OK; } @@ -564,9 +605,9 @@ static int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, ch /* J-Link tap functions */ /* 2048 is the max value we can use here */ -#define JLINK_TAP_BUFFER_SIZE 2048 +#define JLINK_TAP_BUFFER_SIZE 1024 -static unsigned tap_length; +static unsigned tap_length=0; static u8 tms_buffer[JLINK_TAP_BUFFER_SIZE]; static u8 tdi_buffer[JLINK_TAP_BUFFER_SIZE]; static u8 tdo_buffer[JLINK_TAP_BUFFER_SIZE]; @@ -584,8 +625,6 @@ typedef struct static int pending_scan_results_length; static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; -static int last_tms; - static void jlink_tap_init(void) { tap_length = 0; @@ -595,7 +634,7 @@ static void jlink_tap_init(void) static void jlink_tap_ensure_space(int scans, int bits) { int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length; - int available_bits = JLINK_TAP_BUFFER_SIZE * 8 - tap_length; + int available_bits = JLINK_TAP_BUFFER_SIZE * 8 - tap_length - 64; if (scans > available_scans || bits > available_bits) { @@ -605,7 +644,6 @@ static void jlink_tap_ensure_space(int scans, int bits) static void jlink_tap_append_step(int tms, int tdi) { - last_tms = tms; int index = tap_length / 8; if (index >= JLINK_TAP_BUFFER_SIZE) @@ -617,6 +655,12 @@ static void jlink_tap_append_step(int tms, int tdi) int bit_index = tap_length % 8; u8 bit = 1 << bit_index; + // we do not pad TMS, so be sure to initialize all bits + if (0 == bit_index) + { + tms_buffer[index] = tdi_buffer[index] = 0; + } + if (tms) tms_buffer[index] |= bit; else @@ -643,8 +687,8 @@ static void jlink_tap_append_scan(int length, u8 *buffer, scan_command_t *comman for (i = 0; i < length; i++) { - int tms = i < length - 1 ? 0 : 1; - int tdi = buffer[i / 8] & (1 << (i % 8)); + int tms = (i < (length - 1)) ? 0 : 1; + int tdi = (buffer[i / 8] & (1 << (i % 8)))!=0; jlink_tap_append_step(tms, tdi); } pending_scan_results_length++; @@ -655,52 +699,41 @@ static void jlink_tap_append_scan(int length, u8 *buffer, scan_command_t *comman static int jlink_tap_execute(void) { int byte_length; - int tms_offset; - int tdi_offset; int i; int result; if (!tap_length) return ERROR_OK; - /* Pad last byte so that tap_length is divisible by 8 */ - while (tap_length % 8 != 0) + /* JLink returns an extra NULL in packet when size of in message is a multiple of 64, creates problems with usb comms */ + /* WARNING This will interfere with tap state counting */ + while ((TAP_SCAN_BYTES(tap_length)%64)==0) { - /* More of the last TMS value keeps us in the same state, - * analogous to free-running JTAG interfaces. */ - jlink_tap_append_step(last_tms, 0); + jlink_tap_append_step((tap_get_state() == TAP_RESET)?1:0, 0); } - byte_length = tap_length / 8; + // number of full bytes (plus one if some would be left over) + byte_length = TAP_SCAN_BYTES(tap_length); usb_out_buffer[0] = EMU_CMD_HW_JTAG3; usb_out_buffer[1] = 0; usb_out_buffer[2] = (tap_length >> 0) & 0xff; usb_out_buffer[3] = (tap_length >> 8) & 0xff; + memcpy(usb_out_buffer + 4, tms_buffer, byte_length); + memcpy(usb_out_buffer + 4 + byte_length, tdi_buffer, byte_length); - tms_offset = 4; - for (i = 0; i < byte_length; i++) - { - usb_out_buffer[tms_offset + i] = tms_buffer[i]; - } - - tdi_offset = tms_offset + byte_length; - for (i = 0; i < byte_length; i++) - { - usb_out_buffer[tdi_offset + i] = tdi_buffer[i]; - } + jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer, + tap_length, jlink_last_state); result = jlink_usb_message(jlink_jtag_handle, 4 + 2 * byte_length, byte_length); - if (result != byte_length) { - LOG_ERROR("jlink_tap_execute, wrong result %d (expected %d)", - result, byte_length); + LOG_ERROR("jlink_tap_execute, wrong result %d (expected %d)", result, byte_length); + jlink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } - for (i = 0; i < byte_length; i++) - tdo_buffer[i] = usb_in_buffer[i]; + memcpy(tdo_buffer, usb_in_buffer, byte_length); for (i = 0; i < pending_scan_results_length; i++) { @@ -732,7 +765,6 @@ static int jlink_tap_execute(void) } jlink_tap_init(); - return ERROR_OK; } @@ -806,7 +838,7 @@ static int jlink_usb_message(jlink_jtag_t *jlink_jtag, int out_length, int in_le } result = jlink_usb_read(jlink_jtag, in_length); - if ((result != in_length) && (result != in_length + 1)) + if ((result != in_length) && (result != (in_length + 1))) { LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result); @@ -819,9 +851,15 @@ static int jlink_usb_message(jlink_jtag_t *jlink_jtag, int out_length, int in_le result2 = jlink_usb_read_emu_result(jlink_jtag); if (1 != result2) { - LOG_ERROR("jlink_usb_read_emu_result failed " - "(requested=1, result=%d)", result2); - return ERROR_JTAG_DEVICE_ERROR; + LOG_ERROR("jlink_usb_read_emu_result retried requested=1, result=%d, in_length=%i", result2,in_length); + /* Try again once, should only happen if (in_length%64==0) */ + result2 = jlink_usb_read_emu_result(jlink_jtag); + if (1 != result2) + { + LOG_ERROR("jlink_usb_read_emu_result failed " + "(requested=1, result=%d)", result2); + return ERROR_JTAG_DEVICE_ERROR; + } } /* Check the result itself */ @@ -848,28 +886,33 @@ static int usb_bulk_with_retries( usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { - int rc = 0, tries = 3, this_size; + int tries = 3, count = 0; - while (tries && size) { - - this_size = f(dev, ep, bytes, size, timeout); - if (this_size > 0) { - - size -= this_size; - rc += this_size; - bytes += this_size; - - } else - tries --; + while (tries && (count < size)) + { + int result = f(dev, ep, bytes + count, size - count, timeout); + if (result > 0) + count += result; + else if ((-ETIMEDOUT != result) || !--tries) + return result; } - return rc; + return count; } + +static int wrap_usb_bulk_write(usb_dev_handle *dev, int ep, + char *buff, int size, int timeout) +{ + /* usb_bulk_write() takes const char *buff */ + return usb_bulk_write(dev, ep, buff, size, timeout); +} + static inline int usb_bulk_write_ex(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { - return usb_bulk_with_retries(&usb_bulk_write, + return usb_bulk_with_retries(&wrap_usb_bulk_write, dev, ep, bytes, size, timeout); } + static inline int usb_bulk_read_ex(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { @@ -950,3 +993,4 @@ static void jlink_debug_buffer(u8 *buffer, int length) } } #endif +