icdi: add TI icdi interface 22/922/16
authorSpencer Oliver <spen@spen-soft.co.uk>
Mon, 12 Nov 2012 15:06:37 +0000 (15:06 +0000)
committerSpencer Oliver <spen@spen-soft.co.uk>
Sun, 23 Dec 2012 21:46:20 +0000 (21:46 +0000)
This is the new proprietary interface replacing the older FTDI based adapters.
It is currently fitted to the ek-lm4f232 and Stellaris LaunchPad.

Change-Id: I794ad79e31ff61ec8e9f49530aca9308025c0b60
Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk>
Reviewed-on: http://openocd.zylin.com/922
Tested-by: jenkins
13 files changed:
README
configure.ac
contrib/openocd.udev
src/helper/binarybuffer.c
src/helper/binarybuffer.h
src/jtag/drivers/Makefile.am
src/jtag/drivers/ti_icdi_usb.c [new file with mode: 0644]
src/jtag/hla/hla_layout.c
src/jtag/hla/hla_layout.h
tcl/board/ek-lm4f120xl.cfg [new file with mode: 0644]
tcl/board/ek-lm4f232.cfg
tcl/interface/ti-icdi.cfg [new file with mode: 0644]
tcl/target/stellaris_icdi.cfg [new file with mode: 0644]

diff --git a/README b/README
index 7b1f4a2af072642cbbb1592dadae70f1a117df54..08aa4f2a0a585804a2d74f0a4191abc7fd6d57ec 100644 (file)
--- a/README
+++ b/README
@@ -275,6 +275,8 @@ options may be available there:
 
   --enable-stlink         Enable building support for the ST-Link JTAG
                           Programmer
+  --enable-ti-icdi        Enable building support for the TI/Stellaris ICDI
+                          JTAG Programmer
 
   --enable-osbdm          Enable building support for the OSBDM (JTAG only)
                           Programmer
index 99f39d4fa3fdb44b6e876b2eaeb189f3ba5af089..51d43baacde696bf285bec8aaf2dbf90c28ee4e8 100644 (file)
@@ -477,7 +477,11 @@ AC_ARG_ENABLE([buspirate],
 
 AC_ARG_ENABLE([stlink],
   AS_HELP_STRING([--enable-stlink], [Enable building support for the ST-Link JTAG Programmer]),
-  [build_hladapter=$enableval], [build_hladapter=no])
+  [build_hladapter_stlink=$enableval], [build_hladapter_stlink=no])
+
+AC_ARG_ENABLE([ti-icdi],
+  AS_HELP_STRING([--enable-ti-icdi], [Enable building support for the TI ICDI JTAG Programmer]),
+  [build_hladapter_icdi=$enableval], [build_hladapter_icdi=no])
 
 AC_ARG_ENABLE([osbdm],
   AS_HELP_STRING([--enable-osbdm], [Enable building support for the OSBDM (JTAG only) Programmer]),
@@ -790,10 +794,10 @@ else
   AC_DEFINE([BUILD_BUSPIRATE], [0], [0 if you don't want the Buspirate JTAG driver.])
 fi
 
-if test $build_hladapter = yes; then
-  AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the ST-Link JTAG driver.])
+if test $build_hladapter_stlink = yes -o $build_hladapter_icdi = yes; then
+  AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.])
 else
