jlink: improve USB read during jlink_tap_execute

Previously, when doing EMU_CMD_HW_JTAG3 commands we would do two reads,
one to read the data, and one to read the result. However, we can just
do a single larger read instead.

The motivation for this change is a weird problem. If I run the Segger
software before running OpenOCD, then the first read always fails:
Error: usb_bulk_read failed (requested=1, result=0)
Error: jlink_tap_execute, wrong result -107 (expected 1)

Sniffing the USB traffic shows that the J-Link is returning an
overflow error, meaning it is expecting to return the full result
in a single read.

Change-Id: I75e020d3b3732c9a74ee3d31838fdf17a7fac24c
Signed-off-by: Philip Craig <phil@blackmoth.com.au>
Reviewed-on: http://openocd.zylin.com/1447
Tested-by: jenkins
Reviewed-by: Xiaofan <xiaofanc@gmail.com>
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
Philip Craig 2013-06-17 13:56:33 +10:00 committed by Spencer Oliver
parent 322f7dccea
commit ff120440d6
1 changed files with 14 additions and 55 deletions

View File

@ -64,14 +64,12 @@ static unsigned int jlink_hw_jtag_version = 2;
/*#define JLINK_TAP_BUFFER_SIZE 256*/
/*#define JLINK_TAP_BUFFER_SIZE 384*/
#define JLINK_IN_BUFFER_SIZE 2048
#define JLINK_IN_BUFFER_SIZE (2048 + 1)
#define JLINK_OUT_BUFFER_SIZE (2*2048 + 4)
#define JLINK_EMU_RESULT_BUFFER_SIZE 64
/* Global USB buffers */
static uint8_t usb_in_buffer[JLINK_IN_BUFFER_SIZE];
static uint8_t usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
static uint8_t usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE];
/* Constants for JLink command */
#define EMU_CMD_VERSION 0x01
@ -231,7 +229,6 @@ static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length)
static int jlink_usb_io(struct jlink *jlink, int out_length, int in_length);
static int jlink_usb_write(struct jlink *jlink, int out_length);
static int jlink_usb_read(struct jlink *jlink, int expected_size);
static int jlink_usb_read_emu_result(struct jlink *jlink);
/* helper functions */
static int jlink_get_version_info(void);
@ -1421,10 +1418,17 @@ static int jlink_tap_execute(void)
jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer,
tap_length, jlink_last_state);
result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length, byte_length);
if (result != byte_length) {
LOG_ERROR("jlink_tap_execute, wrong result %d (expected %d)",
result, byte_length);
result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length,
use_jtag3 ? byte_length + 1 : byte_length);
if (result != ERROR_OK) {
LOG_ERROR("jlink_tap_execute failed USB io (%d)", result);
jlink_tap_init();
return ERROR_JTAG_QUEUE_FAILED;
}
result = use_jtag3 ? usb_in_buffer[byte_length] : 0;
if (result != 0) {
LOG_ERROR("jlink_tap_execute failed, result %d", result);
jlink_tap_init();
return ERROR_JTAG_QUEUE_FAILED;
}
@ -1539,44 +1543,12 @@ static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length)
}
result = jlink_usb_read(jlink, in_length);
if ((result != in_length) && (result != (in_length + 1))) {
if (result != in_length) {
LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)",
in_length, result);
return ERROR_JTAG_DEVICE_ERROR;
}
if (jlink_hw_jtag_version < 3)
return result;
int result2 = ERROR_OK;
if (result == in_length) {
/* Must read the result from the EMU too */
result2 = jlink_usb_read_emu_result(jlink);
if (1 != result2) {
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);
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 */
result2 = usb_emu_result_buffer[0];
} else {
/* Save the result, then remove it from return value */
result2 = usb_in_buffer[result--];
}
if (result2) {
LOG_ERROR("jlink_usb_message failed with result=%d)", result2);
return ERROR_JTAG_DEVICE_ERROR;
}
return result;
return ERROR_OK;
}
/* calls the given usb_bulk_* function, allowing for the data to
@ -1652,19 +1624,6 @@ static int jlink_usb_read(struct jlink *jlink, int expected_size)
return result;
}
/* Read the result from the previous EMU cmd into result_buffer. */
static int jlink_usb_read_emu_result(struct jlink *jlink)
{
int result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep,
(char *)usb_emu_result_buffer, 1 /* JLINK_EMU_RESULT_BUFFER_SIZE */,
JLINK_USB_TIMEOUT);
DEBUG_JTAG_IO("jlink_usb_read_result, result = %d", result);
jlink_debug_buffer(usb_emu_result_buffer, result);
return result;
}
/*
* Send a message and receive the reply - simple messages.
*