]> git.sur5r.net Git - openocd/blobdiff - src/jtag/jlink.c
Dick Hollenbeck <dick@softplc.com> and Jeff Williams tap_get_tms_path_len()
[openocd] / src / jtag / jlink.c
index 44a1ad6d723e402fbb15cbd6fd27b7c40cd18f15..028a36cf3b0bba46a792e7922a107dd2bb79e859 100644 (file)
@@ -44,7 +44,7 @@
 
 // See Section 1.3.2 of the Segger JLink USB protocol manual
 #define JLINK_IN_BUFFER_SIZE                   2048
-#define JLINK_OUT_BUFFER_SIZE                  2048
+#define JLINK_OUT_BUFFER_SIZE                  2*2048+4
 #define JLINK_EMU_RESULT_BUFFER_SIZE   64
 
 /* Global USB buffers */
@@ -53,14 +53,16 @@ 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_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
@@ -114,6 +116,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;
 
 /***************************************************************************/
@@ -329,6 +333,7 @@ static int jlink_init(void)
 
        jlink_reset(0, 0);
        jlink_tap_init();
+       jlink_speed(jtag_speed);
 
        return ERROR_OK;
 }
@@ -527,6 +532,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);
@@ -534,8 +540,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;
        }
 
@@ -543,14 +548,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;
 }
 
@@ -622,6 +654,10 @@ 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
@@ -660,52 +696,34 @@ 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)
-       {
-               /* 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);
-       }
-
-       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++)
        {
@@ -737,7 +755,6 @@ static int jlink_tap_execute(void)
        }
 
        jlink_tap_init();
-
        return ERROR_OK;
 }
 
@@ -811,7 +828,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);