- added jlink support, based on Jürgen Stuber patch
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 14 May 2008 14:13:38 +0000 (14:13 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 14 May 2008 14:13:38 +0000 (14:13 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@658 b42882b7-edfa-0310-969c-e2dbd0fdcd60

configure.in
doc/openocd.texi
src/Makefile.am
src/jtag/Makefile.am
src/jtag/jlink.c [new file with mode: 0644]
src/jtag/jtag.c
src/target/Makefile.am
src/target/interface/jlink.cfg [new file with mode: 0644]

index ae35f555b643e9e883fcd0423db1b6da992d2fc4..eebbc37643c85d4a36a10cdf294e02289a4e091b 100644 (file)
@@ -99,6 +99,10 @@ AC_ARG_ENABLE(oocd_trace,
   AS_HELP_STRING([--enable-oocd_trace], [Enable building support for the OpenOCD+trace ETM capture device]),
   [build_oocd_trace=$enableval], [build_oocd_trace=no])
 
+AC_ARG_ENABLE(jlink,
+  AS_HELP_STRING([--enable-jlink], [Enable building support for the Segger J-Link JTAG Programmer]),
+  [build_jlink=$enableval], [build_jlink=no])
+
 AC_ARG_WITH(ftd2xx,
         [AS_HELP_STRING(--with-ftd2xx,
            [Where libftd2xx can be found <default=search>])],
@@ -251,6 +255,12 @@ else
   AC_DEFINE(BUILD_OOCD_TRACE, 0, [0 if you don't want the OpenOCD+trace ETM capture driver.])
 fi
 
+if test $build_jlink = yes; then
+  AC_DEFINE(BUILD_JLINK, 1, [1 if you want the J-Link JTAG driver.])
+else
+  AC_DEFINE(BUILD_JLINK, 0, [0 if you don't want the J-Link JTAG driver.])
+fi
+
 AM_CONFIG_HEADER(config.h)
 AM_INIT_AUTOMAKE(openocd, 1.0)
 
@@ -269,6 +279,7 @@ AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)
 AM_CONDITIONAL(PRESTO_FTD2XX, test $build_presto_ftd2xx = yes)
 AM_CONDITIONAL(USBPROG, test $build_usbprog = yes)
 AM_CONDITIONAL(OOCD_TRACE, test $build_oocd_trace = yes)
+AM_CONDITIONAL(JLINK, test $build_jlink = yes)
 AM_CONDITIONAL(IS_CYGWIN, test $is_cygwin = yes)
 AM_CONDITIONAL(IS_MINGW, test $is_mingw = yes)
 AM_CONDITIONAL(IS_WIN32, test $is_win32 = yes)
index 7f13f042726e8f1b24401480cf81fd0dcf977aa3..c9bbed7ce4d25443adf9f2f6c1c2334659e1e1a8 100644 (file)
@@ -176,6 +176,8 @@ build properly.}
 @option{--enable-presto_libftdi}
 @item
 @option{--enable-presto_ftd2xx}
+@item
+@option{--enable-jlink}
 @end itemize
 
 If you want to access the parallel port using the PPDEV interface you have to specify
@@ -259,7 +261,7 @@ Set to <@var{enable}> to cause OpenOCD to send the memory configuration to gdb w
 requested. gdb will then know when to set hardware breakpoints, and program flash
 using the gdb load command. @option{gdb_flash_program enable} will also need enabling
 for flash programming to work.
-Default behaviour is <@var{disable}>
+Default behaviour is <@var{enable}>
 @item @b{gdb_flash_program} <@var{enable|disable}>
 @cindex gdb_flash_program
 Set to <@var{enable}> to cause OpenOCD to program the flash memory when a
@@ -312,6 +314,10 @@ usbprog is a freely programmable USB adapter.
 @item @b{gw16012}
 Gateworks GW16012 JTAG programmer.
 @end itemize
+@itemize @minus
+@item @b{jlink}
+Segger jlink usb adapter
+@end itemize
 @end itemize
 
 @itemize @bullet
@@ -326,6 +332,7 @@ is optional, in which case the reset speed is used.
 @item wiggler: maximum speed / @var{number}
 @item ft2232: 6MHz / (@var{number}+1)
 @item amt jtagaccel: 8 / 2**@var{number}
+@item jlink: maximum speed in kHz (0-12000), 0 will use RTCK
 @end itemize
 
 Note: Make sure the jtag clock is no more than @math{1/6th × CPU-Clock}. This is
index d575fbde0e896f49b69069eee7c70c7c87a1c0bc..4cfabb399e9cd9c67bd324ab3480768be8de5663 100644 (file)
@@ -44,8 +44,12 @@ endif
 if USBPROG
 LIBUSB = -lusb
 else
+if JLINK
+LIBUSB = -lusb
+else
 LIBUSB =
 endif
+endif
 
 if IS_WIN32
 if FTD2XXDIR
index d37a91817b1ac5c8c67bd2055f83b3403f3be90b..0b40ab2339d598b07cfa719a8a8b7140696040cd 100644 (file)
@@ -93,7 +93,13 @@ else
 USBPROGFILES =
 endif
 
+if JLINK
+JLINKFILES = jlink.c
+else
+JLINKFILES =
+endif
+
 libjtag_a_SOURCES = jtag.c $(BITBANGFILES) $(PARPORTFILES) $(DUMMYFILES) $(FT2232FILES) $(AMTJTAGACCELFILES) $(EP93XXFILES) \
-       $(AT91RM9200FILES) $(GW16012FILES) $(BITQFILES) $(PRESTOFILES) $(USBPROGFILES) $(ECOSBOARDFILES)
+       $(AT91RM9200FILES) $(GW16012FILES) $(BITQFILES) $(PRESTOFILES) $(USBPROGFILES) $(ECOSBOARDFILES) $(JLINKFILES)
 
 noinst_HEADERS = bitbang.h jtag.h
diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c
new file mode 100644 (file)
index 0000000..81ede79
--- /dev/null
@@ -0,0 +1,846 @@
+/***************************************************************************
+ *   Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net>            *
+ *   based on Dominic Rath's and Benedikt Sauter's usbprog.c               *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "jtag.h"
+
+#include <usb.h>
+#include <string.h>
+
+#include "log.h"
+
+/* enable this to debug communication
+ */
+#if 0
+#define _DEBUG_USB_COMMS_
+#endif
+
+#ifdef _DEBUG_JTAG_IO_
+#define DEBUG_JTAG_IO(expr ...)        LOG_DEBUG(expr)
+#else
+#define DEBUG_JTAG_IO(expr ...)
+#endif
+
+#define VID 0x1366
+#define PID 0x0101
+
+#define JLINK_WRITE_ENDPOINT   0x02
+#define JLINK_READ_ENDPOINT            0x81
+
+#define JLINK_USB_TIMEOUT              100
+
+#define JLINK_IN_BUFFER_SIZE   2064
+#define JLINK_OUT_BUFFER_SIZE  2064
+
+/* Global USB buffers */
+static u8 usb_in_buffer[JLINK_IN_BUFFER_SIZE];
+static u8 usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
+
+/* Constants for JLink command */
+#define JLINK_FIRMWARE_VERSION                 0x01
+#define JLINK_SPEED_COMMAND                            0x05
+#define JLINK_GET_STATUS_COMMAND               0x07
+#define JLINK_TAP_SEQUENCE_COMMAND             0xcd
+#define JLINK_GET_SERIAL                               0xe6
+#define JLINK_SET_SRST_LOW_COMMAND             0xdc
+#define JLINK_SET_SRST_HIGH_COMMAND            0xdd
+#define JLINK_SET_TRST_LOW_COMMAND             0xde
+#define JLINK_SET_TRST_HIGH_COMMAND            0xdf
+#define JLINK_HARDWARE_VERSION                 0xe8
+
+/* max speed 12MHz v5.0 jlink */
+#define JLINK_MAX_SPEED 12000
+
+/* External interface functions */
+int jlink_execute_queue(void);
+int jlink_speed(int speed);
+int jlink_khz(int khz, int *jtag_speed);
+int jlink_register_commands(struct command_context_s *cmd_ctx);
+int jlink_init(void);
+int jlink_quit(void);
+
+/* CLI command handler functions */
+int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* Queue command functions */
+void jlink_end_state(enum tap_state state);
+void jlink_state_move(void);
+void jlink_path_move(int num_states, enum tap_state *path);
+void jlink_runtest(int num_cycles);
+void jlink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, scan_command_t *command);
+void jlink_reset(int trst, int srst);
+void jlink_simple_command(u8 command);
+int jlink_get_status(void);
+
+/* J-Link tap buffer functions */
+void jlink_tap_init();
+int jlink_tap_execute();
+void jlink_tap_ensure_space(int scans, int bits);
+void jlink_tap_append_step(int tms, int tdi);
+void jlink_tap_append_scan(int length, u8 *buffer, scan_command_t *command);
+
+/* Jlink lowlevel functions */
+typedef struct jlink_jtag
+{
+       struct usb_dev_handle* usb_handle;
+} jlink_jtag_t;
+
+jlink_jtag_t *jlink_usb_open(void);
+void jlink_usb_close(jlink_jtag_t *jlink_jtag);
+int jlink_usb_message(jlink_jtag_t *jlink_jtag, int out_length, int in_length);
+int jlink_usb_write(jlink_jtag_t *jlink_jtag, int out_length);
+int jlink_usb_read(jlink_jtag_t *jlink_jtag);
+
+#ifdef _DEBUG_USB_COMMS_
+void jlink_debug_buffer(u8 *buffer, int length);
+#endif
+
+jlink_jtag_t* jlink_jtag_handle;
+
+/***************************************************************************/
+/* External interface implementation */
+
+jtag_interface_t jlink_interface =
+{
+       .name = "jlink",
+       .execute_queue = jlink_execute_queue,
+       .speed = jlink_speed,
+       .khz = jlink_khz,
+       .register_commands = jlink_register_commands,
+       .init = jlink_init,
+       .quit = jlink_quit
+};
+
+int jlink_execute_queue(void)
+{
+       jtag_command_t *cmd = jtag_command_queue;
+       int scan_size;
+       enum scan_type type;
+       u8 *buffer;
+       
+       while (cmd != NULL)
+       {
+               switch (cmd->type)
+               {
+                       case JTAG_END_STATE:
+                               DEBUG_JTAG_IO("end_state: %i", cmd->cmd.end_state->end_state);
+                       
+                               if (cmd->cmd.end_state->end_state != -1)
+                               {
+                                       jlink_end_state(cmd->cmd.end_state->end_state);
+                               }
+                               break;
+       
+                       case JTAG_RUNTEST:
+                               DEBUG_JTAG_IO( "runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \
+                                       cmd->cmd.runtest->end_state);
+                               
+                               if (cmd->cmd.runtest->end_state != -1)
+                               {
+                                       jlink_end_state(cmd->cmd.runtest->end_state);
+                               }
+                               jlink_runtest(cmd->cmd.runtest->num_cycles);
+                               break;
+       
+                       case JTAG_STATEMOVE:
+                               DEBUG_JTAG_IO("statemove end in %i",
+                               cmd->cmd.statemove->end_state);
+                       
+                               if (cmd->cmd.statemove->end_state != -1)
+                               {
+                                       jlink_end_state(cmd->cmd.statemove->end_state);
+                               }
+                               jlink_state_move();
+                               break;
+       
+                       case JTAG_PATHMOVE:
+                           DEBUG_JTAG_IO("pathmove: %i states, end in %i",
+                               cmd->cmd.pathmove->num_states,
+                               cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+                       
+                               jlink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
+                               break;
+       
+                       case JTAG_SCAN:
+                               DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state);
+                       
+                               if (cmd->cmd.scan->end_state != -1)
+                               {
+                                   jlink_end_state(cmd->cmd.scan->end_state);
+                               }
+                       
+                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+                               DEBUG_JTAG_IO("scan input, length = %d", scan_size);
+                               
+#ifdef _DEBUG_USB_COMMS_
+                               jlink_debug_buffer(buffer, (scan_size + 7) / 8);
+#endif
+                               type = jtag_scan_type(cmd->cmd.scan);
+                               jlink_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
+                               break;
+       
+                       case JTAG_RESET:
+                               DEBUG_JTAG_IO("reset trst: %i srst %i",
+                               cmd->cmd.reset->trst,
+                               cmd->cmd.reset->srst);
+                       
+                               jlink_tap_execute();
+                       
+                               if (cmd->cmd.reset->trst == 1)
+                               {
+                                       cur_state = TAP_TLR;
+                               }
+                               jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+                               break;
+       
+                       case JTAG_SLEEP:
+                               DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us);
+                               jlink_tap_execute();
+                               jtag_sleep(cmd->cmd.sleep->us);
+                               break;
+       
+               default:
+                       LOG_ERROR("BUG: unknown JTAG command type encountered");
+                       exit(-1);
+               }
+               cmd = cmd->next;
+       }
+       jlink_tap_execute();
+       
+       return ERROR_OK;
+}
+
+/* Sets speed in kHz. */
+int jlink_speed(int speed)
+{
+       int result;
+       
+//     if ((speed == -1) || ((1 <= speed) && (speed <= JLINK_MAX_SPEED)))
+       if (speed <= JLINK_MAX_SPEED)
+       {
+               /* check for RTCK setting */
+               if (speed == 0)
+                       speed = -1;
+               
+               usb_out_buffer[0] = JLINK_SPEED_COMMAND;
+               usb_out_buffer[1] = (speed >> 0) & 0xff;
+               usb_out_buffer[2] = (speed >> 8) & 0xff;
+               
+               result = jlink_usb_write(jlink_jtag_handle, 3);
+               
+               if (result == 3)
+               {
+                       return ERROR_OK;
+               }
+               else
+               {
+                       LOG_ERROR("J-Link setting speed failed (%d)", result);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+       }
+       else
+       {
+               LOG_INFO("Requested speed %dkHz exceeds maximum of %dkHz, ignored", speed, JLINK_MAX_SPEED);
+       }
+       
+       return ERROR_OK;
+}
+
+int jlink_khz(int khz, int *jtag_speed)
+{
+       *jtag_speed = khz;
+       
+       return ERROR_OK;
+}
+
+int jlink_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "jlink_info", jlink_handle_jlink_info_command, COMMAND_EXEC,
+               "query jlink info");
+       return ERROR_OK;
+}
+
+int jlink_init(void)
+{
+       int result;
+       
+       jlink_jtag_handle = jlink_usb_open();
+       
+       if (jlink_jtag_handle == 0)
+       {
+               LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+               
+       result = jlink_usb_read(jlink_jtag_handle);
+       if (result != 2 || usb_in_buffer[0] != 0x07 || usb_in_buffer[1] != 0x00)
+       {
+               LOG_INFO("J-Link initial read failed, don't worry");
+       }
+       
+       LOG_INFO("J-Link JTAG Interface ready");
+       
+       jlink_reset(0, 0);
+       jlink_tap_init();
+       
+       /* query jlink status */
+       jlink_get_status();
+       
+       return ERROR_OK;
+}
+
+int jlink_quit(void)
+{
+       jlink_usb_close(jlink_jtag_handle);
+       return ERROR_OK;
+}
+
+/***************************************************************************/
+/* Queue command implementations */
+
+void jlink_end_state(enum tap_state state)
+{
+       if (tap_move_map[state] != -1)
+       {
+               end_state = state;
+       }
+       else
+       {
+               LOG_ERROR("BUG: %i is not a valid end state", state);
+               exit(-1);
+       }
+}
+
+/* Goes to the end state. */
+void jlink_state_move(void)
+{
+       int i;
+       int tms = 0;
+       u8 tms_scan = TAP_MOVE(cur_state, end_state);
+       
+       for (i = 0; i < 7; i++)
+       {
+               tms = (tms_scan >> i) & 1;
+               jlink_tap_append_step(tms, 0);
+       }
+       
+       cur_state = end_state;
+}
+
+void jlink_path_move(int num_states, enum tap_state *path)
+{
+       int i;
+       
+       for (i = 0; i < num_states; i++)
+       {
+               if (path[i] == tap_transitions[cur_state].low)
+               {
+                       jlink_tap_append_step(0, 0);
+               }
+               else if (path[i] == tap_transitions[cur_state].high)
+               {
+                       jlink_tap_append_step(1, 0);
+               }
+               else
+               {
+                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[path[i]]);
+                       exit(-1);
+               }
+               
+               cur_state = path[i];
+       }
+       
+       end_state = cur_state;
+}
+
+void jlink_runtest(int num_cycles)
+{
+       int i;
+       
+       enum tap_state saved_end_state = end_state;
+       
+       /* only do a state_move when we're not already in RTI */
+       if (cur_state != TAP_RTI)
+       {
+               jlink_end_state(TAP_RTI);
+               jlink_state_move();
+       }
+       
+       /* execute num_cycles */
+       for (i = 0; i < num_cycles; i++)
+       {
+               jlink_tap_append_step(0, 0);
+       }
+       
+       /* finish in end_state */
+       jlink_end_state(saved_end_state);
+       if (cur_state != end_state)
+       {
+               jlink_state_move();
+       }
+}
+
+void jlink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, scan_command_t *command)
+{
+       enum tap_state saved_end_state;
+       
+       jlink_tap_ensure_space(1, scan_size + 8);
+       
+       saved_end_state = end_state;
+       
+       /* Move to appropriate scan state */
+       jlink_end_state(ir_scan ? TAP_SI : TAP_SD);
+       
+       jlink_state_move();
+       jlink_end_state(saved_end_state);
+       
+       /* Scan */
+       jlink_tap_append_scan(scan_size, buffer, command);
+       
+       /* We are in Exit1, go to Pause */
+       jlink_tap_append_step(0, 0);
+       
+       cur_state = ir_scan ? TAP_PI : TAP_PD;
+       
+       if (cur_state != end_state)
+       {
+               jlink_state_move();
+       }
+}
+
+void jlink_reset(int trst, int srst)
+{
+       LOG_DEBUG("trst: %i, srst: %i", trst, srst);
+       
+       /* Signals are active low */
+       if (trst == 0)
+       {
+               jlink_simple_command(JLINK_SET_TRST_HIGH_COMMAND);
+       }
+       else if (trst == 1)
+       {
+               jlink_simple_command(JLINK_SET_TRST_LOW_COMMAND);
+       }
+       
+       if (srst == 0)
+       {
+               jlink_simple_command(JLINK_SET_SRST_HIGH_COMMAND);
+       }
+       else if (srst == 1)
+       {
+               jlink_simple_command(JLINK_SET_SRST_LOW_COMMAND);
+       }
+}
+
+void jlink_simple_command(u8 command)
+{
+       int result;
+       
+       DEBUG_JTAG_IO("0x%02x", command);
+       
+       usb_out_buffer[0] = command;
+       result = jlink_usb_write(jlink_jtag_handle, 1);
+       
+       if (result != 1)
+       {
+               LOG_ERROR("J-Link command 0x%02x failed (%d)", command, result);
+       }
+}
+
+int jlink_get_status(void)
+{
+       int result;
+       
+       jlink_simple_command(JLINK_GET_STATUS_COMMAND);
+       result = jlink_usb_read(jlink_jtag_handle);
+       
+       if(result == 8)
+       {
+               int vref = usb_in_buffer[0] + (usb_in_buffer[1] << 8);
+               LOG_INFO("Vref = %d.%d TCK=%d TDI=%d TDO=%d TMS=%d SRST=%d TRST=%d\n", \
+                       vref / 1000, vref % 1000, \
+                       usb_in_buffer[2], usb_in_buffer[3], usb_in_buffer[4], \
+                       usb_in_buffer[5], usb_in_buffer[6], usb_in_buffer[7]);
+               
+               if(vref < 1500)
+               {
+                       LOG_ERROR("Vref too low. Eventually the target isn't powered or disconnected?\n");
+               }
+       }
+       else
+       {
+               LOG_ERROR("J-Link command JLINK_GET_STATUS_COMMAND failed (%d)\n", result);
+       }
+       
+       return ERROR_OK;
+}
+
+int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int result;
+       int len = 0;
+       
+       /* query hardware version */
+       jlink_simple_command(JLINK_FIRMWARE_VERSION);
+       result = jlink_usb_read(jlink_jtag_handle);
+       
+       if (result == 2)
+       {
+               len = buf_get_u32(usb_in_buffer, 0, 16);
+               result = jlink_usb_read(jlink_jtag_handle);
+               
+               if(result == len)
+               {
+                       usb_in_buffer[result] = 0;
+                       LOG_INFO(usb_in_buffer);
+               }
+               
+               /* attempt to get status */
+               jlink_get_status();
+       }
+       else
+       {
+               LOG_ERROR("J-Link command JLINK_FIRMWARE_VERSION failed (%d)\n", result);
+       }
+       
+       return ERROR_OK;
+}
+
+/***************************************************************************/
+/* J-Link tap functions */
+
+/* We use the maximal value observed */
+#define JLINK_TAP_BUFFER_SIZE 390
+
+static int tap_length;
+static u8 tms_buffer[JLINK_TAP_BUFFER_SIZE];
+static u8 tdi_buffer[JLINK_TAP_BUFFER_SIZE];
+static u8 tdo_buffer[JLINK_TAP_BUFFER_SIZE];
+
+typedef struct
+{
+       int first;      /* First bit position in tdo_buffer to read */
+       int length; /* Number of bits to read */
+       scan_command_t *command; /* Corresponding scan command */
+       u8 *buffer;
+} pending_scan_result_t;
+
+#define MAX_PENDING_SCAN_RESULTS 16
+
+static int pending_scan_results_length;
+static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
+
+static int last_tms;
+
+void jlink_tap_init()
+{
+       tap_length = 0;
+       pending_scan_results_length = 0;
+}
+
+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;
+       
+       if (scans > available_scans || bits > available_bits)
+       {
+               jlink_tap_execute();
+       }
+}
+
+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;
+               
+               if (tms)
+               {
+                       tms_buffer[index] |= bit;
+               }
+               else
+               {
+                       tms_buffer[index] &= ~bit;
+               }
+               
+               if (tdi)
+               {
+                       tdi_buffer[index] |= bit;
+               }
+               else
+               {
+                       tdi_buffer[index] &= ~bit;
+               }
+               
+               tap_length++;
+       }
+       else
+       {
+               LOG_ERROR("jlink_tap_append_step, overflow");
+       }
+}
+
+void jlink_tap_append_scan(int length, u8 *buffer, scan_command_t *command)
+{
+       pending_scan_result_t *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length];
+       int i;
+       
+       pending_scan_result->first = tap_length;
+       pending_scan_result->length = length;
+       pending_scan_result->command = command;
+       pending_scan_result->buffer = buffer;
+       
+       for (i = 0; i < length; i++)
+       {
+               jlink_tap_append_step((i < length-1 ? 0 : 1), (buffer[i/8] >> (i%8)) & 1);
+       }
+       pending_scan_results_length++;
+}
+
+/* Pad and send a tap sequence to the device, and receive the answer.
+ * For the purpose of padding we assume that we are in idle or pause state. */
+int jlink_tap_execute()
+{
+       int byte_length;
+       int tms_offset;
+       int tdi_offset;
+       int i;
+       int result;
+       
+       if (tap_length > 0)
+       {
+               /* 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;
+       
+               usb_out_buffer[0] = JLINK_TAP_SEQUENCE_COMMAND;
+               usb_out_buffer[1] = (tap_length >> 0) & 0xff;
+               usb_out_buffer[2] = (tap_length >> 8) & 0xff;
+       
+               tms_offset = 3;
+               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];
+               }
+       
+               result = jlink_usb_message(jlink_jtag_handle, 3 + 2 * byte_length, byte_length);
+       
+               if (result == byte_length)
+               {
+                       for (i = 0; i < byte_length; i++)
+                       {
+                               tdo_buffer[i] = usb_in_buffer[i];
+                       }
+                       
+                       for (i = 0; i < pending_scan_results_length; i++)
+                       {
+                               pending_scan_result_t *pending_scan_result = &pending_scan_results_buffer[i];
+                               u8 *buffer = pending_scan_result->buffer;
+                               int length = pending_scan_result->length;
+                               int first = pending_scan_result->first;
+                               scan_command_t *command = pending_scan_result->command;
+       
+                               /* Copy to buffer */
+                               buf_set_buf(tdo_buffer, first, buffer, 0, length);
+       
+                               DEBUG_JTAG_IO("pending scan result, length = %d", length);
+                               
+#ifdef _DEBUG_USB_COMMS_
+                               jlink_debug_buffer(buffer, byte_length);
+#endif
+       
+                       if (jtag_read_buffer(buffer, command) != ERROR_OK)
+                       {
+                               jlink_tap_init();
+                                       return ERROR_JTAG_QUEUE_FAILED;
+                       }
+               
+                       if (pending_scan_result->buffer != NULL)
+                       {
+                                       free(pending_scan_result->buffer);
+                       }
+               }
+               }
+               else
+               {
+                       LOG_ERROR("jlink_tap_execute, wrong result %d, expected %d", result, byte_length);
+                       return ERROR_JTAG_QUEUE_FAILED;
+               }
+               
+               jlink_tap_init();
+       }
+       
+       return ERROR_OK;
+}
+
+/*****************************************************************************/
+/* JLink USB low-level functions */
+
+jlink_jtag_t* jlink_usb_open()
+{
+       struct usb_bus *busses;
+       struct usb_bus *bus;
+       struct usb_device *dev;
+       
+       jlink_jtag_t *result;
+       
+       result = (jlink_jtag_t*) malloc(sizeof(jlink_jtag_t));
+       
+       usb_init();
+       usb_find_busses();
+       usb_find_devices();
+       
+       busses = usb_get_busses();
+       
+       /* find jlink_jtag device in usb bus */
+       
+       for (bus = busses; bus; bus = bus->next)
+       {
+               for (dev = bus->devices; dev; dev = dev->next)
+               {
+                       if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID))
+                       {
+                               result->usb_handle = usb_open(dev);
+                               
+                               /* usb_set_configuration required under win32 */
+                               usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue);
+                               usb_claim_interface(result->usb_handle, 0);
+                               usb_set_altinterface(result->usb_handle, 0);
+                               return result;
+                       }
+               }
+       }
+       
+       free(result);
+       return NULL;
+}
+
+void jlink_usb_close(jlink_jtag_t *jlink_jtag)
+{
+       usb_close(jlink_jtag->usb_handle);
+       free(jlink_jtag);
+}
+
+/* Send a message and receive the reply. */
+int jlink_usb_message(jlink_jtag_t *jlink_jtag, int out_length, int in_length)
+{
+       int result;
+       
+       result = jlink_usb_write(jlink_jtag, out_length);
+       if (result == out_length)
+       {
+               result = jlink_usb_read(jlink_jtag);
+               if (result == in_length)
+               {
+                       return result;
+               }
+           else
+           {
+                       LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result);
+                       return -1;
+           }
+       }
+       else
+       {
+               LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result);
+           return -1;
+       }
+}
+
+/* Write data from out_buffer to USB. */
+int jlink_usb_write(jlink_jtag_t *jlink_jtag, int out_length)
+{
+       int result;
+       
+       if (out_length > JLINK_OUT_BUFFER_SIZE)
+       {
+               LOG_ERROR("jlink_jtag_write illegal out_length=%d (max=%d)", out_length, JLINK_OUT_BUFFER_SIZE);
+               return -1;
+       }
+       
+       result = usb_bulk_write(jlink_jtag->usb_handle, JLINK_WRITE_ENDPOINT, \
+               usb_out_buffer, out_length, JLINK_USB_TIMEOUT);
+       
+       DEBUG_JTAG_IO("jlink_usb_write, out_length = %d, result = %d", out_length, result);
+       
+#ifdef _DEBUG_USB_COMMS_
+       jlink_debug_buffer(usb_out_buffer, out_length);
+#endif
+       return result;
+}
+
+/* Read data from USB into in_buffer. */
+int jlink_usb_read(jlink_jtag_t *jlink_jtag)
+{
+       int result = usb_bulk_read(jlink_jtag->usb_handle, JLINK_READ_ENDPOINT, \
+               usb_in_buffer, JLINK_IN_BUFFER_SIZE, JLINK_USB_TIMEOUT);
+
+       DEBUG_JTAG_IO("jlink_usb_read, result = %d", result);
+       
+#ifdef _DEBUG_USB_COMMS_
+       jlink_debug_buffer(usb_in_buffer, result);
+#endif
+    return result;
+}
+
+#ifdef _DEBUG_USB_COMMS_
+#define BYTES_PER_LINE  16
+
+void jlink_debug_buffer(u8 *buffer, int length)
+{
+       char line[81];
+       char s[4];
+       int i;
+       int j;
+       
+       for (i = 0; i < length; i += BYTES_PER_LINE)
+       {
+               snprintf(line, 5, "%04x", i);
+               for (j = i; j < i + BYTES_PER_LINE && j < length; j++)
+               {
+                       snprintf(s, 4, " %02x", buffer[j]);
+                       strcat(line, s);
+               }
+               LOG_DEBUG(line);
+       }
+}
+#endif
index 82b9affc51c34aec9a260f5dc1b4da7503201d92..e78d99d93b797e697e1c7d87b62d6a427f6e09c9 100644 (file)
@@ -193,6 +193,10 @@ static int hasKHz = 0;
        extern jtag_interface_t usbprog_interface;
 #endif
 
