#include "config.h"
#endif
-#include "replacements.h"
-
#include "jtag.h"
#include <usb.h>
-#include <string.h>
-#include "log.h"
#define VID 0x1366
#define PID 0x0101
#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 */
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
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;
/***************************************************************************/
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);
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)
LOG_INFO("J-Link JTAG Interface ready");
jlink_reset(0, 0);
+ jtag_sleep(3000);
jlink_tap_init();
+ jlink_speed(jtag_speed);
return ERROR_OK;
}
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);
{
jlink_end_state(TAP_IDLE);
jlink_state_move();
+// num_cycles--;
}
/* execute num_cycles */
{
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();
}
}
{
int result;
int len;
+ u32 jlink_caps, jlink_max_size;
/* query hardware version */
jlink_simple_command(EMU_CMD_VERSION);
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;
}
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;
}
/* 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];
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;
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)
{
static void jlink_tap_append_step(int tms, int tdi)
{
- last_tms = tms;
int index = tap_length / 8;
if (index >= JLINK_TAP_BUFFER_SIZE)
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
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++;
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++)
{
}
jlink_tap_init();
-
return ERROR_OK;
}
}
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);
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 */
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)
{
}
}
#endif
+