aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <openocd-dev@marcschink.de>2014-10-20 13:18:38 -0400
committerFreddie Chopin <freddie.chopin@gmail.com>2015-11-26 12:19:22 +0000
commit442f1540d5066b9ef091cab677b505f2c8196313 (patch)
tree3524cbbeb1fa9cb3fa1041e36c37beb398e2f2f0
parent9a6d6b51b7428ddac6ada28dd9db589deb616f4d (diff)
Improve J-Link driver and introduce libjaylink.
This patch uses libjaylink which is a library to access J-Link devices. As other tools which are not in the scope of OpenOCD also need to access J-Link devices a library is used. A firmware upgrade tool and an advanced configuration tool for J-Link devices are under development. Further versions of libjaylink will support additional features OpenOCD could benefit from. This includes TCP/IP as additional possibility to connect to J-Link devices as well as power tracing and device internal communication. The latter is used to access peripherals on some development boards (e.g EFM32 STK and DVK). Integration of libjaylink is realized with a git submodule like jimtcl. As libjaylink depends on libusb-1.0 only, no additional dependency is introduced for OpenOCD. All low-level JTAG and SWD implementations of the current driver are left untouched and therefore no incompabilities are to be expected. Improvements of this patch: * Support for more USB Product IDs, including those with the new scheme (0x10xx). The corresponding udev rules are also updated. * Device selection with serial number and USB address. * Adaptive clocking is now correctly implemented and only usable for devices with the corresponding capability. * The target power supply can now be switched without the need for changing configuration and power cycling the device. * Device configuration is more restrictive and only allowed if the required capabilities are available. * Device configuration now shows the changes between the current configuration of the device and the values that will be applied. * Device configuration is verified after it is written to the device exactly as the vendor software does. * Connection registration is now handled properly and checks if the maximum number of connections on a device is reached. This is also necessary for devices which are attached via USB to OpenOCD as some device models also support connections on TCP/IP. * Serial Wire Output (SWO) can now be captured. This feature is not documented by SEGGER however it is completely supported by libjaylink. This patch and libjaylink were tested on Ubuntu 14.04 (i386), Debian 7 (amd64), FreeBSD 10.0 (amd64) and Windows XP SP3 (32-bit) with the following device and target configurations: * JTAG: J-Link v8.0, v9.0 and v9.3 with AT91SAM7S256 * SWD: SiLabs EFM32 STK 3700 (EFM32GG990F1024) * SWD: J-Link v8.0, v9.0 and v9.3 with EFM32GG990F1024 * SWD: XMC 2Go (XMC1100) * SWD: XMC1100 Boot Kit (XMC1100) * SWD: IAR Systems / Olimex Eval Board (LPC1343F) * SWD: Nordic Semiconductor nRF51 Dongle (nRF51422) * SWD: SiLabs EZR32 WSTK 6220A (EZR32WG330FG60G) Except for Windows XP all builds are tested with Clang in addition to GCC. This patch and libjaylink are not tested on OSX yet. Change-Id: I8476c57d37c6091c4b892b183da682c548ca1786 Signed-off-by: Marc Schink <openocd-dev@marcschink.de> Reviewed-on: http://openocd.zylin.com/2598 Tested-by: jenkins Reviewed-by: Andreas Färber <afaerber@suse.de> Reviewed-by: Paul Fertser <fercerpav@gmail.com> Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
-rw-r--r--.gitmodules3
-rw-r--r--configure.ac31
-rw-r--r--contrib/99-openocd.rules14
-rw-r--r--doc/openocd.texi81
-rw-r--r--src/jtag/drivers/Makefile.am25
-rw-r--r--src/jtag/drivers/jlink.c2162
m---------src/jtag/drivers/libjaylink0
7 files changed, 1143 insertions, 1173 deletions
diff --git a/.gitmodules b/.gitmodules
index f23a5d4b..013adc83 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "jimtcl"]
path = jimtcl
url = http://repo.or.cz/r/jimtcl.git
+[submodule "src/jtag/drivers/libjaylink"]
+ path = src/jtag/drivers/libjaylink
+ url = git://repo.or.cz/libjaylink.git
diff --git a/configure.ac b/configure.ac
index 87d4d6a0..fb01e1bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -201,6 +201,7 @@ m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])])
m4_define([USB1_ADAPTERS],
[[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]],
+ [[jlink], [Segger J-Link JTAG Programmer], [JLINK]],
[[stlink], [ST-Link JTAG Programmer], [HLADAPTER_STLINK]],
[[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]],
[[ulink], [Keil ULINK JTAG Programmer], [ULINK]],
@@ -208,8 +209,7 @@ m4_define([USB1_ADAPTERS],
[[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]]])
m4_define([USB_ADAPTERS],
- [[[jlink], [Segger J-Link JTAG Programmer], [JLINK]],
- [[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]],
+ [[[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]],
[[opendous], [eStick/opendous JTAG Programmer], [OPENDOUS]],
[[aice], [Andes JTAG Programmer], [AICE]]])
@@ -506,6 +506,11 @@ AC_ARG_ENABLE([internal-jimtcl],
AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]),
[use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes])
+AC_ARG_ENABLE([internal-libjaylink],
+ AS_HELP_STRING([--disable-internal-libjaylink],
+ [Disable building internal libjaylink]),
+ [use_internal_libjaylink=$enableval], [use_internal_libjaylink=yes])
+
build_minidriver=no
AC_MSG_CHECKING([whether to enable ZY1000 minidriver])
if test $build_zy1000 = yes; then
@@ -787,6 +792,19 @@ if test $use_internal_jimtcl = yes; then
fi
fi
+if test $use_internal_libjaylink = yes; then
+ if test -f "$srcdir/src/jtag/drivers/libjaylink/configure.ac"; then
+ ( cd $srcdir/src/jtag/drivers/libjaylink/ && ./autogen.sh )
+ AX_CONFIG_SUBDIR_OPTION([src/jtag/drivers/libjaylink],
+ [--enable-subproject-build])
+ else
+ AC_MSG_ERROR([Internal libjaylink not found, run either 'git submodule init' and 'git submodule update' or disable internal libjaylink with --disable-internal-libjaylink.])
+ fi
+else
+ PKG_CHECK_MODULES([libjaylink], [libjaylink >= 0.1],
+ [CFLAGS="$CFLAGS $libjaylink_CFLAGS"; LIBS="$LIBS $libjaylink_LIBS"; HAVE_LIBJAYLINK=yes], [HAVE_LIBJAYLINK=no])
+fi
+
if test $build_remote_bitbang = yes; then
build_bitbang=yes
AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang JTAG driver.])
@@ -1170,6 +1188,14 @@ else
fi
AM_CONDITIONAL([HLADAPTER], [test $enable_stlink != no -o $enable_ti_icdi != no])
+# Disable J-Link driver if internal libjaylink is disabled and libjaylink was
+# not found by pkg-config.
+if test $enable_jlink != no; then
+ if test $use_internal_libjaylink$HAVE_LIBJAYLINK = nono; then
+ enable_jlink=no
+ fi
+fi
+
AM_CONDITIONAL([RELEASE], [test $build_release = yes])
AM_CONDITIONAL([PARPORT], [test $build_parport = yes])
AM_CONDITIONAL([DUMMY], [test $build_dummy = yes])
@@ -1209,6 +1235,7 @@ AM_CONDITIONAL([MINIDRIVER], [test $build_minidriver = yes])
AM_CONDITIONAL([MINIDRIVER_DUMMY], [test $build_minidriver_dummy = yes])
AM_CONDITIONAL([INTERNAL_JIMTCL], [test $use_internal_jimtcl = yes])
+AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test $use_internal_libjaylink = yes])
# Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h?
AC_MSG_CHECKING([for environ in unistd.h and stdlib.h])
diff --git a/contrib/99-openocd.rules b/contrib/99-openocd.rules
index 154b09fc..344b933a 100644
--- a/contrib/99-openocd.rules
+++ b/contrib/99-openocd.rules
@@ -74,15 +74,23 @@ ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="664", GROUP="plugdev"
# Amontec JTAGkey-HiSpeed
ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="664", GROUP="plugdev"
-# IAR J-Link USB
+# SEGGER J-Link
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="664", GROUP="plugdev"
-
-# J-Link-OB (onboard)
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="664", GROUP="plugdev"
+ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="664", GROUP="plugdev"
# Raisonance RLink
ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="664", GROUP="plugdev"
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 81a45d19..86415319 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -449,18 +449,17 @@ product. The driver can be configured to search for any VID/PID pair
@* Link: @url{http://www.altera.com/literature/ug/ug_usb_blstr.pdf}
@end itemize
-@section USB JLINK based
-There are several OEM versions of the Segger @b{JLINK} adapter. It is
-an example of a micro controller based JTAG adapter, it uses an
+@section USB J-Link based
+There are several OEM versions of the SEGGER @b{J-Link} adapter. It is
+an example of a microcontroller based JTAG adapter, it uses an
AT91SAM764 internally.
@itemize @bullet
-@item @b{ATMEL SAMICE} Only works with ATMEL chips!
-@* Link: @url{http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3892}
-@item @b{SEGGER JLINK}
+@item @b{SEGGER J-Link}
@* Link: @url{http://www.segger.com/jlink.html}
+@item @b{Atmel SAM-ICE} (Only works with Atmel chips!)
+@* Link: @url{http://www.atmel.com/tools/atmelsam-ice.aspx}
@item @b{IAR J-Link}
-@* Link: @url{http://www.iar.com/en/products/hardware-debug-probes/iar-j-link/}
@end itemize
@section USB RLINK based
@@ -1960,7 +1959,7 @@ Examples:
@cindex translation
If you have a configuration file for another hardware debugger
or toolset (Abatron, BDI2000, BDI3000, CCS,
-Lauterbach, Segger, Macraigor, etc.), translating
+Lauterbach, SEGGER, Macraigor, etc.), translating
it into OpenOCD syntax is often quite straightforward. The most tricky
part of creating a configuration script is oftentimes the reset init
sequence where e.g. PLLs, DRAM and the like is set up.
@@ -2717,63 +2716,69 @@ This is a write-once setting.
@end deffn
@deffn {Interface Driver} {jlink}
-Segger J-Link family of USB adapters. It currently supports JTAG and SWD transports.
+SEGGER J-Link family of USB adapters. It currently supports JTAG and SWD
+transports.
@quotation Compatibility Note
-Segger released many firmware versions for the many harware versions they
+SEGGER released many firmware versions for the many harware versions they
produced. OpenOCD was extensively tested and intended to run on all of them,
but some combinations were reported as incompatible. As a general
recommendation, it is advisable to use the latest firmware version
available for each hardware version. However the current V8 is a moving
-target, and Segger firmware versions released after the OpenOCD was
+target, and SEGGER firmware versions released after the OpenOCD was
released may not be compatible. In such cases it is recommended to
revert to the last known functional version. For 0.5.0, this is from
"Feb 8 2012 14:30:39", packed with 4.42c. For 0.6.0, the last known
version is from "May 3 2012 18:36:22", packed with 4.46f.
@end quotation
-@deffn {Command} {jlink caps}
-Display the device firmware capabilities.
+@deffn {Command} {jlink hwstatus}
+Display various hardware related information, for example target voltage and pin
+states.
@end deffn
-@deffn {Command} {jlink info}
-Display various device information, like hardware version, firmware version, current bus status.
+@deffn {Command} {jlink freemem}
+Display free device internal memory.
@end deffn
-@deffn {Command} {jlink hw_jtag} [@option{2}|@option{3}]
-Set the JTAG protocol version to be used. Without argument, show the actual JTAG protocol version.
+@deffn {Command} {jlink jtag} [@option{2}|@option{3}]
+Set the JTAG command version to be used. Without argument, show the actual JTAG
+command version.
@end deffn
@deffn {Command} {jlink config}
-Display the J-Link configuration.
+Display the device configuration.
@end deffn
-@deffn {Command} {jlink config kickstart} [val]
-Set the Kickstart power on JTAG-pin 19. Without argument, show the Kickstart configuration.
+@deffn {Command} {jlink config targetpower} [@option{on}|@option{off}]
+Set the target power state on JTAG-pin 19. Without argument, show the target
+power state.
@end deffn
-@deffn {Command} {jlink config mac_address} [@option{ff:ff:ff:ff:ff:ff}]
-Set the MAC address of the J-Link Pro. Without argument, show the MAC address.
+@deffn {Command} {jlink config mac} [@option{ff:ff:ff:ff:ff:ff}]
+Set the MAC address of the device. Without argument, show the MAC address.
@end deffn
@deffn {Command} {jlink config ip} [@option{A.B.C.D}(@option{/E}|@option{F.G.H.I})]
-Set the IP configuration of the J-Link Pro, where A.B.C.D is the IP address,
- E the bit of the subnet mask and
- F.G.H.I the subnet mask. Without arguments, show the IP configuration.
+Set the IP configuration of the device, where A.B.C.D is the IP address, E the
+bit of the subnet mask and F.G.H.I the subnet mask. Without arguments, show the
+IP configuration.
@end deffn
-@deffn {Command} {jlink config usb_address} [@option{0x00} to @option{0x03} or @option{0xff}]
-Set the USB address; this will also change the product id. Without argument, show the USB address.
+@deffn {Command} {jlink config usb} [@option{0} to @option{3}]
+Set the USB address of the device. This will also change the USB Product ID
+(PID) of the device. Without argument, show the USB address.
@end deffn
@deffn {Command} {jlink config reset}
Reset the current configuration.
@end deffn
-@deffn {Command} {jlink config save}
-Save the current configuration to the internal persistent storage.
-@end deffn
-@deffn {Config} {jlink pid} val
-Set the USB PID of the interface. As a configuration command, it can be used only before 'init'.
+@deffn {Command} {jlink config write}
+Write the current configuration to the internal persistent storage.
@end deffn
-@deffn {Config} {jlink serial} serial-number
-Set the @var{serial-number} of the interface, in case more than one adapter is connected to the host.
-If not specified, serial numbers are not considered.
+@deffn {Config} {jlink usb} <@option{0} to @option{3}>
+Set the USB address of the interface, in case more than one adapter is connected
+to the host. If not specified, USB addresses are not considered. Device
+selection via USB address is deprecated and the serial number should be used
+instead.
-Note that there may be leading zeros in the @var{serial-number} string
-that will not show in the Segger software, but must be specified here.
-Debug level 3 output contains serial numbers if there is a mismatch.
+As a configuration command, it can be used only before 'init'.
+@end deffn
+@deffn {Config} {jlink serial} <serial number>
+Set the serial number of the interface, in case more than one adapter is
+connected to the host. If not specified, serial numbers are not considered.
As a configuration command, it can be used only before 'init'.
@end deffn
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index aea2b38a..2aaf8fd8 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -20,6 +20,22 @@ EXTRA_DIST = $(ULINK_FIRMWARE) \
DRIVERFILES =
SUBDIRS=
+if JLINK
+if INTERNAL_LIBJAYLINK
+SUBDIRS += libjaylink
+
+libjaylink_internal_la_SOURCES = jlink.c
+libjaylink_internal_la_LIBADD = libjaylink/libjaylink/libjaylink.la
+libjaylink_internal_la_CPPFLAGS = -I$(builddir)/libjaylink/libjaylink \
+ -I$(srcdir)/libjaylink $(AM_CPPFLAGS)
+
+noinst_LTLIBRARIES += libjaylink_internal.la
+libocdjtagdrivers_la_LIBADD += libjaylink_internal.la
+else
+DRIVERFILES += jlink.c
+endif
+endif
+
# Standard Driver: common files
DRIVERFILES += driver.c
@@ -77,9 +93,6 @@ endif
if USBPROG
DRIVERFILES += usbprog.c
endif
-if JLINK
-DRIVERFILES += jlink.c
-endif
if RLINK
DRIVERFILES += rlink.c rlink_speed_table.c
endif
@@ -151,4 +164,10 @@ noinst_HEADERS = \
versaloon/versaloon_include.h \
versaloon/versaloon_internal.h
+DIST_SUBDIRS = usb_blaster
+
+if INTERNAL_LIBJAYLINK
+DIST_SUBDIRS += libjaylink
+endif
+
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index de504c86..1db1a711 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -8,6 +8,9 @@
* Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD *
* plagnioj@jcrosoft.com *
* *
+ * Copyright (C) 2015 by Marc Schink *
+ * openocd-dev@marcschink.de *
+ * *
* 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 *
@@ -21,189 +24,60 @@
* 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., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <stdint.h>
+#include <math.h>
+
#include <jtag/interface.h>
#include <jtag/swd.h>
#include <jtag/commands.h>
-#include "libusb_common.h"
-/* See Segger's public documentation:
- * Reference manual for J-Link USB Protocol
- * Document RM08001-R6 Date: June 16, 2009
- * (Or newer, with some SWD information).
- * http://www.segger.com/cms/admin/uploads/productDocs/RM08001_JLinkUSBProtocol.pdf
- */
+#include <libjaylink/libjaylink.h>
-/*
- * The default pid of the segger is 0x0101
- * But when you change the USB Address it will also
- *
- * pid = ( usb_address > 0x4) ? 0x0101 : (0x101 + usb_address)
- */
+static struct jaylink_context *jayctx;
+static struct jaylink_device_handle *devh;
+static struct jaylink_connection conn;
+static struct jaylink_connection connlist[JAYLINK_MAX_CONNECTIONS];
+static enum jaylink_jtag_version jtag_command_version;
+static uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE];
-#define JLINK_USB_INTERFACE_CLASS 0xff
-#define JLINK_USB_INTERFACE_SUBCLASS 0xff
-#define JLINK_USB_INTERFACE_PROTOCOL 0xff
-
-static unsigned int jlink_write_ep;
-static unsigned int jlink_read_ep;
-static unsigned int jlink_hw_jtag_version = 2;
-
-#define JLINK_USB_TIMEOUT 1000
-
-/* See Section 3.3.2 of the Segger JLink USB protocol manual */
-/* 2048 is the max value we can use here */
-#define JLINK_TAP_BUFFER_SIZE 2048
-/*#define JLINK_TAP_BUFFER_SIZE 256*/
-/*#define JLINK_TAP_BUFFER_SIZE 384*/
-
-#define JLINK_IN_BUFFER_SIZE (2048 + 1)
-#define JLINK_OUT_BUFFER_SIZE (2*2048 + 4)
-
-/* Global USB buffers */
-static uint8_t usb_in_buffer[JLINK_IN_BUFFER_SIZE];
-static uint8_t usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
-
-/* Constants for JLink command */
-#define EMU_CMD_VERSION 0x01
-#define EMU_CMD_RESET_TRST 0x02
-#define EMU_CMD_RESET_TARGET 0x03
-#define EMU_CMD_SET_SPEED 0x05
-#define EMU_CMD_GET_STATE 0x07
-#define EMU_CMD_SET_KS_POWER 0x08
-#define EMU_CMD_REGISTER 0x09
-#define EMU_CMD_GET_SPEEDS 0xc0
-#define EMU_CMD_GET_HW_INFO 0xc1
-#define EMU_CMD_GET_COUNTERS 0xc2
-#define EMU_CMD_SELECT_IF 0xc7
-#define EMU_CMD_HW_CLOCK 0xc8
-#define EMU_CMD_HW_TMS0 0xc9
-#define EMU_CMD_HW_TMS1 0xca
-#define EMU_CMD_HW_DATA0 0xcb
-#define EMU_CMD_HW_DATA1 0xcc
-#define EMU_CMD_HW_JTAG 0xcd
-#define EMU_CMD_HW_JTAG2 0xce
-#define EMU_CMD_HW_JTAG3 0xcf
-#define EMU_CMD_HW_RELEASE_RESET_STOP_EX 0xd0
-#define EMU_CMD_HW_RELEASE_RESET_STOP_TIMED 0xd1
-#define EMU_CMD_GET_MAX_MEM_BLOCK 0xd4
-#define EMU_CMD_HW_JTAG_WRITE 0xd5
-#define EMU_CMD_HW_JTAG_GET_RESULT 0xd6
-#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
-#define EMU_CMD_GET_CPU_CAPS 0xe9
-#define EMU_CMD_EXEC_CPU_CMD 0xea
-#define EMU_CMD_GET_CAPS_EX 0xed
-#define EMU_CMD_GET_HW_VERSION 0xf0
-#define EMU_CMD_WRITE_DCC 0xf1
-#define EMU_CMD_READ_CONFIG 0xf2
-#define EMU_CMD_WRITE_CONFIG 0xf3
-#define EMU_CMD_WRITE_MEM 0xf4
-#define EMU_CMD_READ_MEM 0xf5
-#define EMU_CMD_MEASURE_RTCK_REACT 0xf6
-#define EMU_CMD_WRITE_MEM_ARM79 0xf7
-#define EMU_CMD_READ_MEM_ARM79 0xf8
-
-/* Register subcommands */
-#define REG_CMD_REGISTER 100
-#define REG_CMD_UNREGISTER 101
-
-/* bits return from EMU_CMD_GET_CAPS */
-#define EMU_CAP_RESERVED_1 0
-#define EMU_CAP_GET_HW_VERSION 1
-#define EMU_CAP_WRITE_DCC 2
-#define EMU_CAP_ADAPTIVE_CLOCKING 3
-#define EMU_CAP_READ_CONFIG 4
-#define EMU_CAP_WRITE_CONFIG 5
-#define EMU_CAP_TRACE 6
-#define EMU_CAP_WRITE_MEM 7
-#define EMU_CAP_READ_MEM 8
-#define EMU_CAP_SPEED_INFO 9
-#define EMU_CAP_EXEC_CODE 10
-#define EMU_CAP_GET_MAX_BLOCK_SIZE 11
-#define EMU_CAP_GET_HW_INFO 12
-#define EMU_CAP_SET_KS_POWER 13
-#define EMU_CAP_RESET_STOP_TIMED 14
-#define EMU_CAP_RESERVED_2 15
-#define EMU_CAP_MEASURE_RTCK_REACT 16
-#define EMU_CAP_SELECT_IF 17
-#define EMU_CAP_RW_MEM_ARM79 18
-#define EMU_CAP_GET_COUNTERS 19
-#define EMU_CAP_READ_DCC 20
-#define EMU_CAP_GET_CPU_CAPS 21
-#define EMU_CAP_EXEC_CPU_CMD 22
-#define EMU_CAP_SWO 23
-#define EMU_CAP_WRITE_DCC_EX 24
-#define EMU_CAP_UPDATE_FIRMWARE_EX 25
-#define EMU_CAP_FILE_IO 26
-#define EMU_CAP_REGISTER 27
-#define EMU_CAP_INDICATORS 28
-#define EMU_CAP_TEST_NET_SPEED 29
-#define EMU_CAP_RAWTRACE 30
-#define EMU_CAP_RESERVED_3 31
-
-static const char * const jlink_cap_str[] = {
- "Always 1.",
- "Supports command EMU_CMD_GET_HARDWARE_VERSION",
- "Supports command EMU_CMD_WRITE_DCC",
- "Supports adaptive clocking",
- "Supports command EMU_CMD_READ_CONFIG",
- "Supports command EMU_CMD_WRITE_CONFIG",
- "Supports trace commands",
- "Supports command EMU_CMD_WRITE_MEM",
- "Supports command EMU_CMD_READ_MEM",
- "Supports command EMU_CMD_GET_SPEED",
- "Supports command EMU_CMD_CODE_...",
- "Supports command EMU_CMD_GET_MAX_BLOCK_SIZE",
- "Supports command EMU_CMD_GET_HW_INFO",
- "Supports command EMU_CMD_SET_KS_POWER",
- "Supports command EMU_CMD_HW_RELEASE_RESET_STOP_TIMED",
- "Reserved",
- "Supports command EMU_CMD_MEASURE_RTCK_REACT",
- "Supports command EMU_CMD_HW_SELECT_IF",
- "Supports command EMU_CMD_READ/WRITE_MEM_ARM79",
- "Supports command EMU_CMD_GET_COUNTERS",
- "Supports command EMU_CMD_READ_DCC",
- "Supports command EMU_CMD_GET_CPU_CAPS",
- "Supports command EMU_CMD_EXEC_CPU_CMD",
- "Supports command EMU_CMD_SWO",
- "Supports command EMU_CMD_WRITE_DCC_EX",
- "Supports command EMU_CMD_UPDATE_FIRMWARE_EX",
- "Supports command EMU_CMD_FILE_IO",
- "Supports command EMU_CMD_REGISTER",
- "Supports command EMU_CMD_INDICATORS",
- "Supports command EMU_CMD_TEST_NET_SPEED",
- "Supports command EMU_CMD_RAWTRACE",
- "Reserved",
-};
+static uint32_t serial_number;
+static bool use_serial_number;
+static uint8_t usb_address;
+static bool use_usb_address;
+static uint8_t iface = JAYLINK_TIF_JTAG;
+static bool trace_enabled;
+
+#define JLINK_MAX_SPEED 12000
+#define JLINK_TAP_BUFFER_SIZE 2048
-/* max speed 12MHz v5.0 jlink */
-#define JLINK_MAX_SPEED 12000
-
-/* J-Link hardware versions */
-#define JLINK_HW_TYPE_JLINK 0
-#define JLINK_HW_TYPE_JTRACE 1
-#define JLINK_HW_TYPE_FLASHER 2
-#define JLINK_HW_TYPE_JLINK_PRO 3
-#define JLINK_HW_TYPE_JLINK_LITE_ADI 5
-#define JLINK_HW_TYPE_JLINK_LITE_XMC4000 16
-#define JLINK_HW_TYPE_JLINK_LITE_XMC4200 17
-#define JLINK_HW_TYPE_LPCLINK2 18
-
-/* Interface selection */
-#define JLINK_TIF_JTAG 0
-#define JLINK_TIF_SWD 1
-#define JLINK_SWD_DIR_IN 0
-#define JLINK_SWD_DIR_OUT 1
+static unsigned int swd_buffer_size = JLINK_TAP_BUFFER_SIZE;
+
+/* 256 byte non-volatile memory */
+struct device_config {
+ uint8_t usb_address;
+ /* 0ffset 0x01 to 0x03 */
+ uint8_t reserved_1[3];
+ uint32_t target_power;
+ /* 0ffset 0x08 to 0x1f */
+ uint8_t reserved_2[24];
+ /* IP only for J-Link Pro */
+ uint8_t ip_address[4];
+ uint8_t subnet_mask[4];
+ /* 0ffset 0x28 to 0x2f */
+ uint8_t reserved_3[8];
+ uint8_t mac_address[6];
+ /* 0ffset 0x36 to 0xff */
+ uint8_t reserved_4[202];
+} __attribute__ ((packed));
+
+static struct device_config config;
+static struct device_config tmp_config;
/* Queue command functions */
static void jlink_end_state(tap_state_t state);
@@ -213,11 +87,11 @@ static void jlink_runtest(int num_cycles);
static void jlink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
int scan_size, struct scan_command *command);
static void jlink_reset(int trst, int srst);
-static void jlink_simple_command(uint8_t command);
-static int jlink_get_status(void);
static int jlink_swd_run_queue(struct adiv5_dap *dap);
-static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data);
-static int jlink_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq);
+static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd,
+ uint32_t *dst, uint32_t data);
+static int jlink_swd_switch_seq(struct adiv5_dap *dap,
+ enum swd_special_seq seq);
/* J-Link tap buffer functions */
static void jlink_tap_init(void);
@@ -227,75 +101,18 @@ static void jlink_tap_append_step(int tms, int tdi);
static void jlink_tap_append_scan(int length, uint8_t *buffer,
struct scan_command *command);
-/* Jlink lowlevel functions */
-struct jlink {
- struct jtag_libusb_device_handle *usb_handle;
-};
-
-static struct jlink *jlink_usb_open(void);
-static void jlink_usb_close(struct jlink *jlink);
-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);
-
-/* helper functions */
-static int jlink_get_version_info(void);
-
-#ifdef _DEBUG_USB_COMMS_
-static void jlink_debug_buffer(uint8_t *buffer, int length);
-#else
-static inline void jlink_debug_buffer(uint8_t *buffer, int length)
-{
-}
-#endif
-
static enum tap_state jlink_last_state = TAP_RESET;
-
-static struct jlink *jlink_handle;
-
-/* pid could be specified at runtime */
-static uint16_t vids[] = { 0x1366, 0x1366, 0x1366, 0x1366, 0x1366, 0x1366, 0 };
-static uint16_t pids[] = { 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x1015, 0 };
-
-static char *jlink_serial;
-
-static uint32_t jlink_caps;
-static uint32_t jlink_hw_type;
-
static int queued_retval;
-static bool swd_mode;
-
-/* 256 byte non-volatile memory */
-struct jlink_config {
- uint8_t usb_address;
- /* 0ffset 0x01 to 0x03 */
- uint8_t reserved_1[3];
- uint32_t kickstart_power_on_jtag_pin_19;
- /* 0ffset 0x08 to 0x1f */
- uint8_t reserved_2[24];
- /* IP only for J-Link Pro */
- uint8_t ip_address[4];
- uint8_t subnet_mask[4];
- /* 0ffset 0x28 to 0x2f */
- uint8_t reserved_3[8];
- uint8_t mac_address[6];
- /* 0ffset 0x36 to 0xff */
- uint8_t reserved_4[202];
-} __attribute__ ((packed));
-struct jlink_config jlink_cfg;
/***************************************************************************/
/* External interface implementation */
static void jlink_execute_runtest(struct jtag_command *cmd)
{
- DEBUG_JTAG_IO("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
+ DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
+ cmd->cmd.runtest->end_state);
jlink_end_state(cmd->cmd.runtest->end_state);
-
jlink_runtest(cmd->cmd.runtest->num_cycles);
}
@@ -313,8 +130,7 @@ static void jlink_execute_pathmove(struct jtag_command *cmd)
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);
+ jlink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
}
static void jlink_execute_scan(struct jtag_command *cmd)
@@ -330,16 +146,14 @@ static void jlink_execute_scan(struct jtag_command *cmd)
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
DEBUG_JTAG_IO("scan input, length = %d", scan_size);
- jlink_debug_buffer(buffer, (scan_size + 7) / 8);
type = jtag_scan_type(cmd->cmd.scan);
- jlink_scan(cmd->cmd.scan->ir_scan,
- type, buffer, scan_size, cmd->cmd.scan);
+ jlink_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
}
static void jlink_execute_reset(struct jtag_command *cmd)
{
- DEBUG_JTAG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst,
+ cmd->cmd.reset->srst);
jlink_tap_execute();
jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
@@ -353,7 +167,7 @@ static void jlink_execute_sleep(struct jtag_command *cmd)
jtag_sleep(cmd->cmd.sleep->us);
}
-static void jlink_execute_command(struct jtag_command *cmd)
+static int jlink_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
case JTAG_RUNTEST:
@@ -375,45 +189,54 @@ static void jlink_execute_command(struct jtag_command *cmd)
jlink_execute_sleep(cmd);
break;
default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ LOG_ERROR("BUG: Unknown JTAG command type encountered.");
+ return ERROR_JTAG_QUEUE_FAILED;
}
+
+ return ERROR_OK;
}
static int jlink_execute_queue(void)
{
+ int ret;
struct jtag_command *cmd = jtag_command_queue;
while (cmd != NULL) {
- jlink_execute_command(cmd);
+ ret = jlink_execute_command(cmd);
+
+ if (ret != ERROR_OK)
+ return ret;
+
cmd = cmd->next;
}
return jlink_tap_execute();
}
-/* Sets speed in kHz. */
static int jlink_speed(int speed)
{
- int result;
+ int ret;
if (speed > JLINK_MAX_SPEED) {
- LOG_INFO("reduce speed request: %dkHz to %dkHz maximum",
- speed, JLINK_MAX_SPEED);
+ LOG_INFO("Reduce speed from %d kHz to %d kHz (maximum).", speed,
+ JLINK_MAX_SPEED);
speed = JLINK_MAX_SPEED;
}
- /* check for RTCK setting */
- if (speed == 0)
- speed = -1;
+ if (!speed) {
+ if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_ADAPTIVE_CLOCKING)) {
+ LOG_ERROR("Adaptive clocking is not supported by the device.");
+ return ERROR_JTAG_NOT_IMPLEMENTED;
+ }
+
+ speed = JAYLINK_SPEED_ADAPTIVE_CLOCKING;
+ }
- usb_out_buffer[0] = EMU_CMD_SET_SPEED;
- usb_out_buffer[1] = (speed >> 0) & 0xff;
- usb_out_buffer[2] = (speed >> 8) & 0xff;
+ ret = jaylink_set_speed(devh, speed);
- result = jlink_usb_write(jlink_handle, 3);
- if (result != 3) {
- LOG_ERROR("J-Link setting speed failed (%d)", result);
+ if (ret != JAYLINK_OK) {
+ LOG_ERROR("jaylink_set_speed() failed: %s.",
+ jaylink_strerror_name(ret));
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -434,143 +257,319 @@ static int jlink_khz(int khz, int *jtag_speed)
return ERROR_OK;
}
+static bool read_device_config(struct device_config *cfg)
+{
+ int ret;
+
+ ret = jaylink_read_raw_config(devh, (uint8_t *)cfg);
+
+ if (ret != JAYLINK_OK) {
+ LOG_ERROR("jaylink_read_raw_config() failed: %s.",
+ jaylink_strerror_name(ret));
+ return false;
+ }
+
+ if (cfg->usb_address == 0xff)
+ cfg->usb_address = 0x00;
+
+ if (cfg->target_power == 0xffffffff)
+ cfg->target_power = 0;
+
+ return true;
+}
+
+static int select_interface(void)
+{
+ int ret;
+ uint32_t interfaces;
+
+ if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SELECT_TIF)) {
+ if (iface != JAYLINK_TIF_JTAG) {
+ LOG_ERROR("Device supports JTAG transport only.");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ return ERROR_OK;
+ }
+
+ ret = jaylink_get_available_interfaces(devh, &interfaces);
+
+ if (ret != JAYLINK_OK) {
+ LOG_ERROR("jaylink_get_available_interfaces() failed: %s.",
+ jaylink_strerror_name(ret));
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (!(interfaces & (1 << iface))) {
+ LOG_ERROR("Selected transport is not supported by the device.");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ ret = jaylink_select_interface(devh, iface);
+
+ if (ret < 0) {
+ LOG_ERROR("jaylink_select_interface() failed: %s.",
+ jaylink_strerror_name(ret));
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ return ERROR_OK;
+}
+
static int jlink_register(void)
{
- int result;
- usb_out_buffer[0] = EMU_CMD_REGISTER;
- usb_out_buffer[1] = REG_CMD_REGISTER;
- /* 2 - 11 is "additional parameter",
- * 12 - 13 is connection handle, zero initially */
- memset(&usb_out_buffer[2], 0, 10 + 2);
-
- result = jlink_usb_write(jlink_handle, 14);
- if (result != 14) {
- LOG_ERROR("J-Link register write failed (%d)", result);
- return ERROR_JTAG_DEVICE_ERROR;
+ int ret;
+ int i;
+ bool handle_found;
+
+ if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER))
+ return ERROR_OK;
+
+ ret = jaylink_register(devh, &conn, connlist, NULL, NULL);
+
+ if (ret < 0) {
+ LOG_ERROR("jaylink_register() failed: %s.",
+ jaylink_strerror_name(ret));
+ return ERROR_FAIL;
}
- /* Returns:
- * 0 - 1 connection handle,
- * 2 - 3 number of information entities,
- * 4 - 5 size of a single information struct,
- * 6 - 7 number of additional bytes,
- * 8 - ... reply data
- *
- * Try to read the whole USB bulk packet
- */
- result = jtag_libusb_bulk_read(jlink_handle->usb_handle, jlink_read_ep,
- (char *)usb_in_buffer, sizeof(usb_in_buffer),
- JLINK_USB_TIMEOUT);
- if (!result) {
- LOG_ERROR("J-Link register read failed (0 bytes received)");
- return ERROR_JTAG_DEVICE_ERROR;
+ handle_found = false;
+
+ for (i = 0; i < ret; i++) {
+ if (connlist[i].handle == conn.handle) {
+ handle_found = true;
+ break;
+ }
+ }
+
+ if (!handle_found) {
+ LOG_ERROR("Registration failed: maximum number of connections on the "
+ "device reached.");
+ return ERROR_FAIL;
}
return ERROR_OK;
}
/*
- * select transport interface
- *
- * @param iface [0..31] currently: 0=JTAG, 1=SWD
- * @returns ERROR_OK or ERROR_ code
- *
- * @pre jlink_handle must be opened
- * @pre function may be called only for devices, that have
- * EMU_CAP_SELECT_IF capability enabled
+ * Adjust the SWD transaction buffer size depending on the free device internal
+ * memory. This ensures that the SWD transactions sent to the device do not
+ * exceed the internal memory of the device.
*/
-static int jlink_select_interface(int iface)
+static bool adjust_swd_buffer_size(void)
{
- /* According to Segger's document RM08001-R7 Date: October 8, 2010,
- * http://www.segger.com/admin/uploads/productDocs/RM08001_JLinkUSBProtocol.pdf
- * section 5.5.3 EMU_CMD_SELECT_IF
- * > SubCmd 1..31 to select interface (0..31)
- *
- * The table below states:
- * 0 TIF_JTAG
- * 1 TIF_SWD
- *
- * This obviosly means that to select TIF_JTAG one should write SubCmd = 1.
- *
- * In fact, JTAG interface operates when SubCmd=0
- *
- * It looks like a typo in documentation, because interfaces 0..31 could not
- * be selected by 1..31 range command.
- */
- assert(iface >= 0 && iface < 32);
- int result;
+ int ret;
+ uint32_t tmp;
- /* get available interfaces */