+#if BUILD_JLINK == 1
+       extern jtag_interface_t jlink_interface;
+#endif
+
 jtag_interface_t *jtag_interfaces[] = {
 #if BUILD_ECOSBOARD == 1
        &eCosBoard_interface,
@@ -226,6 +230,9 @@ jtag_interface_t *jtag_interfaces[] = {
 #endif
 #if BUILD_USBPROG == 1
        &usbprog_interface,
+#endif
+#if BUILD_JLINK == 1
+       &jlink_interface,
 #endif
        NULL,
 };
index 93f6c46260ceb8c3615b9772c70e12f216e0c3b8..c230100d6b1f5ac8b0f3cec52b99430f8e985eab 100644 (file)
@@ -32,5 +32,5 @@ nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.script
        target/lm3s811.cfg interface/luminary.cfg interface/luminary-lm3s811.cfg interface/stm32-stick.cfg \
        interface/calao-usb-a9260-c01.cfg interface/calao-usb-a9260-c02.cfg \
        interface/calao-usb-a9260.cfg target/at91sam9260minimal.cfg  event/lpc2148_reset.script \
-       interface/chameleon.cfg interface/at91rm9200.cfg
+       interface/chameleon.cfg interface/at91rm9200.cfg interface/jlink.cfg
 
diff --git a/src/target/interface/jlink.cfg b/src/target/interface/jlink.cfg
new file mode 100644 (file)
index 0000000..1e8c2c4
--- /dev/null
@@ -0,0 +1,3 @@
+# jlink interface
+interface jlink
+

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)