-  AC_DEFINE([BUILD_HLADAPTER], [0], [0 if you don't want the ST-Link JTAG driver.])
+  AC_DEFINE([BUILD_HLADAPTER], [0], [0 if you don't want the High Level JTAG driver.])
 fi
 
 if test $build_osbdm = yes; then
@@ -1142,8 +1146,8 @@ fi
 
 # Check for libusb1 ported drivers.
 build_usb_ng=no
-if test $build_jlink = yes -o $build_hladapter = yes -o $build_osbdm = yes -o \
-  $build_opendous = yes -o $build_ftdi = yes
+if test $build_jlink = yes -o $build_hladapter_stlink = yes -o $build_osbdm = yes -o \
+  $build_opendous = yes -o $build_ftdi = yes -o $build_hladapter_icdi = yes
 then
   build_usb_ng=yes
 fi
@@ -1192,7 +1196,7 @@ AM_CONDITIONAL([ULINK], [test $build_ulink = yes])
 AM_CONDITIONAL([ARMJTAGEW], [test $build_armjtagew = yes])
 AM_CONDITIONAL([REMOTE_BITBANG], [test $build_remote_bitbang = yes])
 AM_CONDITIONAL([BUSPIRATE], [test $build_buspirate = yes])
-AM_CONDITIONAL([HLADAPTER], [test $build_hladapter = yes])
+AM_CONDITIONAL([HLADAPTER], [test $build_hladapter_stlink = yes -o $build_hladapter_icdi = yes])
 AM_CONDITIONAL([OSBDM], [test $build_osbdm = yes])
 AM_CONDITIONAL([OPENDOUS], [test $build_opendous = yes])
 AM_CONDITIONAL([SYSFSGPIO], [test $build_sysfsgpio = yes])
index 5d4e63961cda250226d1c9842ec7e239728ce7c2..7065014a309156d1080f043141a02495cbfc2c43 100644 (file)
@@ -49,12 +49,15 @@ ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="664", GROUP="plugdev"
 # Hitex STM32-PerformanceStick
 ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="664", GROUP="plugdev"
 
-# TI/Luminary Stellaris Evaluation Board (several)
+# TI/Luminary Stellaris Evaluation Board FTDI (several)
 ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="664", GROUP="plugdev"
 
-# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
+# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board
 ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="664", GROUP="plugdev"
 
+# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
+ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="664", GROUP="plugdev"
+
 # Xverve Signalyzer Tool (DT-USB-ST)
 ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="664", GROUP="plugdev"
 
index d98fa16212f04138f5c751d507112ed05c2f64fc..a90ec7b01ebab7dc3b928104df4badb77d38e59a 100644 (file)
@@ -370,3 +370,30 @@ void bit_copy_discard(struct bit_copy_queue *q)
                free(qe);
        }
 }
+
+int unhexify(char *bin, const char *hex, int count)
+{
+       int i, tmp;
+
+       for (i = 0; i < count; i++) {
+               if (sscanf(hex + (2 * i), "%02x", &tmp) != 1)
+                       return i;
+               bin[i] = tmp;
+       }
+
+       return i;
+}
+
+int hexify(char *hex, const char *bin, int count, int out_maxlen)
+{
+       int i, cmd_len = 0;
+
+       /* May use a length, or a null-terminated string as input. */
+       if (count == 0)
+               count = strlen(bin);
+
+       for (i = 0; i < count; i++)
+               cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i]);
+
+       return cmd_len;
+}
index cc0be57dcfbac7dcda4160d3d3b468236c36f821..633ed9e5dc6aa111189f9ed4a646c56357903d25 100644 (file)
@@ -156,4 +156,9 @@ int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset,
 void bit_copy_execute(struct bit_copy_queue *q);
 void bit_copy_discard(struct bit_copy_queue *q);
 
+/* functions to convert to/from hex encoded buffer
+ * used in ti-icdi driver and gdb server */
+int unhexify(char *bin, const char *hex, int count);
+int hexify(char *hex, const char *bin, int count, int out_maxlen);
+
 #endif /* BINARYBUFFER_H */
index 6d232d26f64c58fb6b2c51698165fc8e8225dbf6..e064399b5c559d329286372a7063f9364b7a1963 100644 (file)
@@ -100,6 +100,7 @@ DRIVERFILES += remote_bitbang.c
 endif
 if HLADAPTER
 DRIVERFILES += stlink_usb.c
+DRIVERFILES += ti_icdi_usb.c
 endif
 if OSBDM
 DRIVERFILES += osbdm.c
diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c
new file mode 100644 (file)
index 0000000..6729522
--- /dev/null
@@ -0,0 +1,730 @@
+/***************************************************************************
+ *                                                                         *
+ *   Copyright (C) 2012 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   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
+
+/* project specific includes */
+#include <helper/binarybuffer.h>
+#include <jtag/interface.h>
+#include <jtag/hla/hla_layout.h>
+#include <jtag/hla/hla_transport.h>
+#include <jtag/hla/hla_interface.h>
+#include <target/target.h>
+
+#include <target/cortex_m.h>
+
+#include <libusb-1.0/libusb.h>
+
+#define ICDI_WRITE_ENDPOINT 0x02
+#define ICDI_READ_ENDPOINT 0x83
+
+#define ICDI_WRITE_TIMEOUT 1000
+#define ICDI_READ_TIMEOUT 1000
+#define ICDI_PACKET_SIZE 2048
+
+#define PACKET_START "$"
+#define PACKET_END "#"
+
+struct icdi_usb_handle_s {
+       libusb_context *usb_ctx;
+       libusb_device_handle *usb_dev;
+
+       char *read_buffer;
+       char *write_buffer;
+       int max_packet;
+       int read_count;
+};
+
+static int icdi_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, uint8_t *buffer);
+static int icdi_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer);
+
+static int remote_escape_output(const char *buffer, int len, char *out_buf, int *out_len, int out_maxlen)
+{
+       int input_index, output_index;
+
+       output_index = 0;
+
+       for (input_index = 0; input_index < len; input_index++) {
+
+               char b = buffer[input_index];
+
+               if (b == '$' || b == '#' || b == '}' || b == '*') {
+                       /* These must be escaped.  */
+                       if (output_index + 2 > out_maxlen)
+                               break;
+                       out_buf[output_index++] = '}';
+                       out_buf[output_index++] = b ^ 0x20;
+               } else {
+                       if (output_index + 1 > out_maxlen)
+                               break;
+                       out_buf[output_index++] = b;
+               }
+       }
+
+       *out_len = input_index;
+       return output_index;
+}
+
+static int remote_unescape_input(const char *buffer, int len, char *out_buf, int out_maxlen)
+{
+       int input_index, output_index;
+       int escaped;
+
+       output_index = 0;
+       escaped = 0;
+
+       for (input_index = 0; input_index < len; input_index++) {
+
+               char b = buffer[input_index];
+
+               if (output_index + 1 > out_maxlen)
+                       LOG_ERROR("Received too much data from the target.");
+
+               if (escaped) {
+                       out_buf[output_index++] = b ^ 0x20;
+                       escaped = 0;
+               } else if (b == '}')
+                       escaped = 1;
+               else
+                       out_buf[output_index++] = b;
+       }
+
+       if (escaped)
+               LOG_ERROR("Unmatched escape character in target response.");
+
+       return output_index;
+}
+
+static int icdi_send_packet(void *handle, int len)
+{
+       unsigned char cksum = 0;
+       struct icdi_usb_handle_s *h;
+       int result, retry = 0;
+       int transferred = 0;
+
+       assert(handle != NULL);
+       h = (struct icdi_usb_handle_s *)handle;
+
+       /* check we have a large enough buffer for checksum "#00" */
+       if (len + 3 > h->max_packet) {
+               LOG_ERROR("packet buffer too small");
+               return ERROR_FAIL;
+       }
+
+       /* calculate checksum - offset start of packet */
+       for (int i = 1; i < len; i++)
+               cksum += h->write_buffer[i];
+
+       len += sprintf(&h->write_buffer[len], PACKET_END "%02x", cksum);
+
+#ifdef _DEBUG_USB_COMMS_
+       char buffer[50];
+       char ch = h->write_buffer[1];
+       if (ch == 'x' || ch == 'X')
+               LOG_DEBUG("writing packet: <binary>");
+       else {
+               memcpy(buffer, h->write_buffer, len >= 50 ? 50-1 : len);
+               buffer[len] = 0;
+               LOG_DEBUG("writing packet: %s", buffer);
+       }
+#endif
+
+       while (1) {
+
+               result = libusb_bulk_transfer(h->usb_dev, ICDI_WRITE_ENDPOINT, (unsigned char *)h->write_buffer, len,
+                               &transferred, ICDI_WRITE_TIMEOUT);
+               if (result != 0 || transferred != len) {
+                       LOG_DEBUG("Error TX Data %d", result);
+                       return ERROR_FAIL;
+               }
+
+               /* check that the client got the message ok, or shall we resend */
+               result = libusb_bulk_transfer(h->usb_dev, ICDI_READ_ENDPOINT, (unsigned char *)h->read_buffer, h->max_packet,
+                                       &transferred, ICDI_READ_TIMEOUT);
+               if (result != 0 || transferred < 1) {
+                       LOG_DEBUG("Error RX Data %d", result);
+                       return ERROR_FAIL;
+               }
+
+#ifdef _DEBUG_USB_COMMS_
+               LOG_DEBUG("received reply: '%c' : count %d", h->read_buffer[0], transferred);
+#endif
+
+               if (h->read_buffer[0] == '-') {
+                       LOG_DEBUG("Resending packet %d", ++retry);
+               } else {
+                       if (h->read_buffer[0] != '+')
+                               LOG_DEBUG("Unexpected Reply from ICDI: %c", h->read_buffer[0]);
+                       break;
+               }
+
+               if (retry == 3) {
+                       LOG_DEBUG("maximum nack retries attempted");
+                       return ERROR_FAIL;
+               }
+       }
+
+       retry = 0;
+       h->read_count = transferred;
+
+       while (1) {
+
+               /* read reply from icdi */
+               result = libusb_bulk_transfer(h->usb_dev, ICDI_READ_ENDPOINT, (unsigned char *)h->read_buffer + h->read_count,
+                               h->max_packet - h->read_count, &transferred, ICDI_READ_TIMEOUT);
+
+#ifdef _DEBUG_USB_COMMS_
+               LOG_DEBUG("received data: count %d", transferred);
+#endif
+
+               /* check for errors but retry for timeout */
+               if (result != 0) {
+
+                       if (result == LIBUSB_ERROR_TIMEOUT) {
+                               LOG_DEBUG("Error RX timeout %d", result);
+                       } else {
+                               LOG_DEBUG("Error RX Data %d", result);
+                               return ERROR_FAIL;
+                       }
+               }
+
+               h->read_count += transferred;
+
+               /* we need to make sure we have a full packet, including checksum */
+               if (h->read_count > 5) {
+
+                       /* check that we have received an packet delimiter
+                        * we do not validate the checksum
+                        * reply should contain $...#AA - so we check for # */
+                       if (h->read_buffer[h->read_count - 3] == '#')
+                               return ERROR_OK;
+               }
+
+               if (retry++ == 3) {
+                       LOG_DEBUG("maximum data retries attempted");
+                       break;
+               }
+       }
+
+       return ERROR_FAIL;
+}
+
+static int icdi_send_cmd(void *handle, const char *cmd)
+{
+       struct icdi_usb_handle_s *h;
+       h = (struct icdi_usb_handle_s *)handle;
+
+       int cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "%s", cmd);
+       return icdi_send_packet(handle, cmd_len);
+}
+
+static int icdi_send_remote_cmd(void *handle, const char *data)
+{
+       struct icdi_usb_handle_s *h;
+       h = (struct icdi_usb_handle_s *)handle;
+
+       size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,");
+       cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len);
+
+       return icdi_send_packet(handle, cmd_len);
+}
+
+static int icdi_get_cmd_result(void *handle)
+{
+       struct icdi_usb_handle_s *h;
+       int offset = 0;
+       char ch;
+
+       assert(handle != NULL);
+       h = (struct icdi_usb_handle_s *)handle;
+
+       do {
+               ch = h->read_buffer[offset++];
+               if (offset > h->read_count)
+                       return ERROR_FAIL;
+       } while (ch != '$');
+
+       if (memcmp("OK", h->read_buffer + offset, 2) == 0)
+               return ERROR_OK;
+
+       if (h->read_buffer[offset] == 'E') {
+               /* get error code */
+               char result;
+               if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1)
+                       return ERROR_FAIL;
+               return result;
+       }
+
+       /* for now we assume everything else is ok */
+       return ERROR_OK;
+}
+
+static int icdi_usb_idcode(void *handle, uint32_t *idcode)
+{
+       return ERROR_OK;
+}
+
+static int icdi_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
+{
+       return icdi_usb_write_mem32(handle, addr, 1, (uint8_t *)&val);
+}
+
+static enum target_state icdi_usb_state(void *handle)
+{
+       int result;
+       struct icdi_usb_handle_s *h;
+       uint32_t dhcsr;
+
+       h = (struct icdi_usb_handle_s *)handle;
+
+       result = icdi_usb_read_mem32(h, DCB_DHCSR, 1, (uint8_t *)&dhcsr);
+       if (result != ERROR_OK)
+               return TARGET_UNKNOWN;
+
+       if (dhcsr & S_HALT)
+               return TARGET_HALTED;
+
+       return TARGET_RUNNING;
+}
+
+static int icdi_usb_version(void *handle)
+{
+       struct icdi_usb_handle_s *h;
+       h = (struct icdi_usb_handle_s *)handle;
+
+       char version[20];
+
+       /* get info about icdi */
+       int result = icdi_send_remote_cmd(handle, "version");
+       if (result != ERROR_OK)
+               return result;
+
+       if (h->read_count < 8) {
+               LOG_ERROR("Invalid Reply Received");
+               return ERROR_FAIL;
+       }
+
+       /* convert reply */
+       if (unhexify(version, h->read_buffer + 2, 4) != 4) {
+               LOG_WARNING("unable to get ICDI version");
+               return ERROR_OK;
+       }
+
+       /* null terminate and print info */
+       version[4] = 0;
+
+       LOG_INFO("ICDI Firmware version: %s", version);
+
+       return ERROR_OK;
+}
+
+static int icdi_usb_query(void *handle)
+{
+       int result;
+
+       struct icdi_usb_handle_s *h;
+       h = (struct icdi_usb_handle_s *)handle;
+
+       result = icdi_send_cmd(handle, "qSupported");
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("query supported failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       /* from this we can get the max packet supported */
+
+       /* query packet buffer size */
+       char *offset = strstr(h->read_buffer, "PacketSize");
+       if (offset) {
+               char *separator;
+               int max_packet;
+
+               max_packet = strtoul(offset + 11, &separator, 16);
+               if (!max_packet)
+                       LOG_ERROR("invalid max packet, using defaults");
+               else
+                       h->max_packet = max_packet;
+               LOG_DEBUG("max packet supported : %" PRIu32 " bytes", h->max_packet);
+       }
+
+
+       /* if required re allocate packet buffer */
+       if (h->max_packet != ICDI_PACKET_SIZE) {
+               h->read_buffer = realloc(h->read_buffer, h->max_packet);
+               h->write_buffer = realloc(h->write_buffer, h->max_packet);
+               if (h->read_buffer == 0 || h->write_buffer == 0) {
+                       LOG_ERROR("unable to reallocate memory");
+                       return ERROR_FAIL;
+               }
+       }
+
+       /* set extended mode */
+       result = icdi_send_cmd(handle, "!");
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("unable to enable extended mode: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int icdi_usb_reset(void *handle)
+{
+       /* we do this in hla_target.c */
+       return ERROR_OK;
+}
+
+static int icdi_usb_assert_srst(void *handle, int srst)
+{
+       /* TODO not supported yet */
+       return ERROR_COMMAND_NOTFOUND;
+}
+
+static int icdi_usb_run(void *handle)
+{
+       int result;
+
+       /* resume target at current address */
+       result = icdi_send_cmd(handle, "c");
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("continue failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       return result;
+}
+
+static int icdi_usb_halt(void *handle)
+{
+       int result;
+
+       /* this query halts the target ?? */
+       result = icdi_send_cmd(handle, "?");
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("halt failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       return result;
+}
+
+static int icdi_usb_step(void *handle)
+{
+       int result;
+
+       /* step target at current address */
+       result = icdi_send_cmd(handle, "s");
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("step failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       return result;
+}
+
+static int icdi_usb_read_regs(void *handle)
+{
+       /* currently unsupported */
+       return ERROR_OK;
+}
+
+static int icdi_usb_read_reg(void *handle, int num, uint32_t *val)
+{
+       int result;
+       struct icdi_usb_handle_s *h;
+       char cmd[10];
+
+       h = (struct icdi_usb_handle_s *)handle;
+
+       snprintf(cmd, sizeof(cmd), "p%x", num);
+       result = icdi_send_cmd(handle, cmd);
+       if (result != ERROR_OK)
+               return result;
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("register read failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       /* convert result */
+       if (unhexify((char *)val, h->read_buffer + 2, 4) != 4) {
+               LOG_ERROR("failed to convert result");
+               return ERROR_FAIL;
+       }
+
+       return result;
+}
+
+static int icdi_usb_write_reg(void *handle, int num, uint32_t val)
+{
+       int result;
+       char cmd[20];
+
+       int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num);
+       hexify(cmd + cmd_len, (char *)&val, 4, sizeof(cmd));
+
+       result = icdi_send_cmd(handle, cmd);
+       if (result != ERROR_OK)
+               return result;
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("register write failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       return result;
+}
+
+static int icdi_usb_read_mem(void *handle, uint32_t addr, uint32_t len, uint8_t *buffer)
+{
+       int result;
+       struct icdi_usb_handle_s *h;
+       char cmd[20];
+
+       h = (struct icdi_usb_handle_s *)handle;
+
+       snprintf(cmd, sizeof(cmd), "x%x,%x", addr, len);
+       result = icdi_send_cmd(handle, cmd);
+       if (result != ERROR_OK)
+               return result;
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("memory read failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       /* unescape input */
+       int read_len = remote_unescape_input(h->read_buffer + 5, h->read_count - 8, (char *)buffer, len);
+       if (read_len != (int)len) {
+               LOG_ERROR("read more bytes than expected: actual 0x%" PRIx32 " expected 0x%" PRIx32, read_len, len);
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int icdi_usb_write_mem(void *handle, uint32_t addr, uint32_t len, const uint8_t *buffer)
+{
+       int result;
+       struct icdi_usb_handle_s *h;
+
+       h = (struct icdi_usb_handle_s *)handle;
+
+       size_t cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "X%x,%x:", addr, len);
+
+       int out_len;
+       cmd_len += remote_escape_output((char *)buffer, len, h->write_buffer + cmd_len,
+                       &out_len, h->max_packet - cmd_len);
+
+       if (out_len < (int)len) {
+               /* for now issue a error as we have no way of allocating a larger buffer */
+               LOG_ERROR("memory buffer too small: requires 0x%" PRIx32 " actual 0x%" PRIx32, out_len, len);
+               return ERROR_FAIL;
+       }
+
+       result = icdi_send_packet(handle, cmd_len);
+       if (result != ERROR_OK)
+               return result;
+
+       /* check result */
+       result = icdi_get_cmd_result(handle);
+       if (result != ERROR_OK) {
+               LOG_ERROR("memory write failed: 0x%x", result);
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int icdi_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, uint8_t *buffer)
+{
+       return icdi_usb_read_mem(handle, addr, len, buffer);
+}
+
+static int icdi_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer)
+{
+       return icdi_usb_write_mem(handle, addr, len, buffer);
+}
+
+static int icdi_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, uint8_t *buffer)
+{
+       return icdi_usb_read_mem(handle, addr, len * 4, buffer);
+}
+
+static int icdi_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer)
+{
+       return icdi_usb_write_mem(handle, addr, len * 4, buffer);
+}
+
+static int icdi_usb_close(void *handle)
+{
+       struct icdi_usb_handle_s *h;
+
+       h = (struct icdi_usb_handle_s *)handle;
+
+       if (h->usb_dev)
+               libusb_close(h->usb_dev);
+
+       if (h->usb_ctx)
+               libusb_exit(h->usb_ctx);
+
+       if (h->read_buffer)
+               free(h->read_buffer);
+
+       if (h->write_buffer)
+               free(h->write_buffer);
+
+       free(handle);
+
+       return ERROR_OK;
+}
+
+static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
+{
+       int retval;
+       struct icdi_usb_handle_s *h;
+
+       LOG_DEBUG("icdi_usb_open");
+
+       h = calloc(1, sizeof(struct icdi_usb_handle_s));
+
+       if (h == 0) {
+               LOG_ERROR("unable to allocate memory");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport,
+               param->vid, param->pid);
+
+       if (libusb_init(&h->usb_ctx) != 0) {
+               LOG_ERROR("libusb init failed");
+               goto error_open;
+       }
+
+       h->usb_dev = libusb_open_device_with_vid_pid(h->usb_ctx, param->vid, param->pid);
+       if (!h->usb_dev) {
+               LOG_ERROR("open failed");
+               goto error_open;
+       }
+
+       if (libusb_claim_interface(h->usb_dev, 2)) {
+               LOG_DEBUG("claim interface failed");
+               goto error_open;
+       }
+
+       /* check if mode is supported */
+       retval = ERROR_OK;
+
+       switch (param->transport) {
+#if 0
+               /* TODO place holder as swd is not currently supported */
+               case HL_TRANSPORT_SWD:
+#endif
+               case HL_TRANSPORT_JTAG:
+                       break;
+               default:
+                       retval = ERROR_FAIL;
+                       break;
+       }
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("mode (transport) not supported by device");
+               goto error_open;
+       }
+
+       /* allocate buffer */
+       h->read_buffer = malloc(ICDI_PACKET_SIZE);
+       h->write_buffer = malloc(ICDI_PACKET_SIZE);
+       h->max_packet = ICDI_PACKET_SIZE;
+
+       if (h->read_buffer == 0 || h->write_buffer == 0) {
+               LOG_DEBUG("malloc failed");
+               goto error_open;
+       }
+
+       /* query icdi version etc */
+       retval = icdi_usb_version(h);
+       if (retval != ERROR_OK)
+               goto error_open;
+
+       /* query icdi support */
+       retval = icdi_usb_query(h);
+       if (retval != ERROR_OK)
+               goto error_open;
+
+       *fd = h;
+
+       /* set the max target read/write buffer in bytes
+        * as we are using gdb binary packets to transfer memory we have to
+        * reserve half the buffer for any possible escape chars plus
+        * at least 64 bytes for the gdb packet header */
+       param->max_buffer = (((h->max_packet - 64) / 4) * 4) / 2;
+
+       return ERROR_OK;
+
+error_open:
+       icdi_usb_close(h);
+
+       return ERROR_FAIL;
+}
+
+struct hl_layout_api_s icdi_usb_layout_api = {
+       .open = icdi_usb_open,
+       .close = icdi_usb_close,
+       .idcode = icdi_usb_idcode,
+       .state = icdi_usb_state,
+       .reset = icdi_usb_reset,
+       .assert_srst = icdi_usb_assert_srst,
+       .run = icdi_usb_run,
+       .halt = icdi_usb_halt,
+       .step = icdi_usb_step,
+       .read_regs = icdi_usb_read_regs,
+       .read_reg = icdi_usb_read_reg,
+       .write_reg = icdi_usb_write_reg,
+       .read_mem8 = icdi_usb_read_mem8,
+       .write_mem8 = icdi_usb_write_mem8,
+       .read_mem32 = icdi_usb_read_mem32,
+       .write_mem32 = icdi_usb_write_mem32,
+       .write_debug_reg = icdi_usb_write_debug_reg
+};
index 55657294c250f738c0a8165a6bf2e38194798272..54c531401f281a5c01fc5e5bf9dd21de0f22e8d8 100644 (file)
@@ -71,6 +71,12 @@ static const struct hl_layout hl_layouts[] = {
         .close = hl_layout_close,
         .api = &stlink_usb_layout_api,
         },
+       {
+        .name = "ti-icdi",
+        .open = hl_layout_open,
+        .close = hl_layout_close,
+        .api = &icdi_usb_layout_api,
+       },
        {.name = NULL, /* END OF TABLE */ },
 };
 
index 982d71a8644efbc4729abd8a2b677a90f8bda697..3fd361eace5e2a5c84f900f87ec069a38069ed10 100644 (file)
@@ -30,6 +30,7 @@ struct hl_interface_param_s;
 
 /** */
 extern struct hl_layout_api_s stlink_usb_layout_api;
+extern struct hl_layout_api_s icdi_usb_layout_api;
 
 /** */
 struct hl_layout_api_s {
diff --git a/tcl/board/ek-lm4f120xl.cfg b/tcl/board/ek-lm4f120xl.cfg
new file mode 100644 (file)
index 0000000..aa6935c
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# TI Stellaris Launchpad ek-lm4f120xl Evaluation Kits
+#
+# http://www.ti.com/tool/ek-lm4f120xl
+#
+
+#
+# NOTE: using the bundled ICDI interface is optional!
+# This interface is not ftdi based as previous boards were
+#
+source [find interface/ti-icdi.cfg]
+
+set WORKAREASIZE 0x8000
+set CHIPNAME lm4f120h5qr
+source [find target/stellaris_icdi.cfg]
index 6e3f8e3192832b18e4aeebdf48263f83d02ffd3e..ebbc01d305e5e20f0d0bc342a99c57ca2f83faa1 100644 (file)
@@ -4,10 +4,12 @@
 # http://www.ti.com/tool/ek-lm4f232
 #
 
-# NOTE:  using the bundled FT2232 JTAG/SWD/SWO interface is optional!
-# so is using in JTAG mode, as done here.
-source [find interface/luminary-icdi.cfg]
+#
+# NOTE: using the bundled ICDI interface is optional!
+# This interface is not ftdi based as previous boards were
+#
+source [find interface/ti-icdi.cfg]
 
 set WORKAREASIZE 0x8000
 set CHIPNAME lm4f23x
-source [find target/stellaris.cfg]
+source [find target/stellaris_icdi.cfg]
diff --git a/tcl/interface/ti-icdi.cfg b/tcl/interface/ti-icdi.cfg
new file mode 100644 (file)
index 0000000..16a901e
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# TI Stellaris In-Circuit Debug Interface (ICDI) Board
+#
+# This is the propriety ICDI interface used on newer boards such as
+# LM4F232 Evaluation Kit - http://www.ti.com/tool/ek-lm4f232
+# Stellaris Launchpad - http://www.ti.com/stellaris-launchpad
+# http://www.ti.com/tool/ek-lm4f232
+#
+
+interface hla
+hla_layout ti-icdi
+hla_vid_pid 0x1cbe 0x00fd
+
+# unused but set to disable warnings
+adapter_khz 1000
diff --git a/tcl/target/stellaris_icdi.cfg b/tcl/target/stellaris_icdi.cfg
new file mode 100644 (file)
index 0000000..11d57c2
--- /dev/null
@@ -0,0 +1,34 @@
+#
+# lm3s icdi pseudo target
+#
+
+if { [info exists CHIPNAME] } {
+   set _CHIPNAME $CHIPNAME
+} else {
+   set _CHIPNAME lm3s
+}
+
+# Work-area is a space in RAM used for flash programming
+# By default use 16kB
+if { [info exists WORKAREASIZE] } {
+   set _WORKAREASIZE $WORKAREASIZE
+} else {
+   set _WORKAREASIZE 0x4000
+}
+
+#
+# possible value are hla_jtag
+# currently swd is not supported
+#
+transport select hla_jtag
+
+# do not check id as icdi currently does not support it
+hla newtap $_CHIPNAME cpu -expected-id 0
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME hla_target -chain-position $_TARGETNAME
+
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
+
+# flash configuration ... autodetects sizes, autoprobed
+flash bank $_CHIPNAME.flash stellaris 0 0 0 0 $_TARGETNAME

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)