aboutsummaryrefslogtreecommitdiff
path: root/src/jtag
diff options
context:
space:
mode:
Diffstat (limited to 'src/jtag')
-rw-r--r--src/jtag/Makefile.am2
-rw-r--r--src/jtag/adapter.c231
-rw-r--r--src/jtag/aice/aice_interface.c15
-rw-r--r--src/jtag/aice/aice_transport.c6
-rw-r--r--src/jtag/aice/aice_usb.c86
-rw-r--r--src/jtag/aice/aice_usb.h2
-rw-r--r--src/jtag/commands.c14
-rw-r--r--src/jtag/core.c344
-rw-r--r--src/jtag/drivers/Makefile.am16
-rw-r--r--src/jtag/drivers/amt_jtagaccel.c11
-rw-r--r--src/jtag/drivers/arm-jtag-ew.c36
-rw-r--r--src/jtag/drivers/at91rm9200.c13
-rw-r--r--src/jtag/drivers/bcm2835gpio.c27
-rw-r--r--src/jtag/drivers/bitbang.c11
-rw-r--r--src/jtag/drivers/bitbang.h3
-rw-r--r--src/jtag/drivers/buspirate.c35
-rw-r--r--src/jtag/drivers/cmsis_dap_usb.c58
-rw-r--r--src/jtag/drivers/dummy.c30
-rw-r--r--src/jtag/drivers/ep93xx.c12
-rw-r--r--src/jtag/drivers/ft232r.c44
-rw-r--r--src/jtag/drivers/ftdi.c74
-rw-r--r--src/jtag/drivers/gw16012.c13
-rw-r--r--src/jtag/drivers/imx_gpio.c21
-rw-r--r--src/jtag/drivers/jlink.c167
-rw-r--r--src/jtag/drivers/jtag_vpi.c229
-rw-r--r--src/jtag/drivers/kitprog.c91
-rw-r--r--src/jtag/drivers/libusb0_common.c196
-rw-r--r--src/jtag/drivers/libusb0_common.h74
-rw-r--r--src/jtag/drivers/libusb_common.h27
-rw-r--r--src/jtag/drivers/libusb_helper.c (renamed from src/jtag/drivers/libusb1_common.c)123
-rw-r--r--src/jtag/drivers/libusb_helper.h (renamed from src/jtag/drivers/libusb1_common.h)53
-rw-r--r--src/jtag/drivers/mpsse.c9
-rw-r--r--src/jtag/drivers/opendous.c34
-rw-r--r--src/jtag/drivers/openjtag.c42
-rw-r--r--src/jtag/drivers/osbdm.c39
-rw-r--r--src/jtag/drivers/parport.c17
-rw-r--r--src/jtag/drivers/presto.c13
-rw-r--r--src/jtag/drivers/remote_bitbang.c12
-rw-r--r--src/jtag/drivers/rlink.c12
-rw-r--r--src/jtag/drivers/rlink_call.m42
-rw-r--r--src/jtag/drivers/rlink_speed_table.c1
-rw-r--r--src/jtag/drivers/rshim.c523
-rw-r--r--src/jtag/drivers/stlink_usb.c1155
-rw-r--r--src/jtag/drivers/sysfsgpio.c60
-rw-r--r--src/jtag/drivers/ulink.c70
-rw-r--r--src/jtag/drivers/usb_blaster/ublast2_access_libusb.c49
-rw-r--r--src/jtag/drivers/usb_blaster/ublast_access.h4
-rw-r--r--src/jtag/drivers/usb_blaster/usb_blaster.c20
-rw-r--r--src/jtag/drivers/usbprog.c13
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c2
-rw-r--r--src/jtag/drivers/versaloon/versaloon_internal.h2
-rw-r--r--src/jtag/drivers/vsllink.c40
-rw-r--r--src/jtag/drivers/xds110.c353
-rw-r--r--src/jtag/drivers/xlnx-pcie-xvc.c487
-rw-r--r--src/jtag/hla/hla_interface.c32
-rw-r--r--src/jtag/hla/hla_interface.h2
-rw-r--r--src/jtag/hla/hla_layout.h6
-rw-r--r--src/jtag/hla/hla_transport.c14
-rw-r--r--src/jtag/hla/hla_transport.h1
-rw-r--r--src/jtag/interface.c4
-rw-r--r--src/jtag/interface.h83
-rw-r--r--src/jtag/interfaces.c157
-rw-r--r--src/jtag/interfaces.h5
-rw-r--r--src/jtag/jtag.h12
-rw-r--r--src/jtag/minidummy/minidummy.c16
-rw-r--r--src/jtag/startup.tcl88
-rw-r--r--src/jtag/swd.h9
-rw-r--r--src/jtag/swim.c153
-rw-r--r--src/jtag/swim.h68
-rw-r--r--src/jtag/tcl.c61
-rw-r--r--src/jtag/zy1000/zy1000.c14
71 files changed, 4244 insertions, 1504 deletions
diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am
index a764863..b82914b 100644
--- a/src/jtag/Makefile.am
+++ b/src/jtag/Makefile.am
@@ -56,6 +56,7 @@ endif
%D%/interface.c \
%D%/interfaces.c \
%D%/tcl.c \
+ %D%/swim.c \
%D%/commands.h \
%D%/driver.h \
%D%/interface.h \
@@ -65,6 +66,7 @@ endif
%D%/minidriver/minidriver_imp.h \
%D%/minidummy/jtag_minidriver.h \
%D%/swd.h \
+ %D%/swim.h \
%D%/tcl.h \
$(JTAG_SRCS)
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 29a9613..af75917 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -46,7 +46,7 @@
* Holds support for configuring debug adapters from TCl scripts.
*/
-extern struct jtag_interface *jtag_interface;
+struct adapter_driver *adapter_driver;
const char * const jtag_only[] = { "jtag", NULL };
static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
@@ -61,12 +61,12 @@ static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
return JIM_ERR;
}
- const char *name = jtag_interface ? jtag_interface->name : NULL;
+ const char *name = adapter_driver ? adapter_driver->name : NULL;
Jim_SetResultString(goi.interp, name ? : "undefined", -1);
return JIM_OK;
}
-COMMAND_HANDLER(interface_transport_command)
+COMMAND_HANDLER(adapter_transports_command)
{
char **transports;
int retval;
@@ -85,26 +85,26 @@ COMMAND_HANDLER(interface_transport_command)
return retval;
}
-COMMAND_HANDLER(handle_interface_list_command)
+COMMAND_HANDLER(handle_adapter_list_command)
{
- if (strcmp(CMD_NAME, "interface_list") == 0 && CMD_ARGC > 0)
+ if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0)
return ERROR_COMMAND_SYNTAX_ERROR;
- command_print(CMD, "The following debug interfaces are available:");
- for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) {
- const char *name = jtag_interfaces[i]->name;
+ command_print(CMD, "The following debug adapters are available:");
+ for (unsigned i = 0; NULL != adapter_drivers[i]; i++) {
+ const char *name = adapter_drivers[i]->name;
command_print(CMD, "%u: %s", i + 1, name);
}
return ERROR_OK;
}
-COMMAND_HANDLER(handle_interface_command)
+COMMAND_HANDLER(handle_adapter_driver_command)
{
int retval;
/* check whether the interface is already configured */
- if (jtag_interface) {
+ if (adapter_driver) {
LOG_WARNING("Interface already configured, ignoring");
return ERROR_OK;
}
@@ -113,20 +113,20 @@ COMMAND_HANDLER(handle_interface_command)
if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0')
return ERROR_COMMAND_SYNTAX_ERROR;
- for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) {
- if (strcmp(CMD_ARGV[0], jtag_interfaces[i]->name) != 0)
+ for (unsigned i = 0; NULL != adapter_drivers[i]; i++) {
+ if (strcmp(CMD_ARGV[0], adapter_drivers[i]->name) != 0)
continue;
- if (NULL != jtag_interfaces[i]->commands) {
+ if (NULL != adapter_drivers[i]->commands) {
retval = register_commands(CMD_CTX, NULL,
- jtag_interfaces[i]->commands);
+ adapter_drivers[i]->commands);
if (ERROR_OK != retval)
return retval;
}
- jtag_interface = jtag_interfaces[i];
+ adapter_driver = adapter_drivers[i];
- return allow_transports(CMD_CTX, jtag_interface->transports);
+ return allow_transports(CMD_CTX, adapter_driver->transports);
}
/* no valid interface was found (i.e. the configuration option,
@@ -134,7 +134,7 @@ COMMAND_HANDLER(handle_interface_command)
*/
LOG_ERROR("The specified debug interface was not found (%s)",
CMD_ARGV[0]);
- CALL_COMMAND_HANDLER(handle_interface_list_command);
+ CALL_COMMAND_HANDLER(handle_adapter_list_command);
return ERROR_JTAG_INVALID_INTERFACE;
}
@@ -355,7 +355,7 @@ next:
return ERROR_OK;
}
-COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
+COMMAND_HANDLER(handle_adapter_srst_delay_command)
{
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -365,11 +365,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
jtag_set_nsrst_delay(delay);
}
- command_print(CMD, "adapter_nsrst_delay: %u", jtag_get_nsrst_delay());
+ command_print(CMD, "adapter srst delay: %u", jtag_get_nsrst_delay());
return ERROR_OK;
}
-COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command)
+COMMAND_HANDLER(handle_adapter_srst_pulse_width_command)
{
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -379,11 +379,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command)
jtag_set_nsrst_assert_width(width);
}
- command_print(CMD, "adapter_nsrst_assert_width: %u", jtag_get_nsrst_assert_width());
+ command_print(CMD, "adapter srst pulse_width: %u", jtag_get_nsrst_assert_width());
return ERROR_OK;
}
-COMMAND_HANDLER(handle_adapter_khz_command)
+COMMAND_HANDLER(handle_adapter_speed_command)
{
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -411,6 +411,92 @@ COMMAND_HANDLER(handle_adapter_khz_command)
return retval;
}
+COMMAND_HANDLER(handle_adapter_reset_de_assert)
+{
+ enum values {
+ VALUE_UNDEFINED = -1,
+ VALUE_DEASSERT = 0,
+ VALUE_ASSERT = 1,
+ };
+ enum values value;
+ enum values srst = VALUE_UNDEFINED;
+ enum values trst = VALUE_UNDEFINED;
+ enum reset_types jtag_reset_config = jtag_get_reset_config();
+ char *signal;
+
+ if (CMD_ARGC == 0) {
+ if (transport_is_jtag()) {
+ if (jtag_reset_config & RESET_HAS_TRST)
+ signal = jtag_get_trst() ? "asserted" : "deasserted";
+ else
+ signal = "not present";
+ command_print(CMD, "trst %s", signal);
+ }
+
+ if (jtag_reset_config & RESET_HAS_SRST)
+ signal = jtag_get_srst() ? "asserted" : "deasserted";
+ else
+ signal = "not present";
+ command_print(CMD, "srst %s", signal);
+
+ return ERROR_OK;
+ }
+
+ if (CMD_ARGC != 1 && CMD_ARGC != 3)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ value = (strcmp(CMD_NAME, "assert") == 0) ? VALUE_ASSERT : VALUE_DEASSERT;
+ if (strcmp(CMD_ARGV[0], "srst") == 0)
+ srst = value;
+ else if (strcmp(CMD_ARGV[0], "trst") == 0)
+ trst = value;
+ else
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (CMD_ARGC == 3) {
+ if (strcmp(CMD_ARGV[1], "assert") == 0)
+ value = VALUE_ASSERT;
+ else if (strcmp(CMD_ARGV[1], "deassert") == 0)
+ value = VALUE_DEASSERT;
+ else
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (strcmp(CMD_ARGV[2], "srst") == 0 && srst == VALUE_UNDEFINED)
+ srst = value;
+ else if (strcmp(CMD_ARGV[2], "trst") == 0 && trst == VALUE_UNDEFINED)
+ trst = value;
+ else
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ if (trst == VALUE_UNDEFINED) {
+ if (transport_is_jtag())
+ trst = jtag_get_trst() ? VALUE_ASSERT : VALUE_DEASSERT;
+ else
+ trst = VALUE_DEASSERT; /* unused, safe value */
+ }
+
+ if (srst == VALUE_UNDEFINED) {
+ if (jtag_reset_config & RESET_HAS_SRST)
+ srst = jtag_get_srst() ? VALUE_ASSERT : VALUE_DEASSERT;
+ else
+ srst = VALUE_DEASSERT; /* unused, safe value */
+ }
+
+ if (trst == VALUE_ASSERT && !transport_is_jtag()) {
+ LOG_ERROR("transport has no trst signal");
+ return ERROR_FAIL;
+ }
+
+ if (srst == VALUE_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("adapter has no srst signal");
+ return ERROR_FAIL;
+ }
+
+ return adapter_resets((trst == VALUE_DEASSERT) ? TRST_DEASSERT : TRST_ASSERT,
+ (srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT);
+}
+
#ifndef HAVE_JTAG_MINIDRIVER_H
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
COMMAND_HANDLER(handle_usb_location_command)
@@ -438,78 +524,103 @@ static const struct command_registration adapter_usb_command_handlers[] = {
};
#endif /* MINIDRIVER */
-static const struct command_registration adapter_command_handlers[] = {
-#ifndef HAVE_JTAG_MINIDRIVER_H
+static const struct command_registration adapter_srst_command_handlers[] = {
{
- .name = "usb",
+ .name = "delay",
+ .handler = handle_adapter_srst_delay_command,
.mode = COMMAND_ANY,
- .help = "usb adapter command group",
- .usage = "",
- .chain = adapter_usb_command_handlers,
+ .help = "delay after deasserting SRST in ms",
+ .usage = "[milliseconds]",
+ },
+ {
+ .name = "pulse_width",
+ .handler = handle_adapter_srst_pulse_width_command,
+ .mode = COMMAND_ANY,
+ .help = "SRST assertion pulse width in ms",
+ .usage = "[milliseconds]",
},
-#endif /* MINIDRIVER */
COMMAND_REGISTRATION_DONE
};
-static const struct command_registration interface_command_handlers[] = {
+static const struct command_registration adapter_command_handlers[] = {
{
- .name = "adapter",
- .mode = COMMAND_ANY,
- .help = "adapter command group",
- .usage = "",
- .chain = adapter_command_handlers,
+ .name = "driver",
+ .handler = handle_adapter_driver_command,
+ .mode = COMMAND_CONFIG,
+ .help = "Select a debug adapter driver",
+ .usage = "driver_name",
},
{
- .name = "adapter_khz",
- .handler = handle_adapter_khz_command,
+ .name = "speed",
+ .handler = handle_adapter_speed_command,
.mode = COMMAND_ANY,
.help = "With an argument, change to the specified maximum "
"jtag speed. For JTAG, 0 KHz signifies adaptive "
- " clocking. "
+ "clocking. "
"With or without argument, display current setting.",
.usage = "[khz]",
},
{
- .name = "adapter_name",
+ .name = "list",
+ .handler = handle_adapter_list_command,
+ .mode = COMMAND_ANY,
+ .help = "List all built-in debug adapter drivers",
+ .usage = "",
+ },
+ {
+ .name = "name",
.mode = COMMAND_ANY,
.jim_handler = jim_adapter_name,
.help = "Returns the name of the currently "
"selected adapter (driver)",
},
{
- .name = "adapter_nsrst_delay",
- .handler = handle_adapter_nsrst_delay_command,
+ .name = "srst",
.mode = COMMAND_ANY,
- .help = "delay after deasserting SRST in ms",
- .usage = "[milliseconds]",
+ .help = "srst adapter command group",
+ .usage = "",
+ .chain = adapter_srst_command_handlers,
},
{
- .name = "adapter_nsrst_assert_width",
- .handler = handle_adapter_nsrst_assert_width_command,
+ .name = "transports",
+ .handler = adapter_transports_command,
+ .mode = COMMAND_CONFIG,
+ .help = "Declare transports the adapter supports.",
+ .usage = "transport ... ",
+ },
+#ifndef HAVE_JTAG_MINIDRIVER_H
+ {
+ .name = "usb",
.mode = COMMAND_ANY,
- .help = "delay after asserting SRST in ms",
- .usage = "[milliseconds]",
+ .help = "usb adapter command group",
+ .usage = "",
+ .chain = adapter_usb_command_handlers,
},
+#endif /* MINIDRIVER */
{
- .name = "interface",
- .handler = handle_interface_command,
- .mode = COMMAND_CONFIG,
- .help = "Select a debug adapter interface (driver)",
- .usage = "driver_name",
+ .name = "assert",
+ .handler = handle_adapter_reset_de_assert,
+ .mode = COMMAND_EXEC,
+ .help = "Controls SRST and TRST lines.",
+ .usage = "|deassert [srst|trst [assert|deassert srst|trst]]",
},
{
- .name = "interface_transports",
- .handler = interface_transport_command,
- .mode = COMMAND_CONFIG,
- .help = "Declare transports the interface supports.",
- .usage = "transport ... ",
+ .name = "deassert",
+ .handler = handle_adapter_reset_de_assert,
+ .mode = COMMAND_EXEC,
+ .help = "Controls SRST and TRST lines.",
+ .usage = "|assert [srst|trst [deassert|assert srst|trst]]",
},
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration interface_command_handlers[] = {
{
- .name = "interface_list",
- .handler = handle_interface_list_command,
+ .name = "adapter",
.mode = COMMAND_ANY,
- .help = "List all built-in debug adapter interfaces (drivers)",
+ .help = "adapter command group",
.usage = "",
+ .chain = adapter_command_handlers,
},
{
.name = "reset_config",
diff --git a/src/jtag/aice/aice_interface.c b/src/jtag/aice/aice_interface.c
index c83b8c2..90871a1 100644
--- a/src/jtag/aice/aice_interface.c
+++ b/src/jtag/aice/aice_interface.c
@@ -25,7 +25,6 @@
#include <transport/transport.h>
#include <target/target.h>
#include <jtag/aice/aice_transport.h>
-#include <jtag/drivers/libusb_common.h>
#include "aice_usb.h"
#define AICE_KHZ_TO_SPEED_MAP_SIZE 16
@@ -518,14 +517,20 @@ static const struct command_registration aice_command_handlers[] = {
/***************************************************************************/
/* End of Command handlers */
-struct jtag_interface aice_interface = {
+static struct jtag_interface aice_interface = {
+ .execute_queue = aice_execute_queue,
+};
+
+struct adapter_driver aice_adapter_driver = {
.name = "aice",
- .commands = aice_command_handlers,
.transports = aice_transports,
+ .commands = aice_command_handlers,
+
.init = aice_init,
.quit = aice_quit,
- .execute_queue = aice_execute_queue,
.speed = aice_speed, /* set interface speed */
- .speed_div = aice_speed_div, /* return readable value */
.khz = aice_khz, /* convert khz to interface speed value */
+ .speed_div = aice_speed_div, /* return readable value */
+
+ .jtag_ops = &aice_interface,
};
diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c
index 15ebcac..ea710ad 100644
--- a/src/jtag/aice/aice_transport.c
+++ b/src/jtag/aice/aice_transport.c
@@ -47,6 +47,7 @@ static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
return JIM_ERR;
}
+ assert(pTap->expected_ids);
memcpy(new_expected_ids, pTap->expected_ids, expected_len);
new_expected_ids[pTap->expected_ids_cnt] = w;
@@ -173,7 +174,7 @@ COMMAND_HANDLER(handle_scan_chain_command)
while (tap) {
uint32_t expected, expected_mask, ii;
- snprintf(expected_id, sizeof expected_id, "0x%08x",
+ snprintf(expected_id, sizeof(expected_id), "0x%08x",
(unsigned)((tap->expected_ids_cnt > 0)
? tap->expected_ids[0]
: 0));
@@ -195,7 +196,7 @@ COMMAND_HANDLER(handle_scan_chain_command)
(unsigned int)(expected_mask));
for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
- snprintf(expected_id, sizeof expected_id, "0x%08x",
+ snprintf(expected_id, sizeof(expected_id), "0x%08x",
(unsigned) tap->expected_ids[ii]);
if (tap->ignore_version)
expected_id[2] = '*';
@@ -442,4 +443,3 @@ static void aice_constructor(void)
{
transport_register(&aice_jtag_transport);
}
-
diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c
index 324ec7c..4427542 100644
--- a/src/jtag/aice/aice_usb.c
+++ b/src/jtag/aice/aice_usb.c
@@ -19,7 +19,7 @@
#include "config.h"
#endif
-#include <jtag/drivers/libusb_common.h>
+#include <jtag/drivers/libusb_helper.h>
#include <helper/log.h>
#include <helper/time_support.h>
#include <target/target.h>
@@ -349,41 +349,53 @@ static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id,
/* calls the given usb_bulk_* function, allowing for the data to
* trickle in with some timeouts */
static int usb_bulk_with_retries(
- int (*f)(jtag_libusb_device_handle *, int, char *, int, int),
- jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout)
+ int (*f)(libusb_device_handle *, int, char *, int, int, int *),
+ libusb_device_handle *dev, int ep,
+ char *bytes, int size, int timeout, int *transferred)
{
int tries = 3, count = 0;
while (tries && (count < size)) {
- int result = f(dev, ep, bytes + count, size - count, timeout);
- if (result > 0)
+ int result, ret;
+
+ ret = f(dev, ep, bytes + count, size - count, timeout, &result);
+ if (ERROR_OK == ret)
count += result;
- else if ((-ETIMEDOUT != result) || !--tries)
- return result;
+ else if ((ERROR_TIMEOUT_REACHED != ret) || !--tries)
+ return ret;
}
- return count;
+
+ *transferred = count;
+ return ERROR_OK;
}
-static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep,
- char *buff, int size, int timeout)
+static int wrap_usb_bulk_write(libusb_device_handle *dev, int ep,
+ char *buff, int size, int timeout, int *transferred)
{
+
/* usb_bulk_write() takes const char *buff */
- return jtag_libusb_bulk_write(dev, ep, buff, size, timeout);
+ jtag_libusb_bulk_write(dev, ep, buff, size, timeout, transferred);
+
+ return 0;
}
-static inline int usb_bulk_write_ex(jtag_libusb_device_handle *dev, int ep,
+static inline int usb_bulk_write_ex(libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout)
{
- return usb_bulk_with_retries(&wrap_usb_bulk_write,
- dev, ep, bytes, size, timeout);
+ int tr = 0;
+
+ usb_bulk_with_retries(&wrap_usb_bulk_write,
+ dev, ep, bytes, size, timeout, &tr);
+ return tr;
}
-static inline int usb_bulk_read_ex(jtag_libusb_device_handle *dev, int ep,
+static inline int usb_bulk_read_ex(struct libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout)
{
- return usb_bulk_with_retries(&jtag_libusb_bulk_read,
- dev, ep, bytes, size, timeout);
+ int tr = 0;
+ usb_bulk_with_retries(&jtag_libusb_bulk_read,
+ dev, ep, bytes, size, timeout, &tr);
+ return tr;
}
/* Write data from out_buffer to USB. */
@@ -472,7 +484,9 @@ static int aice_usb_packet_flush(void)
i = 0;
while (1) {
- aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
+ int retval = aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
+ if (retval != ERROR_OK)
+ return retval;
if (batch_status & 0x1)
return ERROR_OK;
@@ -1785,8 +1799,8 @@ static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val);
static int check_suppressed_exception(uint32_t coreid, uint32_t dbger_value)
{
- uint32_t ir4_value;
- uint32_t ir6_value;
+ uint32_t ir4_value = 0;
+ uint32_t ir6_value = 0;
/* the default value of handling_suppressed_exception is false */
static bool handling_suppressed_exception;
@@ -1840,7 +1854,7 @@ static int check_privilege(uint32_t coreid, uint32_t dbger_value)
static int aice_check_dbger(uint32_t coreid, uint32_t expect_status)
{
uint32_t i = 0;
- uint32_t value_dbger;
+ uint32_t value_dbger = 0;
while (1) {
aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &value_dbger);
@@ -1961,7 +1975,7 @@ static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
aice_execute_dim(coreid, instructions, 4);
- uint32_t value_edmsw;
+ uint32_t value_edmsw = 0;
aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
if (value_edmsw & NDS_EDMSW_WDV)
aice_read_dtr(coreid, val);
@@ -2006,7 +2020,7 @@ static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
LOG_DEBUG("aice_write_reg, reg_no: 0x%08" PRIx32 ", value: 0x%08" PRIx32, num, val);
uint32_t instructions[4]; /** execute instructions in DIM */
- uint32_t value_edmsw;
+ uint32_t value_edmsw = 0;
aice_write_dtr(coreid, val);
aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
@@ -2095,9 +2109,9 @@ static int aice_usb_open(struct aice_port_param_s *param)
{
const uint16_t vids[] = { param->vid, 0 };
const uint16_t pids[] = { param->pid, 0 };
- struct jtag_libusb_device_handle *devh;
+ struct libusb_device_handle *devh;
- if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
+ if (jtag_libusb_open(vids, pids, NULL, &devh, NULL) != ERROR_OK)
return ERROR_FAIL;
/* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
@@ -2113,7 +2127,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
#if IS_WIN32 == 0
- jtag_libusb_reset_device(devh);
+ libusb_reset_device(devh);
#if IS_DARWIN == 0
@@ -2121,7 +2135,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
/* reopen jlink after usb_reset
* on win32 this may take a second or two to re-enumerate */
int retval;
- while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
+ while ((retval = jtag_libusb_open(vids, pids, NULL, &devh, NULL)) != ERROR_OK) {
usleep(1000);
timeout--;
if (!timeout)
@@ -2134,8 +2148,8 @@ static int aice_usb_open(struct aice_port_param_s *param)
#endif
/* usb_set_configuration required under win32 */
- jtag_libusb_set_configuration(devh, 0);
- jtag_libusb_claim_interface(devh, 0);
+ libusb_set_configuration(devh, 0);
+ libusb_claim_interface(devh, 0);
unsigned int aice_read_ep;
unsigned int aice_write_ep;
@@ -2435,7 +2449,7 @@ static int aice_backup_tmp_registers(uint32_t coreid)
LOG_DEBUG("backup_tmp_registers -");
/* backup target DTR first(if the target DTR is valid) */
- uint32_t value_edmsw;
+ uint32_t value_edmsw = 0;
aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
core_info[coreid].edmsw_backup = value_edmsw;
if (value_edmsw & 0x1) { /* EDMSW.WDV == 1 */
@@ -2602,13 +2616,13 @@ static int aice_usb_halt(uint32_t coreid)
aice_init_edm_registers(coreid, false);
/** Clear EDM_CTL.DBGIM & EDM_CTL.DBGACKM */
- uint32_t edm_ctl_value;
+ uint32_t edm_ctl_value = 0;
aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
if (edm_ctl_value & 0x3)
aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value & ~(0x3));
- uint32_t dbger;
- uint32_t acc_ctl_value;
+ uint32_t dbger = 0;
+ uint32_t acc_ctl_value = 0;
core_info[coreid].debug_under_dex_on = false;
aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger);
@@ -2649,7 +2663,7 @@ static int aice_usb_halt(uint32_t coreid)
* it is only for debugging 'debug exception handler' purpose.
* after openocd detaches from target, target behavior is
* undefined. */
- uint32_t ir0_value;
+ uint32_t ir0_value = 0;
uint32_t debug_mode_ir0_value;
aice_read_reg(coreid, IR0, &ir0_value);
debug_mode_ir0_value = ir0_value | 0x408; /* turn on DEX, set POM = 1 */
@@ -4017,7 +4031,7 @@ static int aice_usb_profiling(uint32_t coreid, uint32_t interval, uint32_t itera
/* check status */
uint32_t i;
- uint32_t batch_status;
+ uint32_t batch_status = 0;
i = 0;
while (1) {
diff --git a/src/jtag/aice/aice_usb.h b/src/jtag/aice/aice_usb.h
index 15cc1f6..04021de 100644
--- a/src/jtag/aice/aice_usb.h
+++ b/src/jtag/aice/aice_usb.h
@@ -93,7 +93,7 @@
struct aice_usb_handler_s {
unsigned int usb_read_ep;
unsigned int usb_write_ep;
- struct jtag_libusb_device_handle *usb_handle;
+ struct libusb_device_handle *usb_handle;
};
struct cache_info {
diff --git a/src/jtag/commands.c b/src/jtag/commands.c
index 3352e03..e88a3b7 100644
--- a/src/jtag/commands.c
+++ b/src/jtag/commands.c
@@ -31,6 +31,7 @@
#endif
#include <jtag/jtag.h>
+#include <transport/transport.h>
#include "commands.h"
struct cmd_queue_page {
@@ -48,6 +49,19 @@ static struct jtag_command **next_command_pointer = &jtag_command_queue;
void jtag_queue_command(struct jtag_command *cmd)
{
+ if (!transport_is_jtag()) {
+ /*
+ * FIXME: This should not happen!
+ * There could be old code that queues jtag commands with non jtag interfaces so, for
+ * the moment simply highlight it by log an error.
+ * We should fix it quitting with assert(0) because it is an internal error, or returning
+ * an error after call to jtag_command_queue_reset() to free the jtag queue and avoid
+ * memory leaks.
+ * The fix can be applied immediately after next release (v0.11.0 ?)
+ */
+ LOG_ERROR("JTAG API jtag_queue_command() called on non JTAG interface");
+ }
+
/* this command goes on the end, so ensure the queue terminates */
cmd->next = NULL;
diff --git a/src/jtag/core.c b/src/jtag/core.c
index 5e7c1e4..1d424b2 100644
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -126,10 +126,10 @@ static int rclk_fallback_speed_khz;
static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode;
static int jtag_speed;
-static struct jtag_interface *jtag;
+/* FIXME: change name to this variable, it is not anymore JTAG only */
+static struct adapter_driver *jtag;
-/* configuration */
-struct jtag_interface *jtag_interface;
+extern struct adapter_driver *adapter_driver;
void jtag_set_flush_queue_sleep(int ms)
{
@@ -503,7 +503,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state)
{
int retval;
- if (!(jtag->supported & DEBUG_CAP_TMS_SEQ))
+ if (!(jtag->jtag_ops->supported & DEBUG_CAP_TMS_SEQ))
return ERROR_JTAG_NOT_IMPLEMENTED;
jtag_checks();
@@ -611,22 +611,91 @@ void jtag_add_clocks(int num_cycles)
}
}
-void swd_add_reset(int req_srst)
+static int adapter_system_reset(int req_srst)
{
+ int retval;
+
if (req_srst) {
if (!(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("BUG: can't assert SRST");
- jtag_set_error(ERROR_FAIL);
- return;
+ return ERROR_FAIL;
}
req_srst = 1;
}
/* Maybe change SRST signal state */
if (jtag_srst != req_srst) {
+ retval = jtag->reset(0, req_srst);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("SRST error");
+ return ERROR_FAIL;
+ }
+ jtag_srst = req_srst;
+
+ if (req_srst) {
+ LOG_DEBUG("SRST line asserted");
+ if (adapter_nsrst_assert_width)
+ jtag_sleep(adapter_nsrst_assert_width * 1000);
+ } else {
+ LOG_DEBUG("SRST line released");
+ if (adapter_nsrst_delay)
+ jtag_sleep(adapter_nsrst_delay * 1000);
+ }
+ }
+
+ return ERROR_OK;
+}
+
+static void legacy_jtag_add_reset(int req_tlr_or_trst, int req_srst)
+{
+ int trst_with_tlr = 0;
+ int new_srst = 0;
+ int new_trst = 0;
+
+ /* Without SRST, we must use target-specific JTAG operations
+ * on each target; callers should not be requesting SRST when
+ * that signal doesn't exist.
+ *
+ * RESET_SRST_PULLS_TRST is a board or chip level quirk, which
+ * can kick in even if the JTAG adapter can't drive TRST.
+ */
+ if (req_srst) {
+ if (!(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("BUG: can't assert SRST");
+ jtag_set_error(ERROR_FAIL);
+ return;
+ }
+ if ((jtag_reset_config & RESET_SRST_PULLS_TRST) != 0
+ && !req_tlr_or_trst) {
+ LOG_ERROR("BUG: can't assert only SRST");
+ jtag_set_error(ERROR_FAIL);
+ return;
+ }
+ new_srst = 1;
+ }
+
+ /* JTAG reset (entry to TAP_RESET state) can always be achieved
+ * using TCK and TMS; that may go through a TAP_{IR,DR}UPDATE
+ * state first. TRST accelerates it, and bypasses those states.
+ *
+ * RESET_TRST_PULLS_SRST is a board or chip level quirk, which
+ * can kick in even if the JTAG adapter can't drive SRST.
+ */
+ if (req_tlr_or_trst) {
+ if (!(jtag_reset_config & RESET_HAS_TRST))
+ trst_with_tlr = 1;
+ else if ((jtag_reset_config & RESET_TRST_PULLS_SRST) != 0
+ && !req_srst)
+ trst_with_tlr = 1;
+ else
+ new_trst = 1;
+ }
+
+ /* Maybe change TRST and/or SRST signal state */
+ if (jtag_srst != new_srst || jtag_trst != new_trst) {
int retval;
- retval = interface_jtag_add_reset(0, req_srst);
+ retval = interface_jtag_add_reset(new_trst, new_srst);
if (retval != ERROR_OK)
jtag_set_error(retval);
else
@@ -636,9 +705,11 @@ void swd_add_reset(int req_srst)
LOG_ERROR("TRST/SRST error");
return;
}
+ }
- /* SRST resets everything hooked up to that signal */
- jtag_srst = req_srst;
+ /* SRST resets everything hooked up to that signal */
+ if (jtag_srst != new_srst) {
+ jtag_srst = new_srst;
if (jtag_srst) {
LOG_DEBUG("SRST line asserted");
if (adapter_nsrst_assert_width)
@@ -648,21 +719,54 @@ void swd_add_reset(int req_srst)
if (adapter_nsrst_delay)
jtag_add_sleep(adapter_nsrst_delay * 1000);
}
+ }
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("SRST timings error");
- return;
+ /* Maybe enter the JTAG TAP_RESET state ...
+ * - using only TMS, TCK, and the JTAG state machine
+ * - or else more directly, using TRST
+ *
+ * TAP_RESET should be invisible to non-debug parts of the system.
+ */
+ if (trst_with_tlr) {
+ LOG_DEBUG("JTAG reset with TLR instead of TRST");
+ jtag_add_tlr();
+
+ } else if (jtag_trst != new_trst) {
+ jtag_trst = new_trst;
+ if (jtag_trst) {
+ LOG_DEBUG("TRST line asserted");
+ tap_set_state(TAP_RESET);
+ if (jtag_ntrst_assert_width)
+ jtag_add_sleep(jtag_ntrst_assert_width * 1000);
+ } else {
+ LOG_DEBUG("TRST line released");
+ if (jtag_ntrst_delay)
+ jtag_add_sleep(jtag_ntrst_delay * 1000);
+
+ /* We just asserted nTRST, so we're now in TAP_RESET.
+ * Inform possible listeners about this, now that
+ * JTAG instructions and data can be shifted. This
+ * sequence must match jtag_add_tlr().
+ */
+ jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+ jtag_notify_event(JTAG_TRST_ASSERTED);
}
}
}
+/* FIXME: name is misleading; we do not plan to "add" reset into jtag queue */
void jtag_add_reset(int req_tlr_or_trst, int req_srst)
{
+ int retval;
int trst_with_tlr = 0;
int new_srst = 0;
int new_trst = 0;
+ if (!jtag->reset) {
+ legacy_jtag_add_reset(req_tlr_or_trst, req_srst);
+ return;
+ }
+
/* Without SRST, we must use target-specific JTAG operations
* on each target; callers should not be requesting SRST when
* that signal doesn't exist.
@@ -704,15 +808,12 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
/* Maybe change TRST and/or SRST signal state */
if (jtag_srst != new_srst || jtag_trst != new_trst) {
- int retval;
-
- retval = interface_jtag_add_reset(new_trst, new_srst);
- if (retval != ERROR_OK)
- jtag_set_error(retval);
- else
- retval = jtag_execute_queue();
+ /* guarantee jtag queue empty before changing reset status */
+ jtag_execute_queue();
+ retval = jtag->reset(new_trst, new_srst);
if (retval != ERROR_OK) {
+ jtag_set_error(retval);
LOG_ERROR("TRST/SRST error");
return;
}
@@ -741,6 +842,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
if (trst_with_tlr) {
LOG_DEBUG("JTAG reset with TLR instead of TRST");
jtag_add_tlr();
+ jtag_execute_queue();
} else if (jtag_trst != new_trst) {
jtag_trst = new_trst;
@@ -836,7 +938,88 @@ int default_interface_jtag_execute_queue(void)
return ERROR_FAIL;
}
- return jtag->execute_queue();
+ if (!transport_is_jtag()) {
+ /*
+ * FIXME: This should not happen!
+ * There could be old code that queues jtag commands with non jtag interfaces so, for
+ * the moment simply highlight it by log an error and return on empty execute_queue.
+ * We should fix it quitting with assert(0) because it is an internal error.
+ * The fix can be applied immediately after next release (v0.11.0 ?)
+ */
+ LOG_ERROR("JTAG API jtag_execute_queue() called on non JTAG interface");
+ if (!jtag->jtag_ops || !jtag->jtag_ops->execute_queue)
+ return ERROR_OK;
+ }
+
+ int result = jtag->jtag_ops->execute_queue();
+
+#if !BUILD_ZY1000
+ /* Only build this if we use a regular driver with a command queue.
+ * Otherwise jtag_command_queue won't be found at compile/link time. Its
+ * definition is in jtag/commands.c, which is only built/linked by
+ * jtag/Makefile.am if MINIDRIVER_DUMMY || !MINIDRIVER, but those variables
+ * aren't accessible here. */
+ struct jtag_command *cmd = jtag_command_queue;
+ while (debug_level >= LOG_LVL_DEBUG && cmd) {
+ switch (cmd->type) {
+ case JTAG_SCAN:
+ LOG_DEBUG_IO("JTAG %s SCAN to %s",
+ cmd->cmd.scan->ir_scan ? "IR" : "DR",
+ tap_state_name(cmd->cmd.scan->end_state));
+ for (int i = 0; i < cmd->cmd.scan->num_fields; i++) {
+ struct scan_field *field = cmd->cmd.scan->fields + i;
+ if (field->out_value) {
+ char *str = buf_to_str(field->out_value, field->num_bits, 16);
+ LOG_DEBUG_IO(" %db out: %s", field->num_bits, str);
+ free(str);
+ }
+ if (field->in_value) {
+ char *str = buf_to_str(field->in_value, field->num_bits, 16);
+ LOG_DEBUG_IO(" %db in: %s", field->num_bits, str);
+ free(str);
+ }
+ }
+ break;
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("JTAG TLR RESET to %s",
+ tap_state_name(cmd->cmd.statemove->end_state));
+ break;
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("JTAG RUNTEST %d cycles to %s",
+ cmd->cmd.runtest->num_cycles,
+ tap_state_name(cmd->cmd.runtest->end_state));
+ break;
+ case JTAG_RESET:
+ {
+ const char *reset_str[3] = {
+ "leave", "deassert", "assert"
+ };
+ LOG_DEBUG_IO("JTAG RESET %s TRST, %s SRST",
+ reset_str[cmd->cmd.reset->trst + 1],
+ reset_str[cmd->cmd.reset->srst + 1]);
+ }
+ break;
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("JTAG PATHMOVE (TODO)");
+ break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("JTAG SLEEP (TODO)");
+ break;
+ case JTAG_STABLECLOCKS:
+ LOG_DEBUG_IO("JTAG STABLECLOCKS (TODO)");
+ break;
+ case JTAG_TMS:
+ LOG_DEBUG_IO("JTAG TMS (TODO)");
+ break;
+ default:
+ LOG_ERROR("Unknown JTAG command: %d", cmd->type);
+ break;
+ }
+ cmd = cmd->next;
+ }
+#endif
+
+ return result;
}
void jtag_execute_queue_noclear(void)
@@ -1050,7 +1233,7 @@ static int jtag_examine_chain(void)
/* Add room for end-of-chain marker. */
max_taps++;
- uint8_t *idcode_buffer = malloc(max_taps * 4);
+ uint8_t *idcode_buffer = calloc(4, max_taps);
if (idcode_buffer == NULL)
return ERROR_JTAG_INIT_FAILED;
@@ -1086,7 +1269,7 @@ static int jtag_examine_chain(void)
* REVISIT create a jtag_alloc(chip, tap) routine, and
* share it with jim_newtap_cmd().
*/
- tap = calloc(1, sizeof *tap);
+ tap = calloc(1, sizeof(*tap));
if (!tap) {
retval = ERROR_FAIL;
goto out;
@@ -1107,7 +1290,8 @@ static int jtag_examine_chain(void)
if ((idcode & 1) == 0) {
/* Zero for LSB indicates a device in bypass */
- LOG_INFO("TAP %s has invalid IDCODE (0x%x)", tap->dotted_name, idcode);
+ LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%x)",
+ tap->dotted_name, idcode);
tap->hasidcode = false;
tap->idcode = 0;
@@ -1222,7 +1406,7 @@ static int jtag_validate_ircapture(void)
&& tap->ir_length < JTAG_IRLEN_MAX) {
tap->ir_length++;
}
- LOG_WARNING("AUTO %s - use \"jtag newtap " "%s %s -irlen %d "
+ LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %d "
"-expected-id 0x%08" PRIx32 "\"",
tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode);
}
@@ -1335,18 +1519,18 @@ int adapter_init(struct command_context *cmd_ctx)
if (jtag)
return ERROR_OK;
- if (!jtag_interface) {
- /* nothing was previously specified by "interface" command */
+ if (!adapter_driver) {
+ /* nothing was previously specified by "adapter driver" command */
LOG_ERROR("Debug Adapter has to be specified, "
- "see \"interface\" command");
+ "see \"adapter driver\" command");
return ERROR_JTAG_INVALID_INTERFACE;
}
int retval;
- retval = jtag_interface->init();
+ retval = adapter_driver->init();
if (retval != ERROR_OK)
return retval;
- jtag = jtag_interface;
+ jtag = adapter_driver;
if (jtag->speed == NULL) {
LOG_INFO("This adapter doesn't support configurable speed");
@@ -1355,7 +1539,7 @@ int adapter_init(struct command_context *cmd_ctx)
if (CLOCK_MODE_UNSELECTED == clock_mode) {
LOG_ERROR("An adapter speed is not selected in the init script."
- " Insert a call to adapter_khz or jtag_rclk to proceed.");
+ " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed.");
return ERROR_JTAG_INIT_FAILED;
}
@@ -1486,17 +1670,19 @@ int adapter_quit(void)
int swd_init_reset(struct command_context *cmd_ctx)
{
- int retval = adapter_init(cmd_ctx);
+ int retval, retval1;
+
+ retval = adapter_init(cmd_ctx);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("Initializing with hard SRST reset");
if (jtag_reset_config & RESET_HAS_SRST)
- swd_add_reset(1);
- swd_add_reset(0);
- retval = jtag_execute_queue();
- return retval;
+ retval = adapter_system_reset(1);
+ retval1 = adapter_system_reset(0);
+
+ return (retval == ERROR_OK) ? retval1 : retval;
}
int jtag_init_reset(struct command_context *cmd_ctx)
@@ -1686,7 +1872,7 @@ void jtag_set_verify(bool enable)
jtag_verify = enable;
}
-bool jtag_will_verify()
+bool jtag_will_verify(void)
{
return jtag_verify;
}
@@ -1696,7 +1882,7 @@ void jtag_set_verify_capture_ir(bool enable)
jtag_verify_capture_ir = enable;
}
-bool jtag_will_verify_capture_ir()
+bool jtag_will_verify_capture_ir(void)
{
return jtag_verify_capture_ir;
}
@@ -1819,42 +2005,98 @@ bool transport_is_jtag(void)
return get_current_transport() == &jtag_transport;
}
-void adapter_assert_reset(void)
+int adapter_resets(int trst, int srst)
+{
+ if (get_current_transport() == NULL) {
+ LOG_ERROR("transport is not selected");
+ return ERROR_FAIL;
+ }
+
+ if (transport_is_jtag()) {
+ if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("adapter has no srst signal");
+ return ERROR_FAIL;
+ }
+
+ /* adapters without trst signal will eventually use tlr sequence */
+ jtag_add_reset(trst, srst);
+ /*
+ * The jtag queue is still used for reset by some adapter. Flush it!
+ * FIXME: To be removed when all adapter drivers will be updated!
+ */
+ jtag_execute_queue();
+ return ERROR_OK;
+ } else if (transport_is_swd() || transport_is_hla() ||
+ transport_is_dapdirect_swd() || transport_is_dapdirect_jtag() ||
+ transport_is_swim()) {
+ if (trst == TRST_ASSERT) {
+ LOG_ERROR("transport %s has no trst signal",
+ get_current_transport()->name);
+ return ERROR_FAIL;
+ }
+
+ if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("adapter has no srst signal");
+ return ERROR_FAIL;
+ }
+ adapter_system_reset(srst);
+ return ERROR_OK;
+ }
+
+ if (trst == TRST_DEASSERT && srst == SRST_DEASSERT)
+ return ERROR_OK;
+
+ LOG_ERROR("reset is not supported on transport %s",
+ get_current_transport()->name);
+
+ return ERROR_FAIL;
+}
+
+int adapter_assert_reset(void)
{
if (transport_is_jtag()) {
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
jtag_add_reset(1, 1);
else
jtag_add_reset(0, 1);
- } else if (transport_is_swd())
- swd_add_reset(1);
+ return ERROR_OK;
+ } else if (transport_is_swd() || transport_is_hla() ||
+ transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
+ transport_is_swim())
+ return adapter_system_reset(1);
else if (get_current_transport() != NULL)
LOG_ERROR("reset is not supported on %s",
get_current_transport()->name);
else
LOG_ERROR("transport is not selected");
+ return ERROR_FAIL;
}
-void adapter_deassert_reset(void)
+int adapter_deassert_reset(void)
{
- if (transport_is_jtag())
+ if (transport_is_jtag()) {
jtag_add_reset(0, 0);
- else if (transport_is_swd())
- swd_add_reset(0);
+ return ERROR_OK;
+ } else if (transport_is_swd() || transport_is_hla() ||
+ transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
+ transport_is_swim())
+ return adapter_system_reset(0);
else if (get_current_transport() != NULL)
LOG_ERROR("reset is not supported on %s",
get_current_transport()->name);
else
LOG_ERROR("transport is not selected");
+ return ERROR_FAIL;
}
int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
+ uint32_t port_size, unsigned int *trace_freq,
+ unsigned int traceclkin_freq, uint16_t *prescaler)
{
- if (jtag->config_trace)
- return jtag->config_trace(enabled, pin_protocol, port_size,
- trace_freq);
- else if (enabled) {
+ if (jtag->config_trace) {
+ return jtag->config_trace(enabled, pin_protocol, port_size, trace_freq,
+ traceclkin_freq, prescaler);
+ } else if (enabled) {
LOG_ERROR("The selected interface does not support tracing");
return ERROR_FAIL;
}
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index 572cd24..07824f6 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -22,7 +22,7 @@ DRIVERFILES += %D%/driver.c
DRIVERFILES += %D%/jtag_usb_common.c
if USE_LIBUSB1
-DRIVERFILES += %D%/libusb1_common.c
+DRIVERFILES += %D%/libusb_helper.c
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB1_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS)
endif
@@ -31,9 +31,6 @@ if USE_LIBUSB0
DRIVERFILES += %D%/usb_common.c
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS)
-if !USE_LIBUSB1
-DRIVERFILES += %D%/libusb0_common.c
-endif
endif
if USE_LIBFTDI
@@ -136,6 +133,9 @@ if HLADAPTER
DRIVERFILES += %D%/stlink_usb.c
DRIVERFILES += %D%/ti_icdi_usb.c
endif
+if RSHIM
+DRIVERFILES += %D%/rshim.c
+endif
if OSBDM
DRIVERFILES += %D%/osbdm.c
endif
@@ -145,6 +145,9 @@ endif
if SYSFSGPIO
DRIVERFILES += %D%/sysfsgpio.c
endif
+if XLNX_PCIE_XVC
+DRIVERFILES += %D%/xlnx-pcie-xvc.c
+endif
if BCM2835GPIO
DRIVERFILES += %D%/bcm2835gpio.c
endif
@@ -168,9 +171,7 @@ DRIVERHEADERS = \
%D%/bitbang.h \
%D%/bitq.h \
%D%/jtag_usb_common.h \
- %D%/libusb0_common.h \
- %D%/libusb1_common.h \
- %D%/libusb_common.h \
+ %D%/libusb_helper.h \
%D%/minidriver_imp.h \
%D%/mpsse.h \
%D%/rlink.h \
@@ -183,4 +184,3 @@ DRIVERHEADERS = \
%D%/versaloon/versaloon.h \
%D%/versaloon/versaloon_include.h \
%D%/versaloon/versaloon_internal.h
-
diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c
index 045672f..f5918a0 100644
--- a/src/jtag/drivers/amt_jtagaccel.c
+++ b/src/jtag/drivers/amt_jtagaccel.c
@@ -393,7 +393,7 @@ int amt_jtagaccel_get_giveio_access(void)
HANDLE h;
OSVERSIONINFO version;
- version.dwOSVersionInfoSize = sizeof version;
+ version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) {
errno = EINVAL;
return -1;
@@ -584,7 +584,11 @@ static const struct command_registration amtjtagaccel_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface amt_jtagaccel_interface = {
+static struct jtag_interface amt_jtagaccel_interface = {
+ .execute_queue = amt_jtagaccel_execute_queue,
+};
+
+struct adapter_driver amt_jtagaccel_adapter_driver = {
.name = "amt_jtagaccel",
.transports = jtag_only,
.commands = amtjtagaccel_command_handlers,
@@ -592,5 +596,6 @@ struct jtag_interface amt_jtagaccel_interface = {
.init = amt_jtagaccel_init,
.quit = amt_jtagaccel_quit,
.speed = amt_jtagaccel_speed,
- .execute_queue = amt_jtagaccel_execute_queue,
+
+ .jtag_ops = &amt_jtagaccel_interface,
};
diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c
index 285bf9b..405278b 100644
--- a/src/jtag/drivers/arm-jtag-ew.c
+++ b/src/jtag/drivers/arm-jtag-ew.c
@@ -107,7 +107,7 @@ static int armjtagew_execute_queue(void)
switch (cmd->type) {
case JTAG_RUNTEST:
LOG_DEBUG_IO("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles, \
+ cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
armjtagew_end_state(cmd->cmd.runtest->end_state);
@@ -122,8 +122,8 @@ static int armjtagew_execute_queue(void)
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i", \
- cmd->cmd.pathmove->num_states, \
+ LOG_DEBUG_IO("pathmove: %i states, end in %i",
+ cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
armjtagew_path_move(cmd->cmd.pathmove->num_states,
@@ -459,10 +459,10 @@ static int armjtagew_get_version_info(void)
auxinfo[256] = '\0';
LOG_INFO(
- "ARM-JTAG-EW firmware version %d.%d, hardware revision %c, SN=%s, Additional info: %s", \
+ "ARM-JTAG-EW firmware version %d.%d, hardware revision %c, SN=%s, Additional info: %s",
usb_in_buffer[1],
- usb_in_buffer[0], \
- isgraph(usb_in_buffer[2]) ? usb_in_buffer[2] : 'X', \
+ usb_in_buffer[0],
+ isgraph(usb_in_buffer[2]) ? usb_in_buffer[2] : 'X',
sn,
auxinfo);
@@ -495,16 +495,22 @@ static const struct command_registration armjtagew_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface armjtagew_interface = {
+static struct jtag_interface armjtagew_interface = {
+ .execute_queue = armjtagew_execute_queue,
+};
+
+struct adapter_driver armjtagew_adapter_driver = {
.name = "arm-jtag-ew",
- .commands = armjtagew_command_handlers,
.transports = jtag_only,
- .execute_queue = armjtagew_execute_queue,
- .speed = armjtagew_speed,
- .speed_div = armjtagew_speed_div,
- .khz = armjtagew_khz,
+ .commands = armjtagew_command_handlers,
+
.init = armjtagew_init,
.quit = armjtagew_quit,
+ .speed = armjtagew_speed,
+ .khz = armjtagew_khz,
+ .speed_div = armjtagew_speed_div,
+
+ .jtag_ops = &armjtagew_interface,
};
/**************************************************************************
@@ -677,7 +683,7 @@ static int armjtagew_tap_execute(void)
/****************************************************************************
* JLink USB low-level functions */
-static struct armjtagew *armjtagew_usb_open()
+static struct armjtagew *armjtagew_usb_open(void)
{
usb_init();
@@ -744,7 +750,7 @@ static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
return -1;
}
- result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT, \
+ result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT,
(char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT);
LOG_DEBUG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result);
@@ -758,7 +764,7 @@ static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
/* Read data from USB into in_buffer. */
static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length)
{
- int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN, \
+ int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN,
(char *)usb_in_buffer, exp_in_length, ARMJTAGEW_USB_TIMEOUT);
LOG_DEBUG_IO("armjtagew_usb_read, result = %d", result);
diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c
index ac65563..1026847 100644
--- a/src/jtag/drivers/at91rm9200.c
+++ b/src/jtag/drivers/at91rm9200.c
@@ -111,7 +111,6 @@ static uint32_t *pio_base;
*/
static bb_value_t at91rm9200_read(void);
static int at91rm9200_write(int tck, int tms, int tdi);
-static int at91rm9200_reset(int trst, int srst);
static int at91rm9200_init(void);
static int at91rm9200_quit(void);
@@ -119,7 +118,6 @@ static int at91rm9200_quit(void);
static struct bitbang_interface at91rm9200_bitbang = {
.read = at91rm9200_read,
.write = at91rm9200_write,
- .reset = at91rm9200_reset,
.blink = 0
};
@@ -189,13 +187,20 @@ static const struct command_registration at91rm9200_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface at91rm9200_interface = {
- .name = "at91rm9200",
+static struct jtag_interface at91rm9200_interface = {
.execute_queue = bitbang_execute_queue,
+};
+
+struct adapter_driver at91rm9200_adapter_driver = {
+ .name = "at91rm9200",
.transports = jtag_only,
.commands = at91rm9200_command_handlers,
+
.init = at91rm9200_init,
.quit = at91rm9200_quit,
+ .reset = at91rm9200_reset,
+
+ .jtag_ops = &at91rm9200_interface,
};
static int at91rm9200_init(void)
diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
index 36e10b6..df557c5 100644
--- a/src/jtag/drivers/bcm2835gpio.c
+++ b/src/jtag/drivers/bcm2835gpio.c
@@ -51,7 +51,6 @@ static volatile uint32_t *pio_base;
static bb_value_t bcm2835gpio_read(void);
static int bcm2835gpio_write(int tck, int tms, int tdi);
-static int bcm2835gpio_reset(int trst, int srst);
static int bcm2835_swdio_read(void);
static void bcm2835_swdio_drive(bool is_output);
@@ -62,7 +61,6 @@ static int bcm2835gpio_quit(void);
static struct bitbang_interface bcm2835gpio_bitbang = {
.read = bcm2835gpio_read,
.write = bcm2835gpio_write,
- .reset = bcm2835gpio_reset,
.swdio_read = bcm2835_swdio_read,
.swdio_drive = bcm2835_swdio_drive,
.blink = NULL
@@ -407,18 +405,25 @@ static const struct command_registration bcm2835gpio_command_handlers[] = {
static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
-struct jtag_interface bcm2835gpio_interface = {
- .name = "bcm2835gpio",
+static struct jtag_interface bcm2835gpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
+};
+
+struct adapter_driver bcm2835gpio_adapter_driver = {
+ .name = "bcm2835gpio",
.transports = bcm2835_transports,
- .swd = &bitbang_swd,
- .speed = bcm2835gpio_speed,
- .khz = bcm2835gpio_khz,
- .speed_div = bcm2835gpio_speed_div,
.commands = bcm2835gpio_command_handlers,
+
.init = bcm2835gpio_init,
.quit = bcm2835gpio_quit,
+ .reset = bcm2835gpio_reset,
+ .speed = bcm2835gpio_speed,
+ .khz = bcm2835gpio_khz,
+ .speed_div = bcm2835gpio_speed_div,
+
+ .jtag_ops = &bcm2835gpio_interface,
+ .swd_ops = &bitbang_swd,
};
static bool bcm2835gpio_jtag_mode_possible(void)
@@ -461,7 +466,11 @@ static int bcm2835gpio_init(void)
return ERROR_JTAG_INIT_FAILED;
}
- dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
+ dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
+ if (dev_mem_fd < 0) {
+ LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
+ dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
+ }
if (dev_mem_fd < 0) {
perror("open");
return ERROR_JTAG_INIT_FAILED;
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
index b5078c0..72e9320 100644
--- a/src/jtag/drivers/bitbang.c
+++ b/src/jtag/drivers/bitbang.c
@@ -314,17 +314,6 @@ int bitbang_execute_queue(void)
while (cmd) {
switch (cmd->type) {
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
- if ((cmd->cmd.reset->trst == 1) ||
- (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
- if (bitbang_interface->reset(cmd->cmd.reset->trst,
- cmd->cmd.reset->srst) != ERROR_OK)
- return ERROR_FAIL;
- break;
case JTAG_RUNTEST:
LOG_DEBUG_IO("runtest %i cycles, end in %s",
cmd->cmd.runtest->num_cycles,
diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h
index 577717e..bbbc693 100644
--- a/src/jtag/drivers/bitbang.h
+++ b/src/jtag/drivers/bitbang.h
@@ -51,13 +51,12 @@ struct bitbang_interface {
/** Set TCK, TMS, and TDI to the given values. */
int (*write)(int tck, int tms, int tdi);
- int (*reset)(int trst, int srst);
int (*blink)(int on);
int (*swdio_read)(void);
void (*swdio_drive)(bool on);
};
-const struct swd_driver bitbang_swd;
+extern const struct swd_driver bitbang_swd;
extern bool swd_mode;
diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c
index 872896b..020c4ce 100644
--- a/src/jtag/drivers/buspirate.c
+++ b/src/jtag/drivers/buspirate.c
@@ -34,6 +34,7 @@
static int buspirate_execute_queue(void);
static int buspirate_init(void);
static int buspirate_quit(void);
+static int buspirate_reset(int trst, int srst);
static void buspirate_end_state(tap_state_t state);
static void buspirate_state_move(void);
@@ -133,7 +134,6 @@ static void buspirate_tap_append_scan(int length, uint8_t *buffer,
struct scan_command *command);
static void buspirate_tap_make_space(int scan, int bits);
-static void buspirate_reset(int trst, int srst);
static void buspirate_set_feature(int, char, char);
static void buspirate_set_mode(int, char);
static void buspirate_set_speed(int, char);
@@ -213,18 +213,6 @@ static int buspirate_execute_queue(void)
buffer, scan_size, cmd->cmd.scan);
break;
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-
- /* flush buffers, so we can reset */
- buspirate_tap_execute();
-
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- buspirate_reset(cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
- break;
case JTAG_SLEEP:
LOG_DEBUG_IO("sleep %i", cmd->cmd.sleep->us);
buspirate_tap_execute();
@@ -548,14 +536,21 @@ static const struct swd_driver buspirate_swd = {
static const char * const buspirate_transports[] = { "jtag", "swd", NULL };
-struct jtag_interface buspirate_interface = {
- .name = "buspirate",
+static struct jtag_interface buspirate_interface = {
.execute_queue = buspirate_execute_queue,
- .commands = buspirate_command_handlers,
+};
+
+struct adapter_driver buspirate_adapter_driver = {
+ .name = "buspirate",
.transports = buspirate_transports,
- .swd = &buspirate_swd,
+ .commands = buspirate_command_handlers,
+
.init = buspirate_init,
- .quit = buspirate_quit
+ .quit = buspirate_quit,
+ .reset = buspirate_reset,
+
+ .jtag_ops = &buspirate_interface,
+ .swd_ops = &buspirate_swd,
};
/*************** jtag execute commands **********************/
@@ -860,7 +855,7 @@ static void buspirate_tap_append_scan(int length, uint8_t *buffer,
/*************** wrapper functions *********************/
/* (1) assert or (0) deassert reset lines */
-static void buspirate_reset(int trst, int srst)
+static int buspirate_reset(int trst, int srst)
{
LOG_DEBUG("trst: %i, srst: %i", trst, srst);
@@ -873,6 +868,8 @@ static void buspirate_reset(int trst, int srst)
buspirate_set_feature(buspirate_fd, FEATURE_SRST, ACTION_DISABLE);
else
buspirate_set_feature(buspirate_fd, FEATURE_SRST, ACTION_ENABLE);
+
+ return ERROR_OK;
}
static void buspirate_set_feature(int fd, char feat, char action)
diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c
index d52d698..ee1cb53 100644
--- a/src/jtag/drivers/cmsis_dap_usb.c
+++ b/src/jtag/drivers/cmsis_dap_usb.c
@@ -364,8 +364,6 @@ static void cmsis_dap_usb_close(struct cmsis_dap *dap)
free(pending_fifo[i].transfers);
pending_fifo[i].transfers = NULL;
}
-
- return;
}
static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen)
@@ -509,15 +507,15 @@ static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
return ERROR_OK;
}
-static int cmsis_dap_cmd_DAP_LED(uint8_t leds)
+static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state)
{
int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
buffer[0] = 0; /* report number */
buffer[1] = CMD_DAP_LED;
- buffer[2] = 0x00;
- buffer[3] = leds;
+ buffer[2] = led;
+ buffer[3] = state;
retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4);
if (retval != ERROR_OK || buffer[1] != 0x00) {
@@ -1086,8 +1084,12 @@ static int cmsis_dap_init(void)
if (retval != ERROR_OK)
return ERROR_FAIL;
}
+ /* Both LEDs on */
+ retval = cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON);
+ if (retval != ERROR_OK)
+ return ERROR_FAIL;
- retval = cmsis_dap_cmd_DAP_LED(0x03); /* Both LEDs on */
+ retval = cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON);
if (retval != ERROR_OK)
return ERROR_FAIL;
@@ -1102,9 +1104,6 @@ static int cmsis_dap_init(void)
LOG_INFO("Connecting under reset");
}
}
-
- cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
-
LOG_INFO("CMSIS-DAP: Interface ready");
return ERROR_OK;
@@ -1119,28 +1118,31 @@ static int cmsis_dap_swd_init(void)
static int cmsis_dap_quit(void)
{
cmsis_dap_cmd_DAP_Disconnect();
- cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
+ /* Both LEDs off */
+ cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_OFF);
+ cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_OFF);
cmsis_dap_usb_close(cmsis_dap_handle);
return ERROR_OK;
}
-static void cmsis_dap_execute_reset(struct jtag_command *cmd)
+static int cmsis_dap_reset(int trst, int srst)
{
/* Set both TRST and SRST even if they're not enabled as
* there's no way to tristate them */
output_pins = 0;
- if (!cmd->cmd.reset->srst)
+ if (!srst)
output_pins |= SWJ_PIN_SRST;
- if (!cmd->cmd.reset->trst)
+ if (!trst)
output_pins |= SWJ_PIN_TRST;
int retval = cmsis_dap_cmd_DAP_SWJ_Pins(output_pins,
SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL);
if (retval != ERROR_OK)
LOG_ERROR("CMSIS-DAP: Interface reset failed");
+ return retval;
}
static void cmsis_dap_execute_sleep(struct jtag_command *cmd)
@@ -1581,10 +1583,6 @@ static void cmsis_dap_execute_tms(struct jtag_command *cmd)
static void cmsis_dap_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
- case JTAG_RESET:
- cmsis_dap_flush();
- cmsis_dap_execute_reset(cmd);
- break;
case JTAG_SLEEP:
cmsis_dap_flush();
cmsis_dap_execute_sleep(cmd);
@@ -1631,10 +1629,10 @@ static int cmsis_dap_execute_queue(void)
static int cmsis_dap_speed(int speed)
{
if (speed > DAP_MAX_CLOCK)
- LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed);
+ LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed);
if (speed == 0) {
- LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
+ LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\".");
return ERROR_JTAG_NOT_IMPLEMENTED;
}
@@ -1789,17 +1787,23 @@ static const struct swd_driver cmsis_dap_swd_driver = {
static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL };
-struct jtag_interface cmsis_dap_interface = {
- .name = "cmsis-dap",
+static struct jtag_interface cmsis_dap_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
- .commands = cmsis_dap_command_handlers,
- .swd = &cmsis_dap_swd_driver,
+ .execute_queue = cmsis_dap_execute_queue,
+};
+
+struct adapter_driver cmsis_dap_adapter_driver = {
+ .name = "cmsis-dap",
.transports = cmsis_dap_transport,
+ .commands = cmsis_dap_command_handlers,
- .execute_queue = cmsis_dap_execute_queue,
- .speed = cmsis_dap_speed,
- .speed_div = cmsis_dap_speed_div,
- .khz = cmsis_dap_khz,
.init = cmsis_dap_init,
.quit = cmsis_dap_quit,
+ .reset = cmsis_dap_reset,
+ .speed = cmsis_dap_speed,
+ .khz = cmsis_dap_khz,
+ .speed_div = cmsis_dap_speed_div,
+
+ .jtag_ops = &cmsis_dap_interface,
+ .swd_ops = &cmsis_dap_swd_driver,
};
diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c
index 4e5b615..e66cb6b 100644
--- a/src/jtag/drivers/dummy.c
+++ b/src/jtag/drivers/dummy.c
@@ -91,7 +91,6 @@ static int dummy_led(int on)
static struct bitbang_interface dummy_bitbang = {
.read = &dummy_read,
.write = &dummy_write,
- .reset = &dummy_reset,
.blink = &dummy_led,
};
@@ -145,19 +144,22 @@ static const struct command_registration dummy_command_handlers[] = {
/* The dummy driver is used to easily check the code path
* where the target is unresponsive.
*/
-struct jtag_interface dummy_interface = {
- .name = "dummy",
-
- .supported = DEBUG_CAP_TMS_SEQ,
- .commands = dummy_command_handlers,
- .transports = jtag_only,
+static struct jtag_interface dummy_interface = {
+ .supported = DEBUG_CAP_TMS_SEQ,
+ .execute_queue = &bitbang_execute_queue,
+};
- .execute_queue = &bitbang_execute_queue,
+struct adapter_driver dummy_adapter_driver = {
+ .name = "dummy",
+ .transports = jtag_only,
+ .commands = dummy_command_handlers,
- .speed = &dummy_speed,
- .khz = &dummy_khz,
- .speed_div = &dummy_speed_div,
+ .init = &dummy_init,
+ .quit = &dummy_quit,
+ .reset = &dummy_reset,
+ .speed = &dummy_speed,
+ .khz = &dummy_khz,
+ .speed_div = &dummy_speed_div,
- .init = &dummy_init,
- .quit = &dummy_quit,
- };
+ .jtag_ops = &dummy_interface,
+};
diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c
index 4cf3184..5e0e62a 100644
--- a/src/jtag/drivers/ep93xx.c
+++ b/src/jtag/drivers/ep93xx.c
@@ -50,21 +50,25 @@ static int ep93xx_quit(void);
struct timespec ep93xx_zzzz;
-struct jtag_interface ep93xx_interface = {
- .name = "ep93xx",
-
+static struct jtag_interface ep93xx_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
+};
+
+struct adapter_driver ep93xx_adapter_driver = {
+ .name = "ep93xx",
.transports = jtag_only,
.init = ep93xx_init,
.quit = ep93xx_quit,
+ .reset = ep93xx_reset,
+
+ .jtag_ops = &ep93xx_interface,
};
static struct bitbang_interface ep93xx_bitbang = {
.read = ep93xx_read,
.write = ep93xx_write,
- .reset = ep93xx_reset,
.blink = 0,
};
diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c
index 8cda76e..c9ed304 100644
--- a/src/jtag/drivers/ft232r.c
+++ b/src/jtag/drivers/ft232r.c
@@ -29,7 +29,7 @@
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <helper/time_support.h>
-#include "libusb1_common.h"
+#include "libusb_helper.h"
/* system includes */
#include <string.h>
@@ -71,7 +71,7 @@
static char *ft232r_serial_desc;
static uint16_t ft232r_vid = 0x0403; /* FTDI */
static uint16_t ft232r_pid = 0x6001; /* FT232R */
-static jtag_libusb_device_handle *adapter;
+static struct libusb_device_handle *adapter;
static uint8_t *ft232r_output;
static size_t ft232r_output_len;
@@ -132,11 +132,11 @@ static int ft232r_send_recv(void)
bytes_to_write = rxfifo_free;
if (bytes_to_write) {
- int n = jtag_libusb_bulk_write(adapter, IN_EP,
- (char *) ft232r_output + total_written,
- bytes_to_write, 1000);
+ int n;
- if (n == 0) {
+ if (jtag_libusb_bulk_write(adapter, IN_EP,
+ (char *) ft232r_output + total_written,
+ bytes_to_write, 1000, &n) != ERROR_OK) {
LOG_ERROR("usb bulk write failed");
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -147,12 +147,10 @@ static int ft232r_send_recv(void)
/* Read */
uint8_t reply[64];
+ int n;
- int n = jtag_libusb_bulk_read(adapter, OUT_EP,
- (char *) reply,
- sizeof(reply), 1000);
-
- if (n == 0) {
+ if (jtag_libusb_bulk_read(adapter, OUT_EP, (char *) reply,
+ sizeof(reply), 1000, &n) != ERROR_OK) {
LOG_ERROR("usb bulk read failed");
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -259,7 +257,7 @@ static int ft232r_init(void)
{
uint16_t avids[] = {ft232r_vid, 0};
uint16_t apids[] = {ft232r_pid, 0};
- if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter)) {
+ if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter, NULL)) {
LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
ft232r_vid, ft232r_pid, (ft232r_serial_desc == NULL) ? "[any]" : ft232r_serial_desc);
return ERROR_JTAG_INIT_FAILED;
@@ -270,7 +268,7 @@ static int ft232r_init(void)
else /* serial port will be restored after jtag: */
libusb_set_auto_detach_kernel_driver(adapter, 1); /* 1: DONT_DETACH_SIO_MODULE */
- if (jtag_libusb_claim_interface(adapter, 0)) {
+ if (libusb_claim_interface(adapter, 0)) {
LOG_ERROR("unable to claim interface");
return ERROR_JTAG_INIT_FAILED;
}
@@ -332,7 +330,7 @@ static int ft232r_quit(void)
}
}
- if (jtag_libusb_release_interface(adapter, 0) != 0)
+ if (libusb_release_interface(adapter, 0) != 0)
LOG_ERROR("usb release interface failed");
jtag_libusb_close(adapter);
@@ -914,17 +912,21 @@ static int syncbb_execute_queue(void)
return retval;
}
-struct jtag_interface ft232r_interface = {
- .name = "ft232r",
- .commands = ft232r_command_handlers,
- .transports = jtag_only,
+static struct jtag_interface ft232r_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
-
.execute_queue = syncbb_execute_queue,
+};
+
+struct adapter_driver ft232r_adapter_driver = {
+ .name = "ft232r",
+ .transports = jtag_only,
+ .commands = ft232r_command_handlers,
- .speed = ft232r_speed,
.init = ft232r_init,
.quit = ft232r_quit,
- .speed_div = ft232r_speed_div,
+ .speed = ft232r_speed,
.khz = ft232r_khz,
+ .speed_div = ft232r_speed_div,
+
+ .jtag_ops = &ft232r_interface,
};
diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
index ebe6016..34b42b8 100644
--- a/src/jtag/drivers/ftdi.c
+++ b/src/jtag/drivers/ftdi.c
@@ -249,7 +249,7 @@ static int ftdi_set_signal(const struct signal *s, char value)
return ERROR_OK;
}
-static int ftdi_get_signal(const struct signal *s, uint16_t * value_out)
+static int ftdi_get_signal(const struct signal *s, uint16_t *value_out)
{
uint8_t data_low = 0;
uint8_t data_high = 0;
@@ -582,46 +582,40 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
tap_state_name(tap_get_end_state()));
}
-static void ftdi_execute_reset(struct jtag_command *cmd)
+static int ftdi_reset(int trst, int srst)
{
- LOG_DEBUG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-
- if (cmd->cmd.reset->trst == 1
- || (cmd->cmd.reset->srst
- && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
-
- struct signal *trst = find_signal_by_name("nTRST");
- if (cmd->cmd.reset->trst == 1) {
- if (trst)
- ftdi_set_signal(trst, '0');
+ struct signal *sig_ntrst = find_signal_by_name("nTRST");
+ struct signal *sig_nsrst = find_signal_by_name("nSRST");
+
+ LOG_DEBUG_IO("reset trst: %i srst %i", trst, srst);
+
+ if (trst == 1) {
+ if (sig_ntrst)
+ ftdi_set_signal(sig_ntrst, '0');
else
LOG_ERROR("Can't assert TRST: nTRST signal is not defined");
- } else if (trst && jtag_get_reset_config() & RESET_HAS_TRST &&
- cmd->cmd.reset->trst == 0) {
+ } else if (sig_ntrst && jtag_get_reset_config() & RESET_HAS_TRST &&
+ trst == 0) {
if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN)
- ftdi_set_signal(trst, 'z');
+ ftdi_set_signal(sig_ntrst, 'z');
else
- ftdi_set_signal(trst, '1');
+ ftdi_set_signal(sig_ntrst, '1');
}
- struct signal *srst = find_signal_by_name("nSRST");
- if (cmd->cmd.reset->srst == 1) {
- if (srst)
- ftdi_set_signal(srst, '0');
+ if (srst == 1) {
+ if (sig_nsrst)
+ ftdi_set_signal(sig_nsrst, '0');
else
LOG_ERROR("Can't assert SRST: nSRST signal is not defined");
- } else if (srst && jtag_get_reset_config() & RESET_HAS_SRST &&
- cmd->cmd.reset->srst == 0) {
+ } else if (sig_nsrst && jtag_get_reset_config() & RESET_HAS_SRST &&
+ srst == 0) {
if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
- ftdi_set_signal(srst, '1');
+ ftdi_set_signal(sig_nsrst, '1');
else
- ftdi_set_signal(srst, 'z');
+ ftdi_set_signal(sig_nsrst, 'z');
}
- LOG_DEBUG_IO("trst: %i, srst: %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ return mpsse_flush(mpsse_ctx);
}
static void ftdi_execute_sleep(struct jtag_command *cmd)
@@ -663,7 +657,6 @@ static void ftdi_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
case JTAG_RESET:
- ftdi_execute_reset(cmd);
#if BUILD_FTDI_OSCAN1 == 1
oscan1_reset_online_activate(); /* put the target back into OSCAN1 mode */
#endif
@@ -727,6 +720,11 @@ static int ftdi_initialize(void)
else
LOG_DEBUG("ftdi interface using shortest path jtag state transitions");
+ if (!ftdi_vid[0] && !ftdi_pid[0]) {
+ LOG_ERROR("Please specify ftdi_vid_pid");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) {
mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc,
ftdi_serial, jtag_usb_get_location(), ftdi_channel);
@@ -1592,17 +1590,23 @@ static const struct swd_driver ftdi_swd = {
static const char * const ftdi_transports[] = { "jtag", "swd", NULL };
-struct jtag_interface ftdi_interface = {
- .name = "ftdi",
+static struct jtag_interface ftdi_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
- .commands = ftdi_command_handlers,
+ .execute_queue = ftdi_execute_queue,
+};
+
+struct adapter_driver ftdi_adapter_driver = {
+ .name = "ftdi",
.transports = ftdi_transports,
- .swd = &ftdi_swd,
+ .commands = ftdi_command_handlers,
.init = ftdi_initialize,
.quit = ftdi_quit,
+ .reset = ftdi_reset,
.speed = ftdi_speed,
- .speed_div = ftdi_speed_div,
.khz = ftdi_khz,
- .execute_queue = ftdi_execute_queue,
+ .speed_div = ftdi_speed_div,
+
+ .jtag_ops = &ftdi_interface,
+ .swd_ops = &ftdi_swd,
};
diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c
index e65f56c..d1699ef 100644
--- a/src/jtag/drivers/gw16012.c
+++ b/src/jtag/drivers/gw16012.c
@@ -350,7 +350,7 @@ static int gw16012_get_giveio_access(void)
HANDLE h;
OSVERSIONINFO version;
- version.dwOSVersionInfoSize = sizeof version;
+ version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) {
errno = EINVAL;
return -1;
@@ -448,7 +448,7 @@ static int gw16012_init_device(void)
LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
}
- LOG_DEBUG("requesting privileges for parallel port 0x%lx...", (long unsigned)(gw16012_port));
+ LOG_DEBUG("requesting privileges for parallel port 0x%" PRIx16 "...", gw16012_port);
#if PARPORT_USE_GIVEIO == 1
if (gw16012_get_giveio_access() != 0) {
#else /* PARPORT_USE_GIVEIO */
@@ -521,12 +521,17 @@ static const struct command_registration gw16012_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface gw16012_interface = {
+static struct jtag_interface gw16012_interface = {
+ .execute_queue = gw16012_execute_queue,
+};
+
+struct adapter_driver gw16012_adapter_driver = {
.name = "gw16012",
.transports = jtag_only,
.commands = gw16012_command_handlers,
.init = gw16012_init,
.quit = gw16012_quit,
- .execute_queue = gw16012_execute_queue,
+
+ .jtag_ops = &gw16012_interface,
};
diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c
index 4923dab..7dcfb67 100644
--- a/src/jtag/drivers/imx_gpio.c
+++ b/src/jtag/drivers/imx_gpio.c
@@ -84,7 +84,6 @@ static inline bool gpio_level(int g)
static bb_value_t imx_gpio_read(void);
static int imx_gpio_write(int tck, int tms, int tdi);
-static int imx_gpio_reset(int trst, int srst);
static int imx_gpio_swdio_read(void);
static void imx_gpio_swdio_drive(bool is_output);
@@ -95,7 +94,6 @@ static int imx_gpio_quit(void);
static struct bitbang_interface imx_gpio_bitbang = {
.read = imx_gpio_read,
.write = imx_gpio_write,
- .reset = imx_gpio_reset,
.swdio_read = imx_gpio_swdio_read,
.swdio_drive = imx_gpio_swdio_drive,
.blink = NULL
@@ -429,18 +427,25 @@ static const struct command_registration imx_gpio_command_handlers[] = {
static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL };
-struct jtag_interface imx_gpio_interface = {
- .name = "imx_gpio",
+static struct jtag_interface imx_gpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
+};
+
+struct adapter_driver imx_gpio_adapter_driver = {
+ .name = "imx_gpio",
.transports = imx_gpio_transports,
- .swd = &bitbang_swd,
- .speed = imx_gpio_speed,
- .khz = imx_gpio_khz,
- .speed_div = imx_gpio_speed_div,
.commands = imx_gpio_command_handlers,
+
.init = imx_gpio_init,
.quit = imx_gpio_quit,
+ .reset = imx_gpio_reset,
+ .speed = imx_gpio_speed,
+ .khz = imx_gpio_khz,
+ .speed_div = imx_gpio_speed_div,
+
+ .jtag_ops = &imx_gpio_interface,
+ .swd_ops = &bitbang_swd,
};
static bool imx_gpio_jtag_mode_possible(void)
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index 09b3a85..1baf345 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -39,6 +39,7 @@
#include <jtag/swd.h>
#include <jtag/commands.h>
#include <jtag/drivers/jtag_usb_common.h>
+#include <target/cortex_m.h>
#include <libjaylink/libjaylink.h>
@@ -62,6 +63,9 @@ static bool trace_enabled;
static unsigned int swd_buffer_size = JLINK_TAP_BUFFER_SIZE;
+/* Maximum SWO frequency deviation. */
+#define SWO_MAX_FREQ_DEV 0.03
+
/* 256 byte non-volatile memory */
struct device_config {
uint8_t usb_address;
@@ -90,6 +94,7 @@ static void jlink_path_move(int num_states, tap_state_t *path);
static void jlink_stableclocks(int num_cycles);
static void jlink_runtest(int num_cycles);
static void jlink_reset(int trst, int srst);
+static int jlink_reset_safe(int trst, int srst);
static int jlink_swd_run_queue(void);
static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk);
static int jlink_swd_switch_seq(enum swd_special_seq seq);
@@ -247,16 +252,6 @@ static void jlink_execute_scan(struct jtag_command *cmd)
tap_state_name(tap_get_end_state()));
}
-static void jlink_execute_reset(struct jtag_command *cmd)
-{
- LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-
- jlink_flush();
- jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- jlink_flush();
-}
-
static void jlink_execute_sleep(struct jtag_command *cmd)
{
LOG_DEBUG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us);
@@ -282,9 +277,6 @@ static int jlink_execute_command(struct jtag_command *cmd)
case JTAG_SCAN:
jlink_execute_scan(cmd);
break;
- case JTAG_RESET:
- jlink_execute_reset(cmd);
- break;
case JTAG_SLEEP:
jlink_execute_sleep(cmd);
break;
@@ -952,6 +944,13 @@ static void jlink_reset(int trst, int srst)
jaylink_jtag_set_trst(devh);
}
+static int jlink_reset_safe(int trst, int srst)
+{
+ jlink_flush();
+ jlink_reset(trst, srst);
+ return jlink_flush();
+}
+
COMMAND_HANDLER(jlink_usb_command)
{
int tmp;
@@ -1267,55 +1266,74 @@ static uint32_t calculate_trace_buffer_size(void)
return tmp & 0xffffff00;
}
-static bool check_trace_freq(struct jaylink_swo_speed speed,
- uint32_t trace_freq)
+static bool calculate_swo_prescaler(unsigned int traceclkin_freq,
+ uint32_t trace_freq, uint16_t *prescaler)
{
- double min;
+ unsigned int presc;
double deviation;
+
+ presc = ((1.0 - SWO_MAX_FREQ_DEV) * traceclkin_freq) / trace_freq + 1;
+
+ if (presc > TPIU_ACPR_MAX_SWOSCALER)
+ return false;
+
+ deviation = fabs(1.0 - ((double)trace_freq * presc / traceclkin_freq));
+
+ if (deviation > SWO_MAX_FREQ_DEV)
+ return false;
+
+ *prescaler = presc;
+
+ return true;
+}
+
+static bool detect_swo_freq_and_prescaler(struct jaylink_swo_speed speed,
+ unsigned int traceclkin_freq, uint32_t *trace_freq,
+ uint16_t *prescaler)
+{
uint32_t divider;
+ unsigned int presc;
+ double deviation;
+
+ for (divider = speed.min_div; divider <= speed.max_div; divider++) {
+ *trace_freq = speed.freq / divider;
+ presc = ((1.0 - SWO_MAX_FREQ_DEV) * traceclkin_freq) / *trace_freq + 1;
- min = fabs(1.0 - (speed.freq / ((double)trace_freq * speed.min_div)));
+ if (presc > TPIU_ACPR_MAX_SWOSCALER)
+ break;
- for (divider = speed.min_div; divider < speed.max_div; divider++) {
- deviation = fabs(1.0 - (speed.freq / ((double)trace_freq * divider)));
+ deviation = fabs(1.0 - ((double)*trace_freq * presc / traceclkin_freq));
- if (deviation < 0.03) {
- LOG_DEBUG("Found suitable frequency divider %u with deviation of "
- "%.02f %%.", divider, deviation);
+ if (deviation <= SWO_MAX_FREQ_DEV) {
+ *prescaler = presc;
return true;
}
-
- if (deviation < min)
- min = deviation;
}
- LOG_ERROR("Selected trace frequency is not supported by the device. "
- "Please choose a different trace frequency.");
- LOG_ERROR("Maximum permitted deviation is 3.00 %%, but only %.02f %% "
- "could be achieved.", min * 100);
-
return false;
}
static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
+ uint32_t port_size, unsigned int *trace_freq,
+ unsigned int traceclkin_freq, uint16_t *prescaler)
{
int ret;
uint32_t buffer_size;
struct jaylink_swo_speed speed;
+ uint32_t divider;
+ uint32_t min_freq;
+ uint32_t max_freq;
+
+ trace_enabled = enabled;
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SWO)) {
- LOG_ERROR("Trace capturing is not supported by the device.");
- return ERROR_FAIL;
- }
+ if (!enabled)
+ return ERROR_OK;
- if (pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART) {
- LOG_ERROR("Selected pin protocol is not supported.");
+ LOG_ERROR("Trace capturing is not supported by the device.");
return ERROR_FAIL;
}
- trace_enabled = enabled;
-
ret = jaylink_swo_stop(devh);
if (ret != JAYLINK_OK) {
@@ -1334,6 +1352,11 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
return ERROR_OK;
}
+ if (pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART) {
+ LOG_ERROR("Selected pin protocol is not supported.");
+ return ERROR_FAIL;
+ }
+
buffer_size = calculate_trace_buffer_size();
if (!buffer_size) {
@@ -1349,13 +1372,45 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
return ERROR_FAIL;
}
- if (!*trace_freq)
- *trace_freq = speed.freq / speed.min_div;
+ if (*trace_freq > 0) {
+ divider = speed.freq / *trace_freq;
+ min_freq = speed.freq / speed.max_div;
+ max_freq = speed.freq / speed.min_div;
+
+ if (*trace_freq > max_freq) {
+ LOG_INFO("Given SWO frequency too high, using %u Hz instead.",
+ max_freq);
+ *trace_freq = max_freq;
+ } else if (*trace_freq < min_freq) {
+ LOG_INFO("Given SWO frequency too low, using %u Hz instead.",
+ min_freq);
+ *trace_freq = min_freq;
+ } else if (*trace_freq != speed.freq / divider) {
+ *trace_freq = speed.freq / divider;
+
+ LOG_INFO("Given SWO frequency is not supported by the device, "
+ "using %u Hz instead.", *trace_freq);
+ }
- if (!check_trace_freq(speed, *trace_freq))
- return ERROR_FAIL;
+ if (!calculate_swo_prescaler(traceclkin_freq, *trace_freq,
+ prescaler)) {
+ LOG_ERROR("SWO frequency is not suitable. Please choose a "
+ "different frequency or use auto-detection.");
+ return ERROR_FAIL;
+ }
+ } else {
+ LOG_INFO("Trying to auto-detect SWO frequency.");
- LOG_DEBUG("Using %u bytes device memory for trace capturing.", buffer_size);
+ if (!detect_swo_freq_and_prescaler(speed, traceclkin_freq, trace_freq,
+ prescaler)) {
+ LOG_ERROR("Maximum permitted frequency deviation of %.02f %% "
+ "could not be achieved.", SWO_MAX_FREQ_DEV);
+ LOG_ERROR("Auto-detection of SWO frequency failed.");
+ return ERROR_FAIL;
+ }
+
+ LOG_INFO("Using SWO frequency of %u Hz.", *trace_freq);
+ }
ret = jaylink_swo_start(devh, JAYLINK_SWO_MODE_UART, *trace_freq,
buffer_size);
@@ -1365,6 +1420,9 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
return ERROR_FAIL;
}
+ LOG_DEBUG("Using %u bytes device memory for trace capturing.",
+ buffer_size);
+
/*
* Adjust the SWD transaction buffer size as starting SWO capturing
* allocates device internal memory.
@@ -1470,7 +1528,7 @@ COMMAND_HANDLER(jlink_handle_config_mac_address_command)
} else if (CMD_ARGC == 1) {
str = CMD_ARGV[0];
- if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' || \
+ if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' ||
str[8] != ':' || str[11] != ':' || str[14] != ':')) {
command_print(CMD, "Invalid MAC address format.");
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -2212,17 +2270,24 @@ static const struct swd_driver jlink_swd = {
static const char * const jlink_transports[] = { "jtag", "swd", NULL };
-struct jtag_interface jlink_interface = {
+static struct jtag_interface jlink_interface = {
+ .execute_queue = &jlink_execute_queue,
+};
+
+struct adapter_driver jlink_adapter_driver = {
.name = "jlink",
- .commands = jlink_command_handlers,
.transports = jlink_transports,
- .swd = &jlink_swd,
- .execute_queue = &jlink_execute_queue,
- .speed = &jlink_speed,
- .speed_div = &jlink_speed_div,
- .khz = &jlink_khz,
+ .commands = jlink_command_handlers,
+
.init = &jlink_init,
.quit = &jlink_quit,
+ .reset = &jlink_reset_safe,
+ .speed = &jlink_speed,
+ .khz = &jlink_khz,
+ .speed_div = &jlink_speed_div,
.config_trace = &config_trace,
.poll_trace = &poll_trace,
+
+ .jtag_ops = &jlink_interface,
+ .swd_ops = &jlink_swd,
};
diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c
index 1033ced..a5a95a5 100644
--- a/src/jtag/drivers/jtag_vpi.c
+++ b/src/jtag/drivers/jtag_vpi.c
@@ -33,6 +33,8 @@
#include <netinet/tcp.h>
#endif
+#include <string.h>
+
#define NO_TAP_SHIFT 0
#define TAP_SHIFT 1
@@ -47,34 +49,160 @@
#define CMD_SCAN_CHAIN_FLIP_TMS 3
#define CMD_STOP_SIMU 4
-int server_port = SERVER_PORT;
-char *server_address;
+/* jtag_vpi server port and address to connect to */
+static int server_port = SERVER_PORT;
+static char *server_address;
+
+/* Send CMD_STOP_SIMU to server when OpenOCD exits? */
+static bool stop_sim_on_exit;
-int sockfd;
-struct sockaddr_in serv_addr;
+static int sockfd;
+static struct sockaddr_in serv_addr;
+/* One jtag_vpi "packet" as sent over a TCP channel. */
struct vpi_cmd {
- int cmd;
+ union {
+ uint32_t cmd;
+ unsigned char cmd_buf[4];
+ };
unsigned char buffer_out[XFERT_MAX_SIZE];
unsigned char buffer_in[XFERT_MAX_SIZE];
- int length;
- int nb_bits;
+ union {
+ uint32_t length;
+ unsigned char length_buf[4];
+ };
+ union {
+ uint32_t nb_bits;
+ unsigned char nb_bits_buf[4];
+ };
};
+static char *jtag_vpi_cmd_to_str(int cmd_num)
+{
+ switch (cmd_num) {
+ case CMD_RESET:
+ return "CMD_RESET";
+ case CMD_TMS_SEQ:
+ return "CMD_TMS_SEQ";
+ case CMD_SCAN_CHAIN:
+ return "CMD_SCAN_CHAIN";
+ case CMD_SCAN_CHAIN_FLIP_TMS:
+ return "CMD_SCAN_CHAIN_FLIP_TMS";
+ case CMD_STOP_SIMU:
+ return "CMD_STOP_SIMU";
+ default:
+ return "<unknown>";
+ }
+}
+
static int jtag_vpi_send_cmd(struct vpi_cmd *vpi)
{
- int retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
- if (retval <= 0)
- return ERROR_FAIL;
+ int retval;
+
+ /* Optional low-level JTAG debug */
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
+ if (vpi->nb_bits > 0) {
+ /* command with a non-empty data payload */
+ char *char_buf = buf_to_str(vpi->buffer_out,
+ (vpi->nb_bits > DEBUG_JTAG_IOZ)
+ ? DEBUG_JTAG_IOZ
+ : vpi->nb_bits,
+ 16);
+ LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
+ "length=%" PRIu32 ", "
+ "nb_bits=%" PRIu32 ", "
+ "buf_out=0x%s%s",
+ jtag_vpi_cmd_to_str(vpi->cmd),
+ vpi->length,
+ vpi->nb_bits,
+ char_buf,
+ (vpi->nb_bits > DEBUG_JTAG_IOZ) ? "(...)" : "");
+ free(char_buf);
+ } else {
+ /* command without data payload */
+ LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
+ "length=%" PRIu32 ", "
+ "nb_bits=%" PRIu32,
+ jtag_vpi_cmd_to_str(vpi->cmd),
+ vpi->length,
+ vpi->nb_bits);
+ }
+ }
+ /* Use little endian when transmitting/receiving jtag_vpi cmds.
+ The choice of little endian goes against usual networking conventions
+ but is intentional to remain compatible with most older OpenOCD builds
+ (i.e. builds on little-endian platforms). */
+ h_u32_to_le(vpi->cmd_buf, vpi->cmd);
+ h_u32_to_le(vpi->length_buf, vpi->length);
+ h_u32_to_le(vpi->nb_bits_buf, vpi->nb_bits);
+
+retry_write:
+ retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
+
+ if (retval < 0) {
+ /* Account for the case when socket write is interrupted. */
+#ifdef _WIN32
+ int wsa_err = WSAGetLastError();
+ if (wsa_err == WSAEINTR)
+ goto retry_write;
+#else
+ if (errno == EINTR)
+ goto retry_write;
+#endif
+ /* Otherwise this is an error using the socket, most likely fatal
+ for the connection. B*/
+ log_socket_error("jtag_vpi xmit");
+ /* TODO: Clean way how adapter drivers can report fatal errors
+ to upper layers of OpenOCD and let it perform an orderly shutdown? */
+ exit(-1);
+ } else if (retval < (int)sizeof(struct vpi_cmd)) {
+ /* This means we could not send all data, which is most likely fatal
+ for the jtag_vpi connection (the underlying TCP connection likely not
+ usable anymore) */
+ LOG_ERROR("Could not send all data through jtag_vpi connection.");
+ exit(-1);
+ }
+
+ /* Otherwise the packet has been sent successfully. */
return ERROR_OK;
}
static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
{
- int retval = read_socket(sockfd, vpi, sizeof(struct vpi_cmd));
- if (retval < (int)sizeof(struct vpi_cmd))
- return ERROR_FAIL;
+ unsigned bytes_buffered = 0;
+ while (bytes_buffered < sizeof(struct vpi_cmd)) {
+ int bytes_to_receive = sizeof(struct vpi_cmd) - bytes_buffered;
+ int retval = read_socket(sockfd, ((char *)vpi) + bytes_buffered, bytes_to_receive);
+ if (retval < 0) {
+#ifdef _WIN32
+ int wsa_err = WSAGetLastError();
+ if (wsa_err == WSAEINTR) {
+ /* socket read interrupted by WSACancelBlockingCall() */
+ continue;
+ }
+#else
+ if (errno == EINTR) {
+ /* socket read interrupted by a signal */
+ continue;
+ }
+#endif
+ /* Otherwise, this is an error when accessing the socket. */
+ log_socket_error("jtag_vpi recv");
+ exit(-1);
+ } else if (retval == 0) {
+ /* Connection closed by the other side */
+ LOG_ERROR("Connection prematurely closed by jtag_vpi server.");
+ exit(-1);
+ }
+ /* Otherwise, we have successfully received some data */
+ bytes_buffered += retval;
+ }
+
+ /* Use little endian when transmitting/receiving jtag_vpi cmds. */
+ vpi->cmd = le_to_h_u32(vpi->cmd_buf);
+ vpi->length = le_to_h_u32(vpi->length_buf);
+ vpi->nb_bits = le_to_h_u32(vpi->nb_bits_buf);
return ERROR_OK;
}
@@ -87,6 +215,7 @@ static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
static int jtag_vpi_reset(int trst, int srst)
{
struct vpi_cmd vpi;
+ memset(&vpi, 0, sizeof(struct vpi_cmd));
vpi.cmd = CMD_RESET;
vpi.length = 0;
@@ -109,6 +238,7 @@ static int jtag_vpi_tms_seq(const uint8_t *bits, int nb_bits)
struct vpi_cmd vpi;
int nb_bytes;
+ memset(&vpi, 0, sizeof(struct vpi_cmd));
nb_bytes = DIV_ROUND_UP(nb_bits, 8);
vpi.cmd = CMD_TMS_SEQ;
@@ -176,6 +306,8 @@ static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
struct vpi_cmd vpi;
int nb_bytes = DIV_ROUND_UP(nb_bits, 8);
+ memset(&vpi, 0, sizeof(struct vpi_cmd));
+
vpi.cmd = tap_shift ? CMD_SCAN_CHAIN_FLIP_TMS : CMD_SCAN_CHAIN;
if (bits)
@@ -194,6 +326,16 @@ static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
if (retval != ERROR_OK)
return retval;
+ /* Optional low-level JTAG debug */
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
+ char *char_buf = buf_to_str(vpi.buffer_in,
+ (nb_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : nb_bits,
+ 16);
+ LOG_DEBUG_IO("recvd JTAG VPI data: nb_bits=%d, buf_in=0x%s%s",
+ nb_bits, char_buf, (nb_bits > DEBUG_JTAG_IOZ) ? "(...)" : "");
+ free(char_buf);
+ }
+
if (bits)
memcpy(bits, vpi.buffer_in, nb_bytes);
@@ -384,6 +526,11 @@ static int jtag_vpi_execute_queue(void)
case JTAG_SCAN:
retval = jtag_vpi_scan(cmd->cmd.scan);
break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type 0x%X",
+ cmd->type);
+ retval = ERROR_FAIL;
+ break;
}
}
@@ -433,10 +580,28 @@ static int jtag_vpi_init(void)
return ERROR_OK;
}
+static int jtag_vpi_stop_simulation(void)
+{
+ struct vpi_cmd cmd;
+ memset(&cmd, 0, sizeof(struct vpi_cmd));
+ cmd.length = 0;
+ cmd.nb_bits = 0;
+ cmd.cmd = CMD_STOP_SIMU;
+ return jtag_vpi_send_cmd(&cmd);
+}
+
static int jtag_vpi_quit(void)
{
+ if (stop_sim_on_exit) {
+ if (jtag_vpi_stop_simulation() != ERROR_OK)
+ LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
+ }
+ if (close_socket(sockfd) != 0) {
+ LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
+ log_socket_error("jtag_vpi");
+ }
free(server_address);
- return close(sockfd);
+ return ERROR_OK;
}
COMMAND_HANDLER(jtag_vpi_set_port)
@@ -466,31 +631,55 @@ COMMAND_HANDLER(jtag_vpi_set_address)
return ERROR_OK;
}
+COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler)
+{
+ if (CMD_ARGC != 1) {
+ LOG_ERROR("jtag_vpi_stop_sim_on_exit expects 1 argument (on|off)");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ } else {
+ COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit);
+ }
+ return ERROR_OK;
+}
+
static const struct command_registration jtag_vpi_command_handlers[] = {
{
.name = "jtag_vpi_set_port",
.handler = &jtag_vpi_set_port,
.mode = COMMAND_CONFIG,
.help = "set the port of the VPI server",
- .usage = "description_string",
+ .usage = "tcp_port_num",
},
{
.name = "jtag_vpi_set_address",
.handler = &jtag_vpi_set_address,
.mode = COMMAND_CONFIG,
.help = "set the address of the VPI server",
- .usage = "description_string",
+ .usage = "ipv4_addr",
+ },
+ {
+ .name = "jtag_vpi_stop_sim_on_exit",
+ .handler = &jtag_vpi_stop_sim_on_exit_handler,
+ .mode = COMMAND_CONFIG,
+ .help = "Configure if simulation stop command shall be sent "
+ "before OpenOCD exits (default: off)",
+ .usage = "<on|off>",
},
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface jtag_vpi_interface = {
- .name = "jtag_vpi",
+static struct jtag_interface jtag_vpi_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
- .commands = jtag_vpi_command_handlers,
+ .execute_queue = jtag_vpi_execute_queue,
+};
+
+struct adapter_driver jtag_vpi_adapter_driver = {
+ .name = "jtag_vpi",
.transports = jtag_only,
+ .commands = jtag_vpi_command_handlers,
.init = jtag_vpi_init,
.quit = jtag_vpi_quit,
- .execute_queue = jtag_vpi_execute_queue,
+
+ .jtag_ops = &jtag_vpi_interface,
};
diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c
index e3ad84d..efb8da2 100644
--- a/src/jtag/drivers/kitprog.c
+++ b/src/jtag/drivers/kitprog.c
@@ -43,7 +43,7 @@
#include <jtag/swd.h>
#include <jtag/commands.h>
-#include "libusb_common.h"
+#include "libusb_helper.h"
#define VID 0x04b4
#define PID 0xf139
@@ -95,7 +95,7 @@
struct kitprog {
hid_device *hid_handle;
- struct jtag_libusb_device_handle *usb_handle;
+ struct libusb_device_handle *usb_handle;
uint16_t packet_size;
uint16_t packet_index;
uint8_t *packet_buffer;
@@ -280,7 +280,7 @@ static int kitprog_usb_open(void)
const uint16_t pids[] = { PID, 0 };
if (jtag_libusb_open(vids, pids, kitprog_serial,
- &kitprog_handle->usb_handle) != ERROR_OK) {
+ &kitprog_handle->usb_handle, NULL) != ERROR_OK) {
LOG_ERROR("Failed to open or find the device");
return ERROR_FAIL;
}
@@ -311,7 +311,7 @@ static int kitprog_usb_open(void)
}
/* Claim the KitProg Programmer (bulk transfer) interface */
- if (jtag_libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) {
+ if (libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) {
LOG_ERROR("Failed to claim KitProg Programmer (bulk transfer) interface");
return ERROR_FAIL;
}
@@ -358,7 +358,7 @@ static int kitprog_get_version(void)
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_WRITE, 0x00, HID_COMMAND_VERSION};
unsigned char data[64];
- ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
+ ret = kitprog_hid_command(command, sizeof(command), data, sizeof(data));
if (ret != ERROR_OK)
return ret;
@@ -376,7 +376,7 @@ static int kitprog_get_millivolts(void)
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_READ, 0x00, HID_COMMAND_POWER};
unsigned char data[64];
- ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
+ ret = kitprog_hid_command(command, sizeof(command), data, sizeof(data));
if (ret != ERROR_OK)
return ret;
@@ -603,7 +603,7 @@ static int kitprog_generic_acquire(void)
* will take the Cortex-M3 out of reset and enable debugging.
*/
for (int i = 0; i < 2; i++) {
- for (uint8_t j = 0; j < sizeof devices && acquire_count == i; j++) {
+ for (uint8_t j = 0; j < sizeof(devices) && acquire_count == i; j++) {
retval = kitprog_acquire_psoc(devices[j], ACQUIRE_MODE_RESET, 3);
if (retval != ERROR_OK) {
LOG_DEBUG("Aquisition function failed for device 0x%02x.", devices[j]);
@@ -731,14 +731,14 @@ static int kitprog_swd_run_queue(void)
}
}
- ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle,
- BULK_EP_OUT, (char *)buffer, write_count, 0);
- if (ret > 0) {
- queued_retval = ERROR_OK;
- } else {
+ if (jtag_libusb_bulk_write(kitprog_handle->usb_handle,
+ BULK_EP_OUT, (char *)buffer,
+ write_count, 0, &ret)) {
LOG_ERROR("Bulk write failed");
queued_retval = ERROR_FAIL;
break;
+ } else {
+ queued_retval = ERROR_OK;
}
/* KitProg firmware does not send a zero length packet
@@ -754,18 +754,17 @@ static int kitprog_swd_run_queue(void)
if (read_count % 64 == 0)
read_count_workaround = read_count;
- ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle,
+ if (jtag_libusb_bulk_read(kitprog_handle->usb_handle,
BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer,
- read_count_workaround, 1000);
- if (ret > 0) {
+ read_count_workaround, 1000, &ret)) {
+ LOG_ERROR("Bulk read failed");
+ queued_retval = ERROR_FAIL;
+ break;
+ } else {
/* Handle garbage data by offsetting the initial read index */
if ((unsigned int)ret > read_count)
read_index = ret - read_count;
queued_retval = ERROR_OK;
- } else {
- LOG_ERROR("Bulk read failed");
- queued_retval = ERROR_FAIL;
- break;
}
for (int i = 0; i < pending_transfer_count; i++) {
@@ -819,11 +818,16 @@ static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
/*************** jtag lowlevel functions ********************/
-static void kitprog_execute_reset(struct jtag_command *cmd)
+static int kitprog_reset(int trst, int srst)
{
int retval = ERROR_OK;
- if (cmd->cmd.reset->srst == 1) {
+ if (trst == 1) {
+ LOG_ERROR("KitProg: Interface has no TRST");
+ return ERROR_FAIL;
+ }
+
+ if (srst == 1) {
retval = kitprog_reset_target();
/* Since the previous command also disables SWCLK output, we need to send an
* SWD bus reset command to re-enable it. For some reason, running
@@ -836,38 +840,7 @@ static void kitprog_execute_reset(struct jtag_command *cmd)
if (retval != ERROR_OK)
LOG_ERROR("KitProg: Interface reset failed");
-}
-
-static void kitprog_execute_sleep(struct jtag_command *cmd)
-{
- jtag_sleep(cmd->cmd.sleep->us);
-}
-
-static void kitprog_execute_command(struct jtag_command *cmd)
-{
- switch (cmd->type) {
- case JTAG_RESET:
- kitprog_execute_reset(cmd);
- break;
- case JTAG_SLEEP:
- kitprog_execute_sleep(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
-}
-
-static int kitprog_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue;
-
- while (cmd != NULL) {
- kitprog_execute_command(cmd);
- cmd = cmd->next;
- }
-
- return ERROR_OK;
+ return retval;
}
COMMAND_HANDLER(kitprog_handle_info_command)
@@ -961,12 +934,14 @@ static const struct swd_driver kitprog_swd = {
static const char * const kitprog_transports[] = { "swd", NULL };
-struct jtag_interface kitprog_interface = {
+struct adapter_driver kitprog_adapter_driver = {
.name = "kitprog",
- .commands = kitprog_command_handlers,
.transports = kitprog_transports,
- .swd = &kitprog_swd,
- .execute_queue = kitprog_execute_queue,
+ .commands = kitprog_command_handlers,
+
.init = kitprog_init,
- .quit = kitprog_quit
+ .quit = kitprog_quit,
+ .reset = kitprog_reset,
+
+ .swd_ops = &kitprog_swd,
};
diff --git a/src/jtag/drivers/libusb0_common.c b/src/jtag/drivers/libusb0_common.c
deleted file mode 100644
index 14a8b61..0000000
--- a/src/jtag/drivers/libusb0_common.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * 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, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "log.h"
-#include "libusb0_common.h"
-
-static bool jtag_libusb_match(struct jtag_libusb_device *dev,
- const uint16_t vids[], const uint16_t pids[])
-{
- for (unsigned i = 0; vids[i]; i++) {
- if (dev->descriptor.idVendor == vids[i] &&
- dev->descriptor.idProduct == pids[i]) {
- return true;
- }
- }
- return false;
-}
-
-/* Returns true if the string descriptor indexed by str_index in device matches string */
-static bool string_descriptor_equal(usb_dev_handle *device, uint8_t str_index,
- const char *string)
-{
- int retval;
- bool matched;
- char desc_string[256+1]; /* Max size of string descriptor */
-
- if (str_index == 0)
- return false;
-
- retval = usb_get_string_simple(device, str_index,
- desc_string, sizeof(desc_string)-1);
- if (retval < 0) {
- LOG_ERROR("usb_get_string_simple() failed with %d", retval);
- return false;
- }
-
- /* Null terminate descriptor string in case it needs to be logged. */
- desc_string[sizeof(desc_string)-1] = '\0';
-
- matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
- if (!matched)
- LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
- desc_string, string);
- return matched;
-}
-
-int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
- const char *serial,
- struct jtag_libusb_device_handle **out)
-{
- int retval = ERROR_FAIL;
- bool serial_mismatch = false;
- struct jtag_libusb_device_handle *libusb_handle;
- usb_init();
-
- usb_find_busses();
- usb_find_devices();
-
- struct usb_bus *busses = usb_get_busses();
- for (struct usb_bus *bus = busses; bus; bus = bus->next) {
- for (struct usb_device *dev = bus->devices;
- dev; dev = dev->next) {
- if (!jtag_libusb_match(dev, vids, pids))
- continue;
-
- libusb_handle = usb_open(dev);
- if (NULL == libusb_handle) {
- LOG_ERROR("usb_open() failed with %s", usb_strerror());
- continue;
- }
-
- /* Device must be open to use libusb_get_string_descriptor_ascii. */
- if (serial != NULL &&
- !string_descriptor_equal(libusb_handle, dev->descriptor.iSerialNumber, serial)) {
- serial_mismatch = true;
- usb_close(libusb_handle);
- continue;
- }
- *out = libusb_handle;
- retval = ERROR_OK;
- serial_mismatch = false;
- break;
- }
- }
-
- if (serial_mismatch)
- LOG_INFO("No device matches the serial string");
-
- return retval;
-}
-
-void jtag_libusb_close(jtag_libusb_device_handle *dev)
-{
- /* Close device */
- usb_close(dev);
-}
-
-int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType,
- uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes,
- uint16_t size, unsigned int timeout)
-{
- int transferred = 0;
-
- transferred = usb_control_msg(dev, requestType, request, wValue, wIndex,
- bytes, size, timeout);
-
- if (transferred < 0)
- transferred = 0;
-
- return transferred;
-}
-
-int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
-{
- return usb_bulk_write(dev, ep, bytes, size, timeout);
-}
-
-int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
-{
- return usb_bulk_read(dev, ep, bytes, size, timeout);
-}
-
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
- int configuration)
-{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
-
- return usb_set_configuration(devh,
- udev->config[configuration].bConfigurationValue);
-}
-
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
- unsigned int *usb_read_ep,
- unsigned int *usb_write_ep,
- int bclass, int subclass, int protocol, int trans_type)
-{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
- struct usb_interface *iface = udev->config->interface;
- struct usb_interface_descriptor *desc = iface->altsetting;
-
- *usb_read_ep = *usb_write_ep = 0;
-
- for (int i = 0; i < desc->bNumEndpoints; i++) {
- if ((bclass > 0 && desc->bInterfaceClass != bclass) ||
- (subclass > 0 && desc->bInterfaceSubClass != subclass) ||
- (protocol > 0 && desc->bInterfaceProtocol != protocol) ||
- (trans_type > 0 && (desc->endpoint[i].bmAttributes & 0x3) != trans_type))
- continue;
-
- uint8_t epnum = desc->endpoint[i].bEndpointAddress;
- bool is_input = epnum & 0x80;
- LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
- if (is_input)
- *usb_read_ep = epnum;
- else
- *usb_write_ep = epnum;
-
- if (*usb_read_ep && *usb_write_ep) {
- LOG_DEBUG("Claiming interface %d", (int)desc->bInterfaceNumber);
- usb_claim_interface(devh, (int)desc->bInterfaceNumber);
- return ERROR_OK;
- }
- }
-
- return ERROR_FAIL;
-}
-
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid)
-{
- if (!dev)
- return ERROR_FAIL;
-
- *pid = dev->descriptor.idProduct;
- return ERROR_OK;
-}
diff --git a/src/jtag/drivers/libusb0_common.h b/src/jtag/drivers/libusb0_common.h
deleted file mode 100644
index 676f43a..0000000
--- a/src/jtag/drivers/libusb0_common.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * 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, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H
-
-#include <usb.h>
-
-#define jtag_libusb_device usb_device
-#define jtag_libusb_device_handle usb_dev_handle
-#define jtag_libusb_device_descriptor usb_device_descriptor
-#define jtag_libusb_interface usb_interface
-#define jtag_libusb_interface_descriptor usb_interface_descriptor
-#define jtag_libusb_endpoint_descriptor usb_endpoint_descriptor
-#define jtag_libusb_config_descriptor usb_config_descriptor
-
-#define jtag_libusb_reset_device(dev) usb_reset(dev)
-#define jtag_libusb_get_device(devh) usb_device(devh)
-
-/* make some defines compatible to libusb1 */
-#define LIBUSB_REQUEST_TYPE_VENDOR USB_TYPE_VENDOR
-#define LIBUSB_RECIPIENT_DEVICE USB_RECIP_DEVICE
-#define LIBUSB_ENDPOINT_OUT USB_ENDPOINT_OUT
-#define LIBUSB_ENDPOINT_IN USB_ENDPOINT_IN
-#define LIBUSB_TRANSFER_TYPE_BULK USB_ENDPOINT_TYPE_BULK
-
-static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return usb_claim_interface(devh, iface);
-};
-
-static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return usb_release_interface(devh, iface);
-}
-
-int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
- const char *serial,
- struct jtag_libusb_device_handle **out);
-void jtag_libusb_close(jtag_libusb_device_handle *dev);
-int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
- uint8_t requestType, uint8_t request, uint16_t wValue,
- uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout);
-int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout);
-int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout);
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
- int configuration);
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
- unsigned int *usb_read_ep,
- unsigned int *usb_write_ep,
- int bclass, int subclass, int protocol, int trans_type);
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
-
-#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */
diff --git a/src/jtag/drivers/libusb_common.h b/src/jtag/drivers/libusb_common.h
deleted file mode 100644
index 599a0a9..0000000
--- a/src/jtag/drivers/libusb_common.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * 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, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
-
-#ifdef HAVE_LIBUSB1
-#include "libusb1_common.h"
-#else
-#include "libusb0_common.h"
-#endif
-
-#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */
diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb_helper.c
index d96ac76..184882a 100644
--- a/src/jtag/drivers/libusb1_common.c
+++ b/src/jtag/drivers/libusb_helper.c
@@ -21,7 +21,7 @@
#include "config.h"
#endif
#include <jtag/drivers/jtag_usb_common.h>
-#include "libusb1_common.h"
+#include "libusb_helper.h"
#include "log.h"
/*
@@ -33,7 +33,32 @@
static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
static libusb_device **devs; /**< The usb device list **/
-static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
+static int jtag_libusb_error(int err)
+{
+ switch (err) {
+ case LIBUSB_SUCCESS:
+ return ERROR_OK;
+ case LIBUSB_ERROR_TIMEOUT:
+ return ERROR_TIMEOUT_REACHED;
+ case LIBUSB_ERROR_IO:
+ case LIBUSB_ERROR_INVALID_PARAM:
+ case LIBUSB_ERROR_ACCESS:
+ case LIBUSB_ERROR_NO_DEVICE:
+ case LIBUSB_ERROR_NOT_FOUND:
+ case LIBUSB_ERROR_BUSY:
+ case LIBUSB_ERROR_OVERFLOW:
+ case LIBUSB_ERROR_PIPE:
+ case LIBUSB_ERROR_INTERRUPTED:
+ case LIBUSB_ERROR_NO_MEM:
+ case LIBUSB_ERROR_NOT_SUPPORTED:
+ case LIBUSB_ERROR_OTHER:
+ return ERROR_FAIL;
+ default:
+ return ERROR_FAIL;
+ }
+}
+
+static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
const uint16_t vids[], const uint16_t pids[])
{
for (unsigned i = 0; vids[i]; i++) {
@@ -98,14 +123,45 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in
return matched;
}
+static bool jtag_libusb_match_serial(libusb_device_handle *device,
+ struct libusb_device_descriptor *dev_desc, const char *serial,
+ adapter_get_alternate_serial_fn adapter_get_alternate_serial)
+{
+ if (string_descriptor_equal(device, dev_desc->iSerialNumber, serial))
+ return true;
+
+ /* check the alternate serial helper */
+ if (!adapter_get_alternate_serial)
+ return false;
+
+ /* get the alternate serial */
+ char *alternate_serial = adapter_get_alternate_serial(device, dev_desc);
+
+ /* check possible failures */
+ if (alternate_serial == NULL)
+ return false;
+
+ /* then compare and free the alternate serial */
+ bool match = false;
+ if (strcmp(serial, alternate_serial) == 0)
+ match = true;
+ else
+ LOG_DEBUG("Device alternate serial number '%s' doesn't match requested serial '%s'",
+ alternate_serial, serial);
+
+ free(alternate_serial);
+ return match;
+}
+
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *serial,
- struct jtag_libusb_device_handle **out)
+ struct libusb_device_handle **out,
+ adapter_get_alternate_serial_fn adapter_get_alternate_serial)
{
int cnt, idx, errCode;
int retval = ERROR_FAIL;
bool serial_mismatch = false;
- struct jtag_libusb_device_handle *libusb_handle = NULL;
+ struct libusb_device_handle *libusb_handle = NULL;
if (libusb_init(&jtag_libusb_context) < 0)
return ERROR_FAIL;
@@ -118,7 +174,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0)
continue;
- if (!jtag_libusb_match(&dev_desc, vids, pids))
+ if (!jtag_libusb_match_ids(&dev_desc, vids, pids))
continue;
if (jtag_usb_get_location() && !jtag_libusb_location_equal(devs[idx]))
@@ -134,7 +190,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
/* Device must be open to use libusb_get_string_descriptor_ascii. */
if (serial != NULL &&
- !string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) {
+ !jtag_libusb_match_serial(libusb_handle, &dev_desc, serial, adapter_get_alternate_serial)) {
serial_mismatch = true;
libusb_close(libusb_handle);
continue;
@@ -152,10 +208,13 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
if (serial_mismatch)
LOG_INFO("No device matches the serial string");
+ if (retval != ERROR_OK)
+ libusb_exit(jtag_libusb_context);
+
return retval;
}
-void jtag_libusb_close(jtag_libusb_device_handle *dev)
+void jtag_libusb_close(struct libusb_device_handle *dev)
{
/* Close device */
libusb_close(dev);
@@ -163,7 +222,7 @@ void jtag_libusb_close(jtag_libusb_device_handle *dev)
libusb_exit(jtag_libusb_context);
}
-int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType,
+int jtag_libusb_control_transfer(struct libusb_device_handle *dev, uint8_t requestType,
uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes,
uint16_t size, unsigned int timeout)
{
@@ -178,30 +237,44 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t request
return transferred;
}
-int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
+int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep, char *bytes,
+ int size, int timeout, int *transferred)
{
- int transferred = 0;
+ int ret;
- libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
- &transferred, timeout);
- return transferred;
+ *transferred = 0;
+
+ ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
+ transferred, timeout);
+ if (ret != LIBUSB_SUCCESS) {
+ LOG_ERROR("libusb_bulk_write error: %s", libusb_error_name(ret));
+ return jtag_libusb_error(ret);
+ }
+
+ return ERROR_OK;
}
-int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
+int jtag_libusb_bulk_read(struct libusb_device_handle *dev, int ep, char *bytes,
+ int size, int timeout, int *transferred)
{
- int transferred = 0;
+ int ret;
- libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
- &transferred, timeout);
- return transferred;
+ *transferred = 0;
+
+ ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
+ transferred, timeout);
+ if (ret != LIBUSB_SUCCESS) {
+ LOG_ERROR("libusb_bulk_read error: %s", libusb_error_name(ret));
+ return jtag_libusb_error(ret);
+ }
+
+ return ERROR_OK;
}
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
+int jtag_libusb_set_configuration(struct libusb_device_handle *devh,
int configuration)
{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
+ struct libusb_device *udev = libusb_get_device(devh);
int retCode = -99;
struct libusb_config_descriptor *config = NULL;
@@ -226,12 +299,12 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
return retCode;
}
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
+int jtag_libusb_choose_interface(struct libusb_device_handle *devh,
unsigned int *usb_read_ep,
unsigned int *usb_write_ep,
int bclass, int subclass, int protocol, int trans_type)
{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
+ struct libusb_device *udev = libusb_get_device(devh);
const struct libusb_interface *inter;
const struct libusb_interface_descriptor *interdesc;
const struct libusb_endpoint_descriptor *epdesc;
@@ -278,7 +351,7 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
return ERROR_FAIL;
}
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid)
+int jtag_libusb_get_pid(struct libusb_device *dev, uint16_t *pid)
{
struct libusb_device_descriptor dev_desc;
diff --git a/src/jtag/drivers/libusb1_common.h b/src/jtag/drivers/libusb_helper.h
index 7c73d29..74bb23c 100644
--- a/src/jtag/drivers/libusb1_common.h
+++ b/src/jtag/drivers/libusb_helper.h
@@ -17,46 +17,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
-#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H
+#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H
+#define OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H
#include <libusb.h>
-#define jtag_libusb_device libusb_device
-#define jtag_libusb_device_handle libusb_device_handle
-#define jtag_libusb_device_descriptor libusb_device_descriptor
-#define jtag_libusb_interface libusb_interface
-#define jtag_libusb_interface_descriptor libusb_interface_descriptor
-#define jtag_libusb_endpoint_descriptor libusb_endpoint_descriptor
-#define jtag_libusb_config_descriptor libusb_config_descriptor
-
-#define jtag_libusb_reset_device(dev) libusb_reset_device(dev)
-#define jtag_libusb_get_device(devh) libusb_get_device(devh)
-
-static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return libusb_claim_interface(devh, iface);
-};
-
-static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return libusb_release_interface(devh, iface);
-}
+/* this callback should return a non NULL value only when the serial could not
+ * be retrieved by the standard 'libusb_get_string_descriptor_ascii' */
+typedef char * (*adapter_get_alternate_serial_fn)(libusb_device_handle *device,
+ struct libusb_device_descriptor *dev_desc);
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *serial,
- struct jtag_libusb_device_handle **out);
-void jtag_libusb_close(jtag_libusb_device_handle *dev);
-int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
+ struct libusb_device_handle **out,
+ adapter_get_alternate_serial_fn adapter_get_alternate_serial);
+void jtag_libusb_close(struct libusb_device_handle *dev);
+int jtag_libusb_control_transfer(struct libusb_device_handle *dev,
uint8_t requestType, uint8_t request, uint16_t wValue,
uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout);
-int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout);
-int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout);
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
+int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep,
+ char *bytes, int size, int timeout, int *transferred);
+int jtag_libusb_bulk_read(struct libusb_device_handle *dev, int ep,
+ char *bytes, int size, int timeout, int *transferred);
+int jtag_libusb_set_configuration(struct libusb_device_handle *devh,
int configuration);
/**
* Find the first interface optionally matching class, subclass and
@@ -72,10 +55,10 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
* @param trans_type `bmAttributes Bits 0..1 Transfer type` to match, or -1 to ignore this field.
* @returns Returns ERROR_OK on success, ERROR_FAIL otherwise.
*/
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
+int jtag_libusb_choose_interface(struct libusb_device_handle *devh,
unsigned int *usb_read_ep,
unsigned int *usb_write_ep,
int bclass, int subclass, int protocol, int trans_type);
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
+int jtag_libusb_get_pid(struct libusb_device *dev, uint16_t *pid);
-#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */
+#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H */
diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c
index c0d883b..7488d9d 100644
--- a/src/jtag/drivers/mpsse.c
+++ b/src/jtag/drivers/mpsse.c
@@ -890,6 +890,7 @@ int mpsse_flush(struct mpsse_ctx *ctx)
/* Polling loop, more or less taken from libftdi */
int64_t start = timeval_ms();
+ int64_t warn_after = 2000;
while (!write_result.done || !read_result.done) {
struct timeval timeout_usb;
@@ -913,9 +914,11 @@ int mpsse_flush(struct mpsse_ctx *ctx)
}
}
- if (timeval_ms() - start > 2000) {
- LOG_ERROR("Timed out handling USB events in mpsse_flush().");
- break;
+ int64_t now = timeval_ms();
+ if (now - start > warn_after) {
+ LOG_WARNING("Haven't made progress in mpsse_flush() for %" PRId64
+ "ms.", now - start);
+ warn_after *= 2;
}
}
diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c
index 5f352af..bb223f4 100644
--- a/src/jtag/drivers/opendous.c
+++ b/src/jtag/drivers/opendous.c
@@ -32,7 +32,7 @@
#include <jtag/interface.h>
#include <jtag/commands.h>
-#include "libusb_common.h"
+#include "libusb_helper.h"
#include <string.h>
#include <time.h>
@@ -134,7 +134,7 @@ static void opendous_tap_append_scan(int length, uint8_t *buffer, struct scan_co
/* opendous lowlevel functions */
struct opendous_jtag {
- struct jtag_libusb_device_handle *usb_handle;
+ struct libusb_device_handle *usb_handle;
};
static struct opendous_jtag *opendous_usb_open(void);
@@ -234,13 +234,19 @@ static const struct command_registration opendous_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface opendous_interface = {
+static struct jtag_interface opendous_interface = {
+ .execute_queue = opendous_execute_queue,
+};
+
+struct adapter_driver opendous_adapter_driver = {
.name = "opendous",
.transports = jtag_only,
.commands = opendous_command_handlers,
- .execute_queue = opendous_execute_queue,
+
.init = opendous_init,
.quit = opendous_quit,
+
+ .jtag_ops = &opendous_interface,
};
static int opendous_execute_queue(void)
@@ -253,7 +259,7 @@ static int opendous_execute_queue(void)
while (cmd != NULL) {
switch (cmd->type) {
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \
+ LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
if (cmd->cmd.runtest->end_state != -1)
@@ -270,8 +276,8 @@ static int opendous_execute_queue(void)
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i", \
- cmd->cmd.pathmove->num_states, \
+ LOG_DEBUG_IO("pathmove: %i states, end in %i",
+ cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
opendous_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
@@ -708,12 +714,12 @@ struct opendous_jtag *opendous_usb_open(void)
{
struct opendous_jtag *result;
- struct jtag_libusb_device_handle *devh;
- if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh) != ERROR_OK)
+ struct libusb_device_handle *devh;
+ if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh, NULL) != ERROR_OK)
return NULL;
jtag_libusb_set_configuration(devh, 0);
- jtag_libusb_claim_interface(devh, 0);
+ libusb_claim_interface(devh, 0);
result = malloc(sizeof(*result));
result->usb_handle = devh;
@@ -764,8 +770,8 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
} else {
- result = jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \
- (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
+ jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT,
+ (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT, &result);
}
#ifdef _DEBUG_USB_COMMS_
LOG_DEBUG("USB write end: %d bytes", result);
@@ -791,8 +797,8 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
} else {
- result = jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
- (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
+ jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
+ (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT, &result);
}
#ifdef _DEBUG_USB_COMMS_
LOG_DEBUG("USB read end: %d bytes", result);
diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c
index 7a3aa23..7eab5c1 100644
--- a/src/jtag/drivers/openjtag.c
+++ b/src/jtag/drivers/openjtag.c
@@ -45,7 +45,7 @@
#include <jtag/interface.h>
#include <jtag/commands.h>
-#include "libusb_common.h"
+#include "libusb_helper.h"
static enum {
OPENJTAG_VARIANT_STANDARD,
@@ -111,7 +111,7 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
static int openjtag_scan_result_count;
-static jtag_libusb_device_handle *usbh;
+static struct libusb_device_handle *usbh;
/* CY7C65215 model only */
#define CY7C65215_JTAG_REQUEST 0x40 /* bmRequestType: vendor host-to-device */
@@ -229,7 +229,7 @@ static int openjtag_buf_write_standard(
return ERROR_JTAG_DEVICE_ERROR;
}
- *bytes_written += retval;
+ *bytes_written = retval;
return ERROR_OK;
}
@@ -256,10 +256,9 @@ static int openjtag_buf_write_cy7c65215(
return ERROR_JTAG_DEVICE_ERROR;
}
- ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
- CY7C65215_USB_TIMEOUT);
- if (ret < 0) {
- LOG_ERROR("bulk write failed, error %d", ret);
+ if (jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
+ CY7C65215_USB_TIMEOUT, &ret)) {
+ LOG_ERROR("bulk write failed, error");
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = ret;
@@ -324,10 +323,9 @@ static int openjtag_buf_read_cy7c65215(
return ERROR_JTAG_DEVICE_ERROR;
}
- ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
- CY7C65215_USB_TIMEOUT);
- if (ret < 0) {
- LOG_ERROR("bulk read failed, error %d", ret);
+ if (jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
+ CY7C65215_USB_TIMEOUT, &ret)) {
+ LOG_ERROR("bulk read failed, error");
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read = ret;
@@ -451,7 +449,7 @@ static int openjtag_init_cy7c65215(void)
int ret;
usbh = NULL;
- ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh);
+ ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh, NULL);
if (ret != ERROR_OK) {
LOG_ERROR("unable to open cy7c65215 device");
goto err;
@@ -654,7 +652,6 @@ static void openjtag_add_scan(uint8_t *buffer, int length, struct scan_command *
/* whole byte */
/* bits to transfer */
- bits = 7;
command |= (7 << 5);
length -= 8;
}
@@ -692,7 +689,7 @@ static void openjtag_execute_sleep(struct jtag_command *cmd)
static void openjtag_set_state(uint8_t openocd_state)
{
- int8_t state = openjtag_get_tap_state(openocd_state);
+ uint8_t state = openjtag_get_tap_state(openocd_state);
uint8_t buf = 0;
buf = 0x01;
@@ -892,17 +889,20 @@ static const struct command_registration openjtag_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface openjtag_interface = {
+static struct jtag_interface openjtag_interface = {
+ .execute_queue = openjtag_execute_queue,
+};
+
+struct adapter_driver openjtag_adapter_driver = {
.name = "openjtag",
.transports = jtag_only,
.commands = openjtag_command_handlers,
- .execute_queue = openjtag_execute_queue,
- .speed = openjtag_speed,
- .speed_div = openjtag_speed_div,
- .khz = openjtag_khz,
.init = openjtag_init,
.quit = openjtag_quit,
-};
-
+ .speed = openjtag_speed,
+ .khz = openjtag_khz,
+ .speed_div = openjtag_speed_div,
+ .jtag_ops = &openjtag_interface,
+};
diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c
index 5db36a1..dc23666 100644
--- a/src/jtag/drivers/osbdm.c
+++ b/src/jtag/drivers/osbdm.c
@@ -23,7 +23,7 @@
#include <helper/binarybuffer.h>
#include <helper/command.h>
#include <jtag/interface.h>
-#include "libusb_common.h"
+#include "libusb_helper.h"
struct sequence {
int len;
@@ -132,7 +132,7 @@ static const uint16_t osbdm_vid[] = { 0x15a2, 0x15a2, 0x15a2, 0 };
static const uint16_t osbdm_pid[] = { 0x0042, 0x0058, 0x005e, 0 };
struct osbdm {
- struct jtag_libusb_device_handle *devh; /* USB handle */
+ struct libusb_device_handle *devh; /* USB handle */
uint8_t buffer[OSBDM_USB_BUFSIZE]; /* Data to send and receive */
int count; /* Count data to send and to read */
};
@@ -144,10 +144,12 @@ static struct osbdm osbdm_context;
static int osbdm_send_and_recv(struct osbdm *osbdm)
{
/* Send request */
- int count = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
- (char *)osbdm->buffer, osbdm->count, OSBDM_USB_TIMEOUT);
+ int count, ret;
- if (count != osbdm->count) {
+ ret = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
+ (char *)osbdm->buffer, osbdm->count,
+ OSBDM_USB_TIMEOUT, &count);
+ if (ret || count != osbdm->count) {
LOG_ERROR("OSBDM communication error: can't write");
return ERROR_FAIL;
}
@@ -156,13 +158,12 @@ static int osbdm_send_and_recv(struct osbdm *osbdm)
uint8_t cmd_saved = osbdm->buffer[0];
/* Reading answer */
- osbdm->count = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
- (char *)osbdm->buffer, OSBDM_USB_BUFSIZE, OSBDM_USB_TIMEOUT);
-
+ ret = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
+ (char *)osbdm->buffer, OSBDM_USB_BUFSIZE,
+ OSBDM_USB_TIMEOUT, &osbdm->count);
/* Now perform basic checks for data sent by BDM device
*/
-
- if (osbdm->count < 0) {
+ if (ret) {
LOG_ERROR("OSBDM communication error: can't read");
return ERROR_FAIL;
}
@@ -296,7 +297,7 @@ static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi,
return ERROR_OK;
}
-static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
+static int osbdm_flush(struct osbdm *osbdm, struct queue *queue)
{
uint8_t tms[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
uint8_t tdi[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
@@ -373,10 +374,10 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
static int osbdm_open(struct osbdm *osbdm)
{
(void)memset(osbdm, 0, sizeof(*osbdm));
- if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK)
+ if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh, NULL) != ERROR_OK)
return ERROR_FAIL;
- if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
+ if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
@@ -688,12 +689,16 @@ static int osbdm_init(void)
return ERROR_OK;
}
-struct jtag_interface osbdm_interface = {
- .name = "osbdm",
+static struct jtag_interface osbdm_interface = {
+ .execute_queue = osbdm_execute_queue,
+};
+struct adapter_driver osbdm_adapter_driver = {
+ .name = "osbdm",
.transports = jtag_only,
- .execute_queue = osbdm_execute_queue,
.init = osbdm_init,
- .quit = osbdm_quit
+ .quit = osbdm_quit,
+
+ .jtag_ops = &osbdm_interface,
};
diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c
index 8e44dcb..b3abd12 100644
--- a/src/jtag/drivers/parport.c
+++ b/src/jtag/drivers/parport.c
@@ -237,7 +237,7 @@ static int parport_get_giveio_access(void)
HANDLE h;
OSVERSIONINFO version;
- version.dwOSVersionInfoSize = sizeof version;
+ version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) {
errno = EINVAL;
return -1;
@@ -260,7 +260,6 @@ static int parport_get_giveio_access(void)
static struct bitbang_interface parport_bitbang = {
.read = &parport_read,
.write = &parport_write,
- .reset = &parport_reset,
.blink = &parport_led,
};
@@ -514,16 +513,22 @@ static const struct command_registration parport_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface parport_interface = {
- .name = "parport",
+static struct jtag_interface parport_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
+ .execute_queue = bitbang_execute_queue,
+};
+
+struct adapter_driver parport_adapter_driver = {
+ .name = "parport",
.transports = jtag_only,
.commands = parport_command_handlers,
.init = parport_init,
.quit = parport_quit,
+ .reset = parport_reset,
+ .speed = parport_speed,
.khz = parport_khz,
.speed_div = parport_speed_div,
- .speed = parport_speed,
- .execute_queue = bitbang_execute_queue,
+
+ .jtag_ops = &parport_interface,
};
diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c
index 2a94d06..3849a27 100644
--- a/src/jtag/drivers/presto.c
+++ b/src/jtag/drivers/presto.c
@@ -561,15 +561,20 @@ static int presto_jtag_quit(void)
return ERROR_OK;
}
-struct jtag_interface presto_interface = {
+static struct jtag_interface presto_interface = {
+ .execute_queue = bitq_execute_queue,
+};
+
+struct adapter_driver presto_adapter_driver = {
.name = "presto",
.transports = jtag_only,
.commands = presto_command_handlers,
- .execute_queue = bitq_execute_queue,
+ .init = presto_jtag_init,
+ .quit = presto_jtag_quit,
.speed = presto_jtag_speed,
.khz = presto_adapter_khz,
.speed_div = presto_jtag_speed_div,
- .init = presto_jtag_init,
- .quit = presto_jtag_quit,
+
+ .jtag_ops = &presto_interface,
};
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index a354894..6637952 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -199,7 +199,6 @@ static struct bitbang_interface remote_bitbang_bitbang = {
.sample = &remote_bitbang_sample,
.read_sample = &remote_bitbang_read_sample,
.write = &remote_bitbang_write,
- .reset = &remote_bitbang_reset,
.blink = &remote_bitbang_blink,
};
@@ -342,11 +341,18 @@ static const struct command_registration remote_bitbang_command_handlers[] = {
COMMAND_REGISTRATION_DONE,
};
-struct jtag_interface remote_bitbang_interface = {
- .name = "remote_bitbang",
+static struct jtag_interface remote_bitbang_interface = {
.execute_queue = &bitbang_execute_queue,
+};
+
+struct adapter_driver remote_bitbang_adapter_driver = {
+ .name = "remote_bitbang",
.transports = jtag_only,
.commands = remote_bitbang_command_handlers,
+
.init = &remote_bitbang_init,
.quit = &remote_bitbang_quit,
+ .reset = &remote_bitbang_reset,
+
+ .jtag_ops = &remote_bitbang_interface,
};
diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c
index 317e8b8..e053399 100644
--- a/src/jtag/drivers/rlink.c
+++ b/src/jtag/drivers/rlink.c
@@ -1660,13 +1660,19 @@ static int rlink_quit(void)
return ERROR_OK;
}
-struct jtag_interface rlink_interface = {
+static struct jtag_interface rlink_interface = {
+ .execute_queue = rlink_execute_queue,
+};
+
+struct adapter_driver rlink_adapter_driver = {
.name = "rlink",
.transports = jtag_only,
+
.init = rlink_init,
.quit = rlink_quit,
.speed = rlink_speed,
- .speed_div = rlink_speed_div,
.khz = rlink_khz,
- .execute_queue = rlink_execute_queue,
+ .speed_div = rlink_speed_div,
+
+ .jtag_ops = &rlink_interface,
};
diff --git a/src/jtag/drivers/rlink_call.m4 b/src/jtag/drivers/rlink_call.m4
index b27f392..bf07afa 100644
--- a/src/jtag/drivers/rlink_call.m4
+++ b/src/jtag/drivers/rlink_call.m4
@@ -479,5 +479,3 @@ m4_delay(HOLD_DELAY_CYCLES - 10)
A = X
DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
BRANCH
-
-
diff --git a/src/jtag/drivers/rlink_speed_table.c b/src/jtag/drivers/rlink_speed_table.c
index b843577..660aac4 100644
--- a/src/jtag/drivers/rlink_speed_table.c
+++ b/src/jtag/drivers/rlink_speed_table.c
@@ -98,4 +98,3 @@ const struct rlink_speed_table rlink_speed_table[] = {{
} };
const size_t rlink_speed_table_size = ARRAY_SIZE(rlink_speed_table);
-
diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c
new file mode 100644
index 0000000..c718af5
--- /dev/null
+++ b/src/jtag/drivers/rshim.c
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 2020, Mellanox Technologies Ltd. - All Rights Reserved
+ * Liming Sun <lsun@mellanox.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/types.h>
+#include <helper/system.h>
+#include <helper/time_support.h>
+#include <helper/list.h>
+#include <jtag/interface.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#include <target/arm_adi_v5.h>
+#include <transport/transport.h>
+
+/* Rshim channel where the CoreSight register resides. */
+#define RSH_MMIO_CHANNEL_RSHIM 0x1
+
+/* APB and tile address translation. */
+#define RSH_CS_ROM_BASE 0x80000000
+#define RSH_CS_TILE_BASE 0x44000000
+#define RSH_CS_TILE_SIZE 0x04000000
+
+/*
+ * APB-AP Identification Register
+ * The default value is defined in "CoreSight on-chip trace and debug
+ * (Revision: r1p0)", Section 3.16.5 APB-AP register summary.
+ */
+#define APB_AP_IDR 0x44770002
+
+/* CoreSight register definition. */
+#define RSH_CORESIGHT_CTL 0x0e00
+#define RSH_CORESIGHT_CTL_GO_SHIFT 0
+#define RSH_CORESIGHT_CTL_GO_MASK 0x1ULL
+#define RSH_CORESIGHT_CTL_ACTION_SHIFT 1
+#define RSH_CORESIGHT_CTL_ACTION_MASK 0x2ULL
+#define RSH_CORESIGHT_CTL_ADDR_SHIFT 2
+#define RSH_CORESIGHT_CTL_ADDR_MASK 0x7ffffffcULL
+#define RSH_CORESIGHT_CTL_ERR_SHIFT 31
+#define RSH_CORESIGHT_CTL_ERR_MASK 0x80000000ULL
+#define RSH_CORESIGHT_CTL_DATA_SHIFT 32
+#define RSH_CORESIGHT_CTL_DATA_MASK 0xffffffff00000000ULL
+
+/* Util macros to access the CoreSight register. */
+#define RSH_CS_GET_FIELD(reg, field) \
+ (((uint64_t)(reg) & RSH_CORESIGHT_CTL_##field##_MASK) >> \
+ RSH_CORESIGHT_CTL_##field##_SHIFT)
+
+#define RSH_CS_SET_FIELD(reg, field, value) \
+ (reg) = (((reg) & ~RSH_CORESIGHT_CTL_##field##_MASK) | \
+ (((uint64_t)(value) << RSH_CORESIGHT_CTL_##field##_SHIFT) & \
+ RSH_CORESIGHT_CTL_##field##_MASK))
+
+#ifdef HAVE_SYS_IOCTL_H
+/* Message used to program rshim via ioctl(). */
+typedef struct {
+ uint32_t addr;
+ uint64_t data;
+} __attribute__((packed)) rshim_ioctl_msg;
+
+enum {
+ RSH_IOC_READ = _IOWR('R', 0, rshim_ioctl_msg),
+ RSH_IOC_WRITE = _IOWR('R', 1, rshim_ioctl_msg),
+};
+#endif
+
+/* Use local variable stub for DP/AP registers. */
+static uint32_t dp_ctrl_stat;
+static uint32_t dp_id_code;
+static uint32_t ap_sel, ap_bank;
+static uint32_t ap_csw;
+static uint32_t ap_drw;
+static uint32_t ap_tar, ap_tar_inc;
+
+/* Static functions to read/write via rshim/coresight. */
+static int (*rshim_read)(int chan, int addr, uint64_t *value);
+static int (*rshim_write)(int chan, int addr, uint64_t value);
+static int coresight_write(uint32_t tile, uint32_t addr, uint32_t wdata);
+static int coresight_read(uint32_t tile, uint32_t addr, uint32_t *value);
+
+/* RShim file handler. */
+static int rshim_fd = -1;
+
+/* DAP error code. */
+static int rshim_dap_retval = ERROR_OK;
+
+/* Default rshim device. */
+#define RSHIM_DEV_PATH_DEFAULT "/dev/rshim0/rshim"
+static char *rshim_dev_path;
+
+static int rshim_dev_read(int chan, int addr, uint64_t *value)
+{
+ int rc;
+
+ addr = (addr & 0xFFFF) | (1 << 16);
+ rc = pread(rshim_fd, value, sizeof(*value), addr);
+
+#ifdef HAVE_SYS_IOCTL_H
+ if (rc < 0 && errno == ENOSYS) {
+ rshim_ioctl_msg msg;
+
+ msg.addr = addr;
+ msg.data = 0;
+ rc = ioctl(rshim_fd, RSH_IOC_READ, &msg);
+ if (!rc)
+ *value = msg.data;
+ }
+#endif
+
+ return rc;
+}
+
+static int rshim_dev_write(int chan, int addr, uint64_t value)
+{
+ int rc;
+
+ addr = (addr & 0xFFFF) | (1 << 16);
+ rc = pwrite(rshim_fd, &value, sizeof(value), addr);
+
+#ifdef HAVE_SYS_IOCTL_H
+ if (rc < 0 && errno == ENOSYS) {
+ rshim_ioctl_msg msg;
+
+ msg.addr = addr;
+ msg.data = value;
+ rc = ioctl(rshim_fd, RSH_IOC_WRITE, &msg);
+ }
+#endif
+
+ return rc;
+}
+
+/* Convert AP address to tile local address. */
+static void ap_addr_2_tile(int *tile, uint32_t *addr)
+{
+ *addr -= RSH_CS_ROM_BASE;
+
+ if (*addr < RSH_CS_TILE_BASE) {
+ *tile = 0;
+ } else {
+ *addr -= RSH_CS_TILE_BASE;
+ *tile = *addr / RSH_CS_TILE_SIZE + 1;
+ *addr = *addr % RSH_CS_TILE_SIZE;
+ }
+}
+
+/*
+ * Write 4 bytes on the APB bus.
+ * tile = 0: access the root CS_ROM table
+ * > 0: access the ROM table of cluster (tile - 1)
+ */
+static int coresight_write(uint32_t tile, uint32_t addr, uint32_t wdata)
+{
+ uint64_t ctl = 0;
+ int rc;
+
+ if (!rshim_read || !rshim_write)
+ return ERROR_FAIL;
+
+ /*
+ * ADDR[28] - must be set to 1 due to coresight ip.
+ * ADDR[27:24] - linear tile id
+ */
+ addr = (addr >> 2) | (tile << 24);
+ if (tile)
+ addr |= (1 << 28);
+ RSH_CS_SET_FIELD(ctl, ADDR, addr);
+ RSH_CS_SET_FIELD(ctl, ACTION, 0); /* write */
+ RSH_CS_SET_FIELD(ctl, DATA, wdata);
+ RSH_CS_SET_FIELD(ctl, GO, 1); /* start */
+
+ rshim_write(RSH_MMIO_CHANNEL_RSHIM, RSH_CORESIGHT_CTL, ctl);
+
+ do {
+ rc = rshim_read(RSH_MMIO_CHANNEL_RSHIM,
+ RSH_CORESIGHT_CTL, &ctl);
+ if (rc < 0) {
+ LOG_ERROR("Failed to read rshim.\n");
+ return rc;
+ }
+ } while (RSH_CS_GET_FIELD(ctl, GO));
+
+ return ERROR_OK;
+}
+
+static int coresight_read(uint32_t tile, uint32_t addr, uint32_t *value)
+{
+ uint64_t ctl = 0;
+ int rc;
+
+ if (!rshim_read || !rshim_write)
+ return ERROR_FAIL;
+
+ /*
+ * ADDR[28] - must be set to 1 due to coresight ip.
+ * ADDR[27:24] - linear tile id
+ */
+ addr = (addr >> 2) | (tile << 24);
+ if (tile)
+ addr |= (1 << 28);
+ RSH_CS_SET_FIELD(ctl, ADDR, addr);
+ RSH_CS_SET_FIELD(ctl, ACTION, 1); /* read */
+ RSH_CS_SET_FIELD(ctl, GO, 1); /* start */
+
+ rshim_write(RSH_MMIO_CHANNEL_RSHIM, RSH_CORESIGHT_CTL, ctl);
+
+ do {
+ rc = rshim_read(RSH_MMIO_CHANNEL_RSHIM,
+ RSH_CORESIGHT_CTL, &ctl);
+ if (rc < 0) {
+ LOG_ERROR("Failed to write rshim.\n");
+ return rc;
+ }
+ } while (RSH_CS_GET_FIELD(ctl, GO));
+
+ *value = RSH_CS_GET_FIELD(ctl, DATA);
+ return ERROR_OK;
+}
+
+static int rshim_dp_q_read(struct adiv5_dap *dap, unsigned int reg,
+ uint32_t *data)
+{
+ if (!data)
+ return ERROR_OK;
+
+ switch (reg) {
+ case DP_DPIDR:
+ *data = dp_id_code;
+ break;
+
+ case DP_CTRL_STAT:
+ *data = CDBGPWRUPACK | CSYSPWRUPACK;
+ break;
+
+ default:
+ break;
+ }
+
+ return ERROR_OK;
+}
+
+static int rshim_dp_q_write(struct adiv5_dap *dap, unsigned int reg,
+ uint32_t data)
+{
+ switch (reg) {
+ case DP_CTRL_STAT:
+ dp_ctrl_stat = data;
+ break;
+ case DP_SELECT:
+ ap_sel = (data & DP_SELECT_APSEL) >> 24;
+ ap_bank = (data & DP_SELECT_APBANK) >> 4;
+ break;
+ default:
+ LOG_INFO("Unknown command");
+ break;
+ }
+
+ return ERROR_OK;
+}
+
+static int rshim_ap_q_read(struct adiv5_ap *ap, unsigned int reg,
+ uint32_t *data)
+{
+ uint32_t addr;
+ int rc = ERROR_OK, tile;
+
+ switch (reg) {
+ case MEM_AP_REG_CSW:
+ *data = ap_csw;
+ break;
+
+ case MEM_AP_REG_CFG:
+ *data = 0;
+ break;
+
+ case MEM_AP_REG_BASE:
+ *data = RSH_CS_ROM_BASE;
+ break;
+
+ case AP_REG_IDR:
+ if (ap->ap_num == 0)
+ *data = APB_AP_IDR;
+ else
+ *data = 0;
+ break;
+
+ case MEM_AP_REG_BD0:
+ case MEM_AP_REG_BD1:
+ case MEM_AP_REG_BD2:
+ case MEM_AP_REG_BD3:
+ addr = (ap_tar & ~0xf) + (reg & 0x0C);
+ ap_addr_2_tile(&tile, &addr);
+ rc = coresight_read(tile, addr, data);
+ break;
+
+ case MEM_AP_REG_DRW:
+ addr = (ap_tar & ~0x3) + ap_tar_inc;
+ ap_addr_2_tile(&tile, &addr);
+ rc = coresight_read(tile, addr, data);
+ if (!rc && (ap_csw & CSW_ADDRINC_MASK))
+ ap_tar_inc += (ap_csw & 0x03) * 2;
+ break;
+
+ default:
+ LOG_INFO("Unknown command");
+ rc = ERROR_FAIL;
+ break;
+ }
+
+ /* Track the last error code. */
+ if (rc != ERROR_OK)
+ rshim_dap_retval = rc;
+
+ return rc;
+}
+
+static int rshim_ap_q_write(struct adiv5_ap *ap, unsigned int reg,
+ uint32_t data)
+{
+ int rc = ERROR_OK, tile;
+ uint32_t addr;
+
+ if (ap_bank != 0) {
+ rshim_dap_retval = ERROR_FAIL;
+ return ERROR_FAIL;
+ }
+
+ switch (reg) {
+ case MEM_AP_REG_CSW:
+ ap_csw = data;
+ break;
+
+ case MEM_AP_REG_TAR:
+ ap_tar = data;
+ ap_tar_inc = 0;
+ break;
+
+ case MEM_AP_REG_BD0:
+ case MEM_AP_REG_BD1:
+ case MEM_AP_REG_BD2:
+ case MEM_AP_REG_BD3:
+ addr = (ap_tar & ~0xf) + (reg & 0x0C);
+ ap_addr_2_tile(&tile, &addr);
+ rc = coresight_write(tile, addr, data);
+ break;
+
+ case MEM_AP_REG_DRW:
+ ap_drw = data;
+ addr = (ap_tar & ~0x3) + ap_tar_inc;
+ ap_addr_2_tile(&tile, &addr);
+ rc = coresight_write(tile, addr, data);
+ if (!rc && (ap_csw & CSW_ADDRINC_MASK))
+ ap_tar_inc += (ap_csw & 0x03) * 2;
+ break;
+
+ default:
+ rc = EINVAL;
+ break;
+ }
+
+ /* Track the last error code. */
+ if (rc != ERROR_OK)
+ rshim_dap_retval = rc;
+
+ return rc;
+}
+
+static int rshim_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack)
+{
+ return ERROR_OK;
+}
+
+static int rshim_dp_run(struct adiv5_dap *dap)
+{
+ int retval = rshim_dap_retval;
+
+ /* Clear the error code. */
+ rshim_dap_retval = ERROR_OK;
+
+ return retval;
+}
+
+static int rshim_connect(struct adiv5_dap *dap)
+{
+ char *path = rshim_dev_path ? rshim_dev_path : RSHIM_DEV_PATH_DEFAULT;
+
+ rshim_fd = open(path, O_RDWR | O_SYNC);
+ if (rshim_fd == -1) {
+ LOG_ERROR("Unable to open %s\n", path);
+ return ERROR_FAIL;
+ }
+
+ /*
+ * Set read/write operation via the device file. Funtion pointers
+ * are used here so more ways like remote accessing via socket could
+ * be added later.
+ */
+ rshim_read = rshim_dev_read;
+ rshim_write = rshim_dev_write;
+
+ return ERROR_OK;
+}
+
+static void rshim_disconnect(struct adiv5_dap *dap)
+{
+ if (rshim_fd != -1) {
+ close(rshim_fd);
+ rshim_fd = -1;
+ }
+}
+
+COMMAND_HANDLER(rshim_dap_device_command)
+{
+ if (CMD_ARGC != 1) {
+ command_print(CMD, "Too many arguments");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ free(rshim_dev_path);
+ rshim_dev_path = strdup(CMD_ARGV[0]);
+ return ERROR_OK;
+}
+
+static const struct command_registration rshim_dap_subcommand_handlers[] = {
+ {
+ .name = "device",
+ .handler = rshim_dap_device_command,
+ .mode = COMMAND_CONFIG,
+ .help = "set the rshim device",
+ .usage = "</dev/rshim<N>/rshim>",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration rshim_dap_command_handlers[] = {
+ {
+ .name = "rshim",
+ .mode = COMMAND_ANY,
+ .help = "perform rshim management",
+ .chain = rshim_dap_subcommand_handlers,
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static int rshim_dap_init(void)
+{
+ return ERROR_OK;
+}
+
+static int rshim_dap_quit(void)
+{
+ return ERROR_OK;
+}
+
+static int rshim_dap_reset(int req_trst, int req_srst)
+{
+ return ERROR_OK;
+}
+
+static int rshim_dap_speed(int speed)
+{
+ return ERROR_OK;
+}
+
+static int rshim_dap_khz(int khz, int *jtag_speed)
+{
+ *jtag_speed = khz;
+ return ERROR_OK;
+}
+
+static int rshim_dap_speed_div(int speed, int *khz)
+{
+ *khz = speed;
+ return ERROR_OK;
+}
+
+/* DAP operations. */
+static const struct dap_ops rshim_dap_ops = {
+ .connect = rshim_connect,
+ .queue_dp_read = rshim_dp_q_read,
+ .queue_dp_write = rshim_dp_q_write,
+ .queue_ap_read = rshim_ap_q_read,
+ .queue_ap_write = rshim_ap_q_write,
+ .queue_ap_abort = rshim_ap_q_abort,
+ .run = rshim_dp_run,
+ .quit = rshim_disconnect,
+};
+
+static const char *const rshim_dap_transport[] = { "dapdirect_swd", NULL };
+
+struct adapter_driver rshim_dap_adapter_driver = {
+ .name = "rshim",
+ .transports = rshim_dap_transport,
+ .commands = rshim_dap_command_handlers,
+
+ .init = rshim_dap_init,
+ .quit = rshim_dap_quit,
+ .reset = rshim_dap_reset,
+ .speed = rshim_dap_speed,
+ .khz = rshim_dap_khz,
+ .speed_div = rshim_dap_speed_div,
+
+ .dap_swd_ops = &rshim_dap_ops,
+};
diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index ea3dc00..72975d5 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -31,27 +31,31 @@
/* project specific includes */
#include <helper/binarybuffer.h>
+#include <helper/bits.h>
#include <jtag/interface.h>
#include <jtag/hla/hla_layout.h>
#include <jtag/hla/hla_transport.h>
#include <jtag/hla/hla_interface.h>
+#include <jtag/swim.h>
#include <target/target.h>
+#include <transport/transport.h>
#include <target/cortex_m.h>
-#include "libusb_common.h"
+#include "libusb_helper.h"
#ifdef HAVE_LIBUSB1
#define USE_LIBUSB_ASYNCIO
#endif
+#define STLINK_SERIAL_LEN 24
+
#define ENDPOINT_IN 0x80
#define ENDPOINT_OUT 0x00
#define STLINK_WRITE_TIMEOUT 1000
#define STLINK_READ_TIMEOUT 1000
-#define STLINK_NULL_EP 0
#define STLINK_RX_EP (1|ENDPOINT_IN)
#define STLINK_TX_EP (2|ENDPOINT_OUT)
#define STLINK_TRACE_EP (3|ENDPOINT_IN)
@@ -76,7 +80,7 @@
/*
* ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
* this limits the bulk packet size and the 8bit read/writes to max 64 bytes.
- * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes.
+ * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes from FW V3J6.
*/
#define STLINK_MAX_RW8 (64)
#define STLINKV3_MAX_RW8 (512)
@@ -92,6 +96,15 @@ enum stlink_jtag_api_version {
STLINK_JTAG_API_V3,
};
+enum stlink_mode {
+ STLINK_MODE_UNKNOWN = 0,
+ STLINK_MODE_DFU,
+ STLINK_MODE_MASS,
+ STLINK_MODE_DEBUG_JTAG,
+ STLINK_MODE_DEBUG_SWD,
+ STLINK_MODE_DEBUG_SWIM
+};
+
/** */
struct stlink_usb_version {
/** */
@@ -109,7 +122,7 @@ struct stlink_usb_version {
/** */
struct stlink_usb_handle_s {
/** */
- struct jtag_libusb_device_handle *fd;
+ struct libusb_device_handle *fd;
/** */
struct libusb_transfer *trans;
/** */
@@ -129,7 +142,7 @@ struct stlink_usb_handle_s {
/** */
uint32_t max_mem_packet;
/** */
- enum hl_transports transport;
+ enum stlink_mode st_mode;
/** */
struct stlink_usb_version version;
/** */
@@ -265,10 +278,14 @@ struct stlink_usb_handle_s {
#define STLINK_DEBUG_APIV2_GET_TRACE_NB 0x42
#define STLINK_DEBUG_APIV2_SWD_SET_FREQ 0x43
#define STLINK_DEBUG_APIV2_JTAG_SET_FREQ 0x44
-
+#define STLINK_DEBUG_APIV2_READ_DAP_REG 0x45
+#define STLINK_DEBUG_APIV2_WRITE_DAP_REG 0x46
#define STLINK_DEBUG_APIV2_READMEM_16BIT 0x47
#define STLINK_DEBUG_APIV2_WRITEMEM_16BIT 0x48
+#define STLINK_DEBUG_APIV2_INIT_AP 0x4B
+#define STLINK_DEBUG_APIV2_CLOSE_AP_DBG 0x4C
+
#define STLINK_APIV3_SET_COM_FREQ 0x61
#define STLINK_APIV3_GET_COM_FREQ 0x62
@@ -278,21 +295,13 @@ struct stlink_usb_handle_s {
#define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01
#define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02
+#define STLINK_DEBUG_PORT_ACCESS 0xffff
+
#define STLINK_TRACE_SIZE 4096
#define STLINK_TRACE_MAX_HZ 2000000
#define STLINK_V3_MAX_FREQ_NB 10
-/** */
-enum stlink_mode {
- STLINK_MODE_UNKNOWN = 0,
- STLINK_MODE_DFU,
- STLINK_MODE_MASS,
- STLINK_MODE_DEBUG_JTAG,
- STLINK_MODE_DEBUG_SWD,
- STLINK_MODE_DEBUG_SWIM
-};
-
#define REQUEST_SENSE 0x03
#define REQUEST_SENSE_LENGTH 18
@@ -300,11 +309,17 @@ enum stlink_mode {
* Map the relevant features, quirks and workaround for specific firmware
* version of stlink
*/
-#define STLINK_F_HAS_TRACE (1UL << 0)
-#define STLINK_F_HAS_SWD_SET_FREQ (1UL << 1)
-#define STLINK_F_HAS_JTAG_SET_FREQ (1UL << 2)
-#define STLINK_F_HAS_MEM_16BIT (1UL << 3)
-#define STLINK_F_HAS_GETLASTRWSTATUS2 (1UL << 4)
+#define STLINK_F_HAS_TRACE BIT(0)
+#define STLINK_F_HAS_SWD_SET_FREQ BIT(1)
+#define STLINK_F_HAS_JTAG_SET_FREQ BIT(2)
+#define STLINK_F_HAS_MEM_16BIT BIT(3)
+#define STLINK_F_HAS_GETLASTRWSTATUS2 BIT(4)
+#define STLINK_F_HAS_DAP_REG BIT(5)
+#define STLINK_F_QUIRK_JTAG_DP_READ BIT(6)
+#define STLINK_F_HAS_AP_INIT BIT(7)
+#define STLINK_F_HAS_DPBANKSEL BIT(8)
+#define STLINK_F_HAS_RW8_512BYTES BIT(9)
+#define STLINK_F_FIX_CLOSE_AP BIT(10)
/* aliases */
#define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE
@@ -332,7 +347,6 @@ static const struct speed_map stlink_khz_to_speed_map_swd[] = {
/* JTAG clock speed */
static const struct speed_map stlink_khz_to_speed_map_jtag[] = {
- {18000, 2},
{9000, 4},
{4500, 8},
{2250, 16},
@@ -347,6 +361,7 @@ static int stlink_swim_status(void *handle);
void stlink_dump_speed_map(const struct speed_map *map, unsigned int map_size);
static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map *map);
static int stlink_speed(void *handle, int khz, bool query);
+static int stlink_usb_open_ap(void *handle, unsigned short apsel);
/** */
static unsigned int stlink_usb_block(void *handle)
@@ -355,7 +370,7 @@ static unsigned int stlink_usb_block(void *handle)
assert(handle != NULL);
- if (h->version.stlink == 3)
+ if (h->version.flags & STLINK_F_HAS_RW8_512BYTES)
return STLINKV3_MAX_RW8;
else
return STLINK_MAX_RW8;
@@ -437,7 +452,8 @@ struct jtag_xfer {
struct libusb_transfer *transfer;
};
-static int jtag_libusb_bulk_transfer_n(jtag_libusb_device_handle *dev_handle,
+static int jtag_libusb_bulk_transfer_n(
+ struct libusb_device_handle *dev_handle,
struct jtag_xfer *transfers,
size_t n_transfers,
int timeout)
@@ -518,14 +534,16 @@ static int jtag_libusb_bulk_transfer_n(jtag_libusb_device_handle *dev_handle,
static int stlink_usb_xfer_v1_get_status(void *handle)
{
struct stlink_usb_handle_s *h = handle;
+ int tr, ret;
assert(handle != NULL);
/* read status */
memset(h->cmdbuf, 0, STLINK_SG_SIZE);
- if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf,
- 13, STLINK_READ_TIMEOUT) != 13)
+ ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf, 13,
+ STLINK_READ_TIMEOUT, &tr);
+ if (ret || tr != 13)
return ERROR_FAIL;
uint32_t t1;
@@ -589,23 +607,26 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int
static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int size)
{
struct stlink_usb_handle_s *h = handle;
+ int tr, ret;
assert(handle != NULL);
- if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf, cmdsize,
- STLINK_WRITE_TIMEOUT) != cmdsize) {
+ ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf,
+ cmdsize, STLINK_WRITE_TIMEOUT, &tr);
+ if (ret || tr != cmdsize)
return ERROR_FAIL;
- }
if (h->direction == h->tx_ep && size) {
- if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf,
- size, STLINK_WRITE_TIMEOUT) != size) {
+ ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf,
+ size, STLINK_WRITE_TIMEOUT, &tr);
+ if (ret || tr != size) {
LOG_DEBUG("bulk write failed");
return ERROR_FAIL;
}
} else if (h->direction == h->rx_ep && size) {
- if (jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf,
- size, STLINK_READ_TIMEOUT) != size) {
+ ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf,
+ size, STLINK_READ_TIMEOUT, &tr);
+ if (ret || tr != size) {
LOG_DEBUG("bulk read failed");
return ERROR_FAIL;
}
@@ -691,7 +712,7 @@ static int stlink_usb_error_check(void *handle)
assert(handle != NULL);
- if (h->transport == HL_TRANSPORT_SWIM) {
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
switch (h->databuf[0]) {
case STLINK_SWIM_ERR_OK:
return ERROR_OK;
@@ -800,13 +821,13 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size)
struct stlink_usb_handle_s *h = handle;
while (1) {
- if ((h->transport != HL_TRANSPORT_SWIM) || !retries) {
+ if ((h->st_mode != STLINK_MODE_DEBUG_SWIM) || !retries) {
res = stlink_usb_xfer_noerrcheck(handle, buf, size);
if (res != ERROR_OK)
return res;
}
- if (h->transport == HL_TRANSPORT_SWIM) {
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
res = stlink_swim_status(handle);
if (res != ERROR_OK)
return res;
@@ -814,7 +835,7 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size)
res = stlink_usb_error_check(handle);
if (res == ERROR_WAIT && retries < MAX_WAIT_RETRIES) {
- useconds_t delay_us = (1<<retries++) * 1000;
+ unsigned int delay_us = (1<<retries++) * 1000;
LOG_DEBUG("stlink_cmd_allow_retry ERROR_WAIT, retry %d, delaying %u microseconds", retries, delay_us);
usleep(delay_us);
continue;
@@ -827,13 +848,15 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size)
static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size)
{
struct stlink_usb_handle_s *h = handle;
+ int tr, ret;
assert(handle != NULL);
assert(h->version.flags & STLINK_F_HAS_TRACE);
- if (jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf,
- size, STLINK_READ_TIMEOUT) != size) {
+ ret = jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf, size,
+ STLINK_READ_TIMEOUT, &tr);
+ if (ret || tr != size) {
LOG_ERROR("bulk trace read failed");
return ERROR_FAIL;
}
@@ -991,13 +1014,32 @@ static int stlink_usb_version(void *handle)
flags |= STLINK_F_HAS_SWD_SET_FREQ;
/* API to set JTAG frequency from J24 */
- if (h->version.jtag >= 24)
+ /* API to access DAP registers from J24 */
+ if (h->version.jtag >= 24) {
flags |= STLINK_F_HAS_JTAG_SET_FREQ;
+ flags |= STLINK_F_HAS_DAP_REG;
+ }
+
+ /* Quirk for read DP in JTAG mode (V2 only) from J24, fixed in J32 */
+ if (h->version.jtag >= 24 && h->version.jtag < 32)
+ flags |= STLINK_F_QUIRK_JTAG_DP_READ;
/* API to read/write memory at 16 bit from J26 */
if (h->version.jtag >= 26)
flags |= STLINK_F_HAS_MEM_16BIT;
+ /* API required to init AP before any AP access from J28 */
+ if (h->version.jtag >= 28)
+ flags |= STLINK_F_HAS_AP_INIT;
+
+ /* API required to return proper error code on close AP from J29 */
+ if (h->version.jtag >= 29)
+ flags |= STLINK_F_FIX_CLOSE_AP;
+
+ /* Banked regs (DPv1 & DPv2) support from V2J32 */
+ if (h->version.jtag >= 32)
+ flags |= STLINK_F_HAS_DPBANKSEL;
+
break;
case 3:
/* all STLINK-V3 use api-v3 */
@@ -1012,9 +1054,26 @@ static int stlink_usb_version(void *handle)
/* preferred API to get last R/W status */
flags |= STLINK_F_HAS_GETLASTRWSTATUS2;
+ /* API to access DAP registers */
+ flags |= STLINK_F_HAS_DAP_REG;
+
/* API to read/write memory at 16 bit */
flags |= STLINK_F_HAS_MEM_16BIT;
+ /* API required to init AP before any AP access */
+ flags |= STLINK_F_HAS_AP_INIT;
+
+ /* API required to return proper error code on close AP */
+ flags |= STLINK_F_FIX_CLOSE_AP;
+
+ /* Banked regs (DPv1 & DPv2) support from V3J2 */
+ if (h->version.jtag >= 2)
+ flags |= STLINK_F_HAS_DPBANKSEL;
+
+ /* 8bit read/write max packet size 512 bytes from V3J6 */
+ if (h->version.jtag >= 6)
+ flags |= STLINK_F_HAS_RW8_512BYTES;
+
break;
default:
break;
@@ -1180,9 +1239,8 @@ static int stlink_usb_mode_enter(void *handle, enum stlink_mode type)
case STLINK_MODE_DEBUG_SWIM:
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER;
- /* no answer for this function... */
- rx_size = 0;
- break;
+ /* swim enter does not return any response or status */
+ return stlink_usb_xfer_noerrcheck(handle, h->databuf, 0);
case STLINK_MODE_DFU:
case STLINK_MODE_MASS:
default:
@@ -1200,7 +1258,8 @@ static int stlink_usb_mode_leave(void *handle, enum stlink_mode type)
assert(handle != NULL);
- stlink_usb_init_buffer(handle, STLINK_NULL_EP, 0);
+ /* command with no reply, use a valid endpoint but zero size */
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
switch (type) {
case STLINK_MODE_DEBUG_JTAG:
@@ -1221,7 +1280,7 @@ static int stlink_usb_mode_leave(void *handle, enum stlink_mode type)
return ERROR_FAIL;
}
- res = stlink_usb_xfer_noerrcheck(handle, 0, 0);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 0);
if (res != ERROR_OK)
return res;
@@ -1238,20 +1297,17 @@ static enum stlink_mode stlink_get_mode(enum hl_transports t)
return STLINK_MODE_DEBUG_SWD;
case HL_TRANSPORT_JTAG:
return STLINK_MODE_DEBUG_JTAG;
- case HL_TRANSPORT_SWIM:
- return STLINK_MODE_DEBUG_SWIM;
default:
return STLINK_MODE_UNKNOWN;
}
}
/** */
-static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int initial_interface_speed)
+static int stlink_usb_exit_mode(void *handle)
{
int res;
uint8_t mode;
enum stlink_mode emode;
- struct stlink_usb_handle_s *h = handle;
assert(handle != NULL);
@@ -1280,12 +1336,25 @@ static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int init
break;
}
- if (emode != STLINK_MODE_UNKNOWN) {
- res = stlink_usb_mode_leave(handle, emode);
+ if (emode != STLINK_MODE_UNKNOWN)
+ return stlink_usb_mode_leave(handle, emode);
- if (res != ERROR_OK)
- return res;
- }
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int initial_interface_speed)
+{
+ int res;
+ uint8_t mode;
+ enum stlink_mode emode;
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ res = stlink_usb_exit_mode(handle);
+ if (res != ERROR_OK)
+ return res;
res = stlink_usb_current_mode(handle, &mode);
@@ -1318,7 +1387,7 @@ static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int init
LOG_DEBUG("MODE: 0x%02X", mode);
/* set selected mode */
- emode = stlink_get_mode(h->transport);
+ emode = h->st_mode;
if (emode == STLINK_MODE_UNKNOWN) {
LOG_ERROR("selected mode (transport) not supported");
@@ -1326,12 +1395,12 @@ static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int init
}
/* set the speed before entering the mode, as the chip discovery phase should be done at this speed too */
- if (h->transport == HL_TRANSPORT_JTAG) {
+ if (emode == STLINK_MODE_DEBUG_JTAG) {
if (h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ) {
stlink_dump_speed_map(stlink_khz_to_speed_map_jtag, ARRAY_SIZE(stlink_khz_to_speed_map_jtag));
stlink_speed(h, initial_interface_speed, false);
}
- } else if (h->transport == HL_TRANSPORT_SWD) {
+ } else if (emode == STLINK_MODE_DEBUG_SWD) {
if (h->version.flags & STLINK_F_HAS_SWD_SET_FREQ) {
stlink_dump_speed_map(stlink_khz_to_speed_map_swd, ARRAY_SIZE(stlink_khz_to_speed_map_swd));
stlink_speed(h, initial_interface_speed, false);
@@ -1341,7 +1410,7 @@ static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int init
if (h->version.jtag_api == STLINK_JTAG_API_V3) {
struct speed_map map[STLINK_V3_MAX_FREQ_NB];
- stlink_get_com_freq(h, (h->transport == HL_TRANSPORT_JTAG), map);
+ stlink_get_com_freq(h, (emode == STLINK_MODE_DEBUG_JTAG), map);
stlink_dump_speed_map(map, ARRAY_SIZE(map));
stlink_speed(h, initial_interface_speed, false);
}
@@ -1582,7 +1651,7 @@ static int stlink_usb_idcode(void *handle, uint32_t *idcode)
assert(handle != NULL);
/* there is no swim read core id cmd */
- if (h->transport == HL_TRANSPORT_SWIM) {
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
*idcode = 0;
return ERROR_OK;
}
@@ -1713,22 +1782,9 @@ static enum target_state stlink_usb_state(void *handle)
assert(handle != NULL);
- if (h->transport == HL_TRANSPORT_SWIM) {
- res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport));
- if (res != ERROR_OK)
- return TARGET_UNKNOWN;
-
- res = stlink_swim_resync(handle);
- if (res != ERROR_OK)
- return TARGET_UNKNOWN;
-
- return ERROR_OK;
- }
-
if (h->reconnect_pending) {
LOG_INFO("Previous state query failed, trying to reconnect");
- res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport));
-
+ res = stlink_usb_mode_enter(handle, h->st_mode);
if (res != ERROR_OK)
return TARGET_UNKNOWN;
@@ -1768,7 +1824,7 @@ static int stlink_usb_assert_srst(void *handle, int srst)
assert(handle != NULL);
- if (h->transport == HL_TRANSPORT_SWIM)
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM)
return stlink_swim_assert_reset(handle, srst);
if (h->version.stlink == 1)
@@ -1845,9 +1901,6 @@ static int stlink_usb_reset(void *handle)
assert(handle != NULL);
- if (h->transport == HL_TRANSPORT_SWIM)
- return stlink_swim_generate_rst(handle);
-
stlink_usb_init_buffer(handle, h->rx_ep, 2);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
@@ -2269,17 +2322,12 @@ static int stlink_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
while (count) {
- bytes_remaining = (size != 1) ? \
+ bytes_remaining = (size != 1) ?
stlink_max_block_size(h->max_mem_packet, addr) : stlink_usb_block(h);
if (count < bytes_remaining)
bytes_remaining = count;
- if (h->transport == HL_TRANSPORT_SWIM) {
- retval = stlink_swim_readbytes(handle, addr, bytes_remaining, buffer);
- if (retval != ERROR_OK)
- return retval;
- } else
/*
* all stlink support 8/32bit memory read/writes and only from
* stlink V2J26 there is support for 16 bit memory read/write.
@@ -2354,17 +2402,12 @@ static int stlink_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
while (count) {
- bytes_remaining = (size != 1) ? \
+ bytes_remaining = (size != 1) ?
stlink_max_block_size(h->max_mem_packet, addr) : stlink_usb_block(h);
if (count < bytes_remaining)
bytes_remaining = count;
- if (h->transport == HL_TRANSPORT_SWIM) {
- retval = stlink_swim_writebytes(handle, addr, bytes_remaining, buffer);
- if (retval != ERROR_OK)
- return retval;
- } else
/*
* all stlink support 8/32bit memory read/writes and only from
* stlink V2J26 there is support for 16 bit memory read/write.
@@ -2430,17 +2473,20 @@ static int stlink_usb_override_target(const char *targetname)
static int stlink_speed_swim(void *handle, int khz, bool query)
{
+ int retval;
+
/*
- we dont care what the khz rate is
we only have low and high speed...
before changing speed the SWIM_CSR HS bit
must be updated
*/
- if (khz == 0)
- stlink_swim_speed(handle, 0);
- else
- stlink_swim_speed(handle, 1);
- return khz;
+ if (!query) {
+ retval = stlink_swim_speed(handle, (khz < SWIM_FREQ_HIGH) ? 0 : 1);
+ if (retval != ERROR_OK)
+ LOG_ERROR("Unable to set adapter speed");
+ }
+
+ return (khz < SWIM_FREQ_HIGH) ? SWIM_FREQ_LOW : SWIM_FREQ_HIGH;
}
static int stlink_match_speed_map(const struct speed_map *map, unsigned int map_size, int khz, bool query)
@@ -2478,7 +2524,7 @@ static int stlink_match_speed_map(const struct speed_map *map, unsigned int map_
match = false;
if (!match && query) {
- LOG_INFO("Unable to match requested speed %d kHz, using %d kHz", \
+ LOG_INFO("Unable to match requested speed %d kHz, using %d kHz",
khz, map[speed_index].speed);
}
@@ -2624,17 +2670,16 @@ static int stlink_speed(void *handle, int khz, bool query)
if (!handle)
return khz;
- switch (h->transport) {
- case HL_TRANSPORT_SWIM:
+ switch (h->st_mode) {
+ case STLINK_MODE_DEBUG_SWIM:
return stlink_speed_swim(handle, khz, query);
- break;
- case HL_TRANSPORT_SWD:
+ case STLINK_MODE_DEBUG_SWD:
if (h->version.jtag_api == STLINK_JTAG_API_V3)
return stlink_speed_v3(handle, false, khz, query);
else
return stlink_speed_swd(handle, khz, query);
break;
- case HL_TRANSPORT_JTAG:
+ case STLINK_MODE_DEBUG_JTAG:
if (h->version.jtag_api == STLINK_JTAG_API_V3)
return stlink_speed_v3(handle, true, khz, query);
else
@@ -2650,53 +2695,101 @@ static int stlink_speed(void *handle, int khz, bool query)
/** */
static int stlink_usb_close(void *handle)
{
- int res;
- uint8_t mode;
- enum stlink_mode emode;
struct stlink_usb_handle_s *h = handle;
- if (h && h->fd)
- res = stlink_usb_current_mode(handle, &mode);
- else
- res = ERROR_FAIL;
- /* do not exit if return code != ERROR_OK,
- it prevents us from closing jtag_libusb */
-
- if (res == ERROR_OK) {
- /* try to exit current mode */
- switch (mode) {
- case STLINK_DEV_DFU_MODE:
- emode = STLINK_MODE_DFU;
- break;
- case STLINK_DEV_DEBUG_MODE:
- emode = STLINK_MODE_DEBUG_SWD;
- break;
- case STLINK_DEV_SWIM_MODE:
- emode = STLINK_MODE_DEBUG_SWIM;
- break;
- case STLINK_DEV_BOOTLOADER_MODE:
- case STLINK_DEV_MASS_MODE:
- default:
- emode = STLINK_MODE_UNKNOWN;
- break;
- }
-
- if (emode != STLINK_MODE_UNKNOWN)
- stlink_usb_mode_leave(handle, emode);
- /* do not check return code, it prevent
- us from closing jtag_libusb */
- }
-
- if (h && h->fd)
+ if (h && h->fd) {
+ stlink_usb_exit_mode(h);
+ /* do not check return code, it prevent
+ us from closing jtag_libusb */
jtag_libusb_close(h->fd);
+ }
free(h);
return ERROR_OK;
}
+/* Compute ST-Link serial number from the device descriptor
+ * this function will help to work-around a bug in old ST-Link/V2 DFU
+ * the buggy DFU returns an incorrect serial in the USB descriptor
+ * example for the following serial "57FF72067265575742132067"
+ * - the correct descriptor serial is:
+ * 0x32, 0x03, 0x35, 0x00, 0x37, 0x00, 0x46, 0x00, 0x46, 0x00, 0x37, 0x00, 0x32, 0x00 ...
+ * this contains the length (0x32 = 50), the type (0x3 = DT_STRING) and the serial in unicode format
+ * the serial part is: 0x0035, 0x0037, 0x0046, 0x0046, 0x0037, 0x0032 ... >> 57FF72 ...
+ * this format could be read correctly by 'libusb_get_string_descriptor_ascii'
+ * so this case is managed by libusb_helper::string_descriptor_equal
+ * - the buggy DFU is not doing any unicode conversion and returns a raw serial data in the descriptor
+ * 0x1a, 0x03, 0x57, 0x00, 0xFF, 0x00, 0x72, 0x00 ...
+ * >> 57 FF 72 ...
+ * based on the length (0x1a = 26) we could easily decide if we have to fixup the serial
+ * and then we have just to convert the raw data into printable characters using sprintf
+ */
+char *stlink_usb_get_alternate_serial(libusb_device_handle *device,
+ struct libusb_device_descriptor *dev_desc)
+{
+ int usb_retval;
+ unsigned char desc_serial[(STLINK_SERIAL_LEN + 1) * 2];
+
+ if (dev_desc->iSerialNumber == 0)
+ return NULL;
+
+ /* get the LANGID from String Descriptor Zero */
+ usb_retval = libusb_get_string_descriptor(device, 0, 0, desc_serial,
+ sizeof(desc_serial));
+
+ if (usb_retval < LIBUSB_SUCCESS) {
+ LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
+ libusb_error_name(usb_retval), usb_retval);
+ return NULL;
+ } else if (usb_retval < 4) {
+ /* the size should be least 4 bytes to contain a minimum of 1 supported LANGID */
+ LOG_ERROR("could not get the LANGID");
+ return NULL;
+ }
+
+ uint32_t langid = desc_serial[2] | (desc_serial[3] << 8);
+
+ /* get the serial */
+ usb_retval = libusb_get_string_descriptor(device, dev_desc->iSerialNumber,
+ langid, desc_serial, sizeof(desc_serial));
+
+ unsigned char len = desc_serial[0];
+
+ if (usb_retval < LIBUSB_SUCCESS) {
+ LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)",
+ libusb_error_name(usb_retval), usb_retval);
+ return NULL;
+ } else if (desc_serial[1] != LIBUSB_DT_STRING || len > usb_retval) {
+ LOG_ERROR("invalid string in ST-LINK USB serial descriptor");
+ return NULL;
+ }
+
+ if (len == ((STLINK_SERIAL_LEN + 1) * 2)) {
+ /* good ST-Link adapter, this case is managed by
+ * libusb::libusb_get_string_descriptor_ascii */
+ return NULL;
+ } else if (len != ((STLINK_SERIAL_LEN / 2 + 1) * 2)) {
+ LOG_ERROR("unexpected serial length (%d) in descriptor", len);
+ return NULL;
+ }
+
+ /* else (len == 26) => buggy ST-Link */
+
+ char *alternate_serial = malloc((STLINK_SERIAL_LEN + 1) * sizeof(char));
+ if (alternate_serial == NULL)
+ return NULL;
+
+ for (unsigned int i = 0; i < STLINK_SERIAL_LEN; i += 2)
+ sprintf(alternate_serial + i, "%02X", desc_serial[i + 2]);
+
+ alternate_serial[STLINK_SERIAL_LEN] = '\0';
+
+ return alternate_serial;
+}
+
/** */
-static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
+static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode mode, void **fd)
{
int err, retry_count = 1;
struct stlink_usb_handle_s *h;
@@ -2710,11 +2803,11 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
return ERROR_FAIL;
}
- h->transport = param->transport;
+ h->st_mode = mode;
for (unsigned i = 0; param->vid[i]; i++) {
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
- param->transport, param->vid[i], param->pid[i],
+ h->st_mode, param->vid[i], param->pid[i],
param->serial ? param->serial : "");
}
@@ -2728,14 +2821,15 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
in order to become operational.
*/
do {
- if (jtag_libusb_open(param->vid, param->pid, param->serial, &h->fd) != ERROR_OK) {
+ if (jtag_libusb_open(param->vid, param->pid, param->serial,
+ &h->fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
LOG_ERROR("open failed");
goto error_open;
}
jtag_libusb_set_configuration(h->fd, 0);
- if (jtag_libusb_claim_interface(h->fd, 0) != ERROR_OK) {
+ if (libusb_claim_interface(h->fd, 0) != ERROR_OK) {
LOG_DEBUG("claim interface failed");
goto error_open;
}
@@ -2744,7 +2838,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
h->rx_ep = STLINK_RX_EP;
uint16_t pid;
- if (jtag_libusb_get_pid(jtag_libusb_get_device(h->fd), &pid) != ERROR_OK) {
+ if (jtag_libusb_get_pid(libusb_get_device(h->fd), &pid) != ERROR_OK) {
LOG_DEBUG("libusb_get_pid failed");
goto error_open;
}
@@ -2788,13 +2882,13 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
LOG_ERROR("read version failed");
goto error_open;
} else {
- err = jtag_libusb_release_interface(h->fd, 0);
+ err = libusb_release_interface(h->fd, 0);
if (err != ERROR_OK) {
LOG_ERROR("release interface failed");
goto error_open;
}
- err = jtag_libusb_reset_device(h->fd);
+ err = libusb_reset_device(h->fd);
if (err != ERROR_OK) {
LOG_ERROR("reset device failed");
goto error_open;
@@ -2813,16 +2907,16 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
/* check if mode is supported */
err = ERROR_OK;
- switch (h->transport) {
- case HL_TRANSPORT_SWD:
+ switch (h->st_mode) {
+ case STLINK_MODE_DEBUG_SWD:
if (h->version.jtag_api == STLINK_JTAG_API_V1)
err = ERROR_FAIL;
/* fall-through */
- case HL_TRANSPORT_JTAG:
+ case STLINK_MODE_DEBUG_JTAG:
if (h->version.jtag == 0)
err = ERROR_FAIL;
break;
- case HL_TRANSPORT_SWIM:
+ case STLINK_MODE_DEBUG_SWIM:
if (h->version.swim == 0)
err = ERROR_FAIL;
break;
@@ -2844,7 +2938,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
goto error_open;
}
- if (h->transport == HL_TRANSPORT_SWIM) {
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
err = stlink_swim_enter(h);
if (err != ERROR_OK) {
LOG_ERROR("stlink_swim_enter_failed (unable to connect to the target)");
@@ -2860,6 +2954,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
h->max_mem_packet = (1 << 10);
uint8_t buffer[4];
+ stlink_usb_open_ap(h, 0);
err = stlink_usb_read_mem32(h, CPUID, 4, buffer);
if (err == ERROR_OK) {
uint32_t cpuid = le_to_h_u32(buffer);
@@ -2882,10 +2977,18 @@ error_open:
return ERROR_FAIL;
}
-int stlink_config_trace(void *handle, bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
+static int stlink_usb_hl_open(struct hl_interface_param_s *param, void **fd)
+{
+ return stlink_usb_open(param, stlink_get_mode(param->transport), fd);
+}
+
+int stlink_config_trace(void *handle, bool enabled,
+ enum tpiu_pin_protocol pin_protocol, uint32_t port_size,
+ unsigned int *trace_freq, unsigned int traceclkin_freq,
+ uint16_t *prescaler)
{
struct stlink_usb_handle_s *h = handle;
+ uint16_t presc;
if (enabled && (!(h->version.flags & STLINK_F_HAS_TRACE) ||
pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART)) {
@@ -2908,15 +3011,116 @@ int stlink_config_trace(void *handle, bool enabled, enum tpiu_pin_protocol pin_p
if (!*trace_freq)
*trace_freq = STLINK_TRACE_MAX_HZ;
+
+ presc = traceclkin_freq / *trace_freq;
+
+ if (traceclkin_freq % *trace_freq > 0)
+ presc++;
+
+ if (presc > TPIU_ACPR_MAX_SWOSCALER) {
+ LOG_ERROR("SWO frequency is not suitable. Please choose a different "
+ "frequency.");
+ return ERROR_FAIL;
+ }
+
+ *prescaler = presc;
h->trace.source_hz = *trace_freq;
return stlink_usb_trace_enable(h);
}
/** */
+static int stlink_usb_init_access_port(void *handle, unsigned char ap_num)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (!(h->version.flags & STLINK_F_HAS_AP_INIT))
+ return ERROR_COMMAND_NOTFOUND;
+
+ LOG_DEBUG_IO("init ap_num = %d", ap_num);
+ stlink_usb_init_buffer(handle, h->rx_ep, 16);
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_INIT_AP;
+ h->cmdbuf[h->cmdidx++] = ap_num;
+
+ return stlink_usb_xfer_errcheck(handle, h->databuf, 2);
+}
+
+/** */
+static int stlink_usb_close_access_port(void *handle, unsigned char ap_num)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (!(h->version.flags & STLINK_F_HAS_AP_INIT))
+ return ERROR_COMMAND_NOTFOUND;
+
+ LOG_DEBUG_IO("close ap_num = %d", ap_num);
+ stlink_usb_init_buffer(handle, h->rx_ep, 16);
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_CLOSE_AP_DBG;
+ h->cmdbuf[h->cmdidx++] = ap_num;
+
+ /* ignore incorrectly returned error on bogus FW */
+ if (h->version.flags & STLINK_F_FIX_CLOSE_AP)
+ return stlink_usb_xfer_errcheck(handle, h->databuf, 2);
+ else
+ return stlink_usb_xfer_noerrcheck(handle, h->databuf, 2);
+
+}
+
+/** */
+static int stlink_read_dap_register(void *handle, unsigned short dap_port,
+ unsigned short addr, uint32_t *val)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int retval;
+
+ assert(handle != NULL);
+
+ if (!(h->version.flags & STLINK_F_HAS_DAP_REG))
+ return ERROR_COMMAND_NOTFOUND;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 16);
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READ_DAP_REG;
+ h_u16_to_le(&h->cmdbuf[2], dap_port);
+ h_u16_to_le(&h->cmdbuf[4], addr);
+
+ retval = stlink_usb_xfer_errcheck(handle, h->databuf, 8);
+ *val = le_to_h_u32(h->databuf + 4);
+ LOG_DEBUG_IO("dap_port_read = %d, addr = 0x%x, value = 0x%x", dap_port, addr, *val);
+ return retval;
+}
+
+/** */
+static int stlink_write_dap_register(void *handle, unsigned short dap_port,
+ unsigned short addr, uint32_t val)
+{
+ struct stlink_usb_handle_s *h = handle;
+
+ assert(handle != NULL);
+
+ if (!(h->version.flags & STLINK_F_HAS_DAP_REG))
+ return ERROR_COMMAND_NOTFOUND;
+
+ LOG_DEBUG_IO("dap_write port = %d, addr = 0x%x, value = 0x%x", dap_port, addr, val);
+ stlink_usb_init_buffer(handle, h->rx_ep, 16);
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITE_DAP_REG;
+ h_u16_to_le(&h->cmdbuf[2], dap_port);
+ h_u16_to_le(&h->cmdbuf[4], addr);
+ h_u32_to_le(&h->cmdbuf[6], val);
+ return stlink_usb_xfer_errcheck(handle, h->databuf, 2);
+}
+
+/** */
struct hl_layout_api_s stlink_usb_layout_api = {
/** */
- .open = stlink_usb_open,
+ .open = stlink_usb_hl_open,
/** */
.close = stlink_usb_close,
/** */
@@ -2954,3 +3158,648 @@ struct hl_layout_api_s stlink_usb_layout_api = {
/** */
.poll_trace = stlink_usb_trace_read,
};
+
+/*****************************************************************************
+ * DAP direct interface
+ */
+
+static struct stlink_usb_handle_s *stlink_dap_handle;
+static struct hl_interface_param_s stlink_dap_param;
+static DECLARE_BITMAP(opened_ap, DP_APSEL_MAX + 1);
+static int stlink_dap_error = ERROR_OK;
+
+static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
+ uint32_t *data);
+
+/** */
+static int stlink_dap_record_error(int error)
+{
+ if (stlink_dap_error == ERROR_OK)
+ stlink_dap_error = error;
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_get_and_clear_error(void)
+{
+ int retval = stlink_dap_error;
+ stlink_dap_error = ERROR_OK;
+ return retval;
+}
+
+static int stlink_usb_open_ap(void *handle, unsigned short apsel)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int retval;
+
+ /* nothing to do on old versions */
+ if (!(h->version.flags & STLINK_F_HAS_AP_INIT))
+ return ERROR_OK;
+
+ if (apsel > DP_APSEL_MAX)
+ return ERROR_FAIL;
+
+ if (test_bit(apsel, opened_ap))
+ return ERROR_OK;
+
+ retval = stlink_usb_init_access_port(h, apsel);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("AP %d enabled", apsel);
+ set_bit(apsel, opened_ap);
+ return ERROR_OK;
+}
+
+static int stlink_dap_open_ap(unsigned short apsel)
+{
+ return stlink_usb_open_ap(stlink_dap_handle, apsel);
+}
+
+/** */
+static int stlink_dap_closeall_ap(void)
+{
+ int retval, apsel;
+
+ /* nothing to do on old versions */
+ if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_AP_INIT))
+ return ERROR_OK;
+
+ for (apsel = 0; apsel <= DP_APSEL_MAX; apsel++) {
+ if (!test_bit(apsel, opened_ap))
+ continue;
+ retval = stlink_usb_close_access_port(stlink_dap_handle, apsel);
+ if (retval != ERROR_OK)
+ return retval;
+ clear_bit(apsel, opened_ap);
+ }
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_reinit_interface(void)
+{
+ int retval;
+
+ /*
+ * On JTAG only, it should be enough to call stlink_usb_reset(). But on
+ * some firmware version it does not work as expected, and there is no
+ * equivalent for SWD.
+ * At least for now, to reset the interface quit from JTAG/SWD mode then
+ * select the mode again.
+ */
+
+ if (!stlink_dap_handle->reconnect_pending) {
+ stlink_dap_handle->reconnect_pending = true;
+ stlink_usb_mode_leave(stlink_dap_handle, stlink_dap_handle->st_mode);
+ }
+
+ retval = stlink_usb_mode_enter(stlink_dap_handle, stlink_dap_handle->st_mode);
+ if (retval != ERROR_OK)
+ return retval;
+
+ stlink_dap_handle->reconnect_pending = false;
+ /* on new FW, calling mode-leave closes all the opened AP; reopen them! */
+ if (stlink_dap_handle->version.flags & STLINK_F_HAS_AP_INIT)
+ for (int apsel = 0; apsel <= DP_APSEL_MAX; apsel++)
+ if (test_bit(apsel, opened_ap)) {
+ clear_bit(apsel, opened_ap);
+ stlink_dap_open_ap(apsel);
+ }
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_op_connect(struct adiv5_dap *dap)
+{
+ uint32_t idcode;
+ int retval;
+
+ LOG_INFO("stlink_dap_op_connect(%sconnect)", dap->do_reconnect ? "re" : "");
+
+ /* Check if we should reset srst already when connecting, but not if reconnecting. */
+ if (!dap->do_reconnect) {
+ enum reset_types jtag_reset_config = jtag_get_reset_config();
+
+ if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
+ if (jtag_reset_config & RESET_SRST_NO_GATING)
+ adapter_assert_reset();
+ else
+ LOG_WARNING("\'srst_nogate\' reset_config option is required");
+ }
+ }
+
+ dap->do_reconnect = false;
+ dap_invalidate_cache(dap);
+
+ retval = dap_dp_init(dap);
+ if (retval != ERROR_OK) {
+ dap->do_reconnect = true;
+ return retval;
+ }
+
+ retval = stlink_usb_idcode(stlink_dap_handle, &idcode);
+ if (retval == ERROR_OK)
+ LOG_INFO("%s %#8.8" PRIx32,
+ (stlink_dap_handle->st_mode == STLINK_MODE_DEBUG_JTAG) ? "JTAG IDCODE" : "SWD DPIDR",
+ idcode);
+ else
+ dap->do_reconnect = true;
+
+ return retval;
+}
+
+/** */
+static int stlink_dap_check_reconnect(struct adiv5_dap *dap)
+{
+ int retval;
+
+ if (!dap->do_reconnect)
+ return ERROR_OK;
+
+ retval = stlink_dap_reinit_interface();
+ if (retval != ERROR_OK)
+ return retval;
+
+ return stlink_dap_op_connect(dap);
+}
+
+/** */
+static int stlink_dap_op_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq)
+{
+ /* Ignore the request */
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
+ uint32_t *data)
+{
+ uint32_t dummy;
+ int retval;
+
+ if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_DPBANKSEL))
+ if (reg & 0x000000F0) {
+ LOG_ERROR("Banked DP registers not supported in current STLink FW");
+ return ERROR_COMMAND_NOTFOUND;
+ }
+
+ retval = stlink_dap_check_reconnect(dap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ data = data ? : &dummy;
+ if (stlink_dap_handle->version.flags & STLINK_F_QUIRK_JTAG_DP_READ
+ && stlink_dap_handle->st_mode == STLINK_MODE_DEBUG_JTAG) {
+ /* Quirk required in JTAG. Read RDBUFF to get the data */
+ retval = stlink_read_dap_register(stlink_dap_handle,
+ STLINK_DEBUG_PORT_ACCESS, reg, &dummy);
+ if (retval == ERROR_OK)
+ retval = stlink_read_dap_register(stlink_dap_handle,
+ STLINK_DEBUG_PORT_ACCESS, DP_RDBUFF, data);
+ } else {
+ retval = stlink_read_dap_register(stlink_dap_handle,
+ STLINK_DEBUG_PORT_ACCESS, reg, data);
+ }
+
+ return stlink_dap_record_error(retval);
+}
+
+/** */
+static int stlink_dap_op_queue_dp_write(struct adiv5_dap *dap, unsigned reg,
+ uint32_t data)
+{
+ int retval;
+
+ if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_DPBANKSEL))
+ if (reg & 0x000000F0) {
+ LOG_ERROR("Banked DP registers not supported in current STLink FW");
+ return ERROR_COMMAND_NOTFOUND;
+ }
+
+ if (reg == DP_SELECT && (data & DP_SELECT_DPBANK) != 0) {
+ /* ignored if STLINK_F_HAS_DPBANKSEL, not properly managed otherwise */
+ LOG_DEBUG("Ignoring DPBANKSEL while write SELECT");
+ data &= ~DP_SELECT_DPBANK;
+ }
+
+ retval = stlink_dap_check_reconnect(dap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* ST-Link does not like that we set CORUNDETECT */
+ if (reg == DP_CTRL_STAT)
+ data &= ~CORUNDETECT;
+
+ retval = stlink_write_dap_register(stlink_dap_handle,
+ STLINK_DEBUG_PORT_ACCESS, reg, data);
+ return stlink_dap_record_error(retval);
+}
+
+/** */
+static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
+ uint32_t *data)
+{
+ struct adiv5_dap *dap = ap->dap;
+ uint32_t dummy;
+ int retval;
+
+ retval = stlink_dap_check_reconnect(dap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (reg != AP_REG_IDR) {
+ retval = stlink_dap_open_ap(ap->ap_num);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ data = data ? : &dummy;
+ retval = stlink_read_dap_register(stlink_dap_handle, ap->ap_num, reg,
+ data);
+ dap->stlink_flush_ap_write = false;
+ return stlink_dap_record_error(retval);
+}
+
+/** */
+static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned reg,
+ uint32_t data)
+{
+ struct adiv5_dap *dap = ap->dap;
+ int retval;
+
+ retval = stlink_dap_check_reconnect(dap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = stlink_dap_open_ap(ap->ap_num);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = stlink_write_dap_register(stlink_dap_handle, ap->ap_num, reg,
+ data);
+ dap->stlink_flush_ap_write = true;
+ return stlink_dap_record_error(retval);
+}
+
+/** */
+static int stlink_dap_op_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
+{
+ LOG_WARNING("stlink_dap_op_queue_ap_abort()");
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_op_run(struct adiv5_dap *dap)
+{
+ uint32_t ctrlstat, pwrmask;
+ int retval, saved_retval;
+
+ /* Here no LOG_DEBUG. This is called continuously! */
+
+ /*
+ * ST-Link returns immediately after a DAP write, without waiting for it
+ * to complete.
+ * Run a dummy read to DP_RDBUFF, as suggested in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka16363.html
+ */
+ if (dap->stlink_flush_ap_write) {
+ dap->stlink_flush_ap_write = false;
+ retval = stlink_dap_op_queue_dp_read(dap, DP_RDBUFF, NULL);
+ if (retval != ERROR_OK) {
+ dap->do_reconnect = true;
+ return retval;
+ }
+ }
+
+ saved_retval = stlink_dap_get_and_clear_error();
+
+ retval = stlink_dap_op_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
+ if (retval != ERROR_OK) {
+ dap->do_reconnect = true;
+ return retval;
+ }
+ retval = stlink_dap_get_and_clear_error();
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Fail reading CTRL/STAT register. Force reconnect");
+ dap->do_reconnect = true;
+ return retval;
+ }
+
+ if (ctrlstat & SSTICKYERR) {
+ if (stlink_dap_handle->st_mode == STLINK_MODE_DEBUG_JTAG)
+ retval = stlink_dap_op_queue_dp_write(dap, DP_CTRL_STAT,
+ ctrlstat & (dap->dp_ctrl_stat | SSTICKYERR));
+ else
+ retval = stlink_dap_op_queue_dp_write(dap, DP_ABORT, STKERRCLR);
+ if (retval != ERROR_OK) {
+ dap->do_reconnect = true;
+ return retval;
+ }
+ retval = stlink_dap_get_and_clear_error();
+ if (retval != ERROR_OK) {
+ dap->do_reconnect = true;
+ return retval;
+ }
+ }
+
+ /* check for power lost */
+ pwrmask = dap->dp_ctrl_stat & (CDBGPWRUPREQ | CSYSPWRUPREQ);
+ if ((ctrlstat & pwrmask) != pwrmask)
+ dap->do_reconnect = true;
+
+ return saved_retval;
+}
+
+/** */
+static void stlink_dap_op_quit(struct adiv5_dap *dap)
+{
+ int retval;
+
+ retval = stlink_dap_closeall_ap();
+ if (retval != ERROR_OK)
+ LOG_ERROR("Error closing APs");
+}
+
+static int stlink_swim_op_srst(void)
+{
+ return stlink_swim_generate_rst(stlink_dap_handle);
+}
+
+static int stlink_swim_op_read_mem(uint32_t addr, uint32_t size,
+ uint32_t count, uint8_t *buffer)
+{
+ int retval;
+ uint32_t bytes_remaining;
+
+ LOG_DEBUG_IO("read at 0x%08x len %d*0x%08x", addr, size, count);
+ count *= size;
+
+ while (count) {
+ bytes_remaining = (count > STLINK_DATA_SIZE) ? STLINK_DATA_SIZE : count;
+ retval = stlink_swim_readbytes(stlink_dap_handle, addr, bytes_remaining, buffer);
+ if (retval != ERROR_OK)
+ return retval;
+
+ buffer += bytes_remaining;
+ addr += bytes_remaining;
+ count -= bytes_remaining;
+ }
+
+ return ERROR_OK;
+}
+
+static int stlink_swim_op_write_mem(uint32_t addr, uint32_t size,
+ uint32_t count, const uint8_t *buffer)
+{
+ int retval;
+ uint32_t bytes_remaining;
+
+ LOG_DEBUG_IO("write at 0x%08x len %d*0x%08x", addr, size, count);
+ count *= size;
+
+ while (count) {
+ bytes_remaining = (count > STLINK_DATA_SIZE) ? STLINK_DATA_SIZE : count;
+ retval = stlink_swim_writebytes(stlink_dap_handle, addr, bytes_remaining, buffer);
+ if (retval != ERROR_OK)
+ return retval;
+
+ buffer += bytes_remaining;
+ addr += bytes_remaining;
+ count -= bytes_remaining;
+ }
+
+ return ERROR_OK;
+}
+
+static int stlink_swim_op_reconnect(void)
+{
+ int retval;
+
+ retval = stlink_usb_mode_enter(stlink_dap_handle, STLINK_MODE_DEBUG_SWIM);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return stlink_swim_resync(stlink_dap_handle);
+}
+
+static int stlink_dap_config_trace(bool enabled,
+ enum tpiu_pin_protocol pin_protocol, uint32_t port_size,
+ unsigned int *trace_freq, unsigned int traceclkin_freq,
+ uint16_t *prescaler)
+{
+ return stlink_config_trace(stlink_dap_handle, enabled, pin_protocol,
+ port_size, trace_freq, traceclkin_freq,
+ prescaler);
+}
+
+static int stlink_dap_trace_read(uint8_t *buf, size_t *size)
+{
+ return stlink_usb_trace_read(stlink_dap_handle, buf, size);
+}
+
+/** */
+COMMAND_HANDLER(stlink_dap_serial_command)
+{
+ LOG_DEBUG("stlink_dap_serial_command");
+
+ if (CMD_ARGC != 1) {
+ LOG_ERROR("Expected exactly one argument for \"st-link serial <serial-number>\".");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ if (stlink_dap_param.serial) {
+ LOG_WARNING("Command \"st-link serial\" already used. Replacing previous value");
+ free((void *)stlink_dap_param.serial);
+ }
+
+ stlink_dap_param.serial = strdup(CMD_ARGV[0]);
+ return ERROR_OK;
+}
+
+/** */
+COMMAND_HANDLER(stlink_dap_vid_pid)
+{
+ unsigned int i, max_usb_ids = HLA_MAX_USB_IDS;
+
+ if (CMD_ARGC > max_usb_ids * 2) {
+ LOG_WARNING("ignoring extra IDs in vid_pid "
+ "(maximum is %d pairs)", max_usb_ids);
+ CMD_ARGC = max_usb_ids * 2;
+ }
+ if (CMD_ARGC < 2 || (CMD_ARGC & 1)) {
+ LOG_WARNING("incomplete vid_pid configuration directive");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+ for (i = 0; i < CMD_ARGC; i += 2) {
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], stlink_dap_param.vid[i / 2]);
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], stlink_dap_param.pid[i / 2]);
+ }
+
+ /* null termination */
+ stlink_dap_param.vid[i / 2] = stlink_dap_param.pid[i / 2] = 0;
+
+ return ERROR_OK;
+}
+
+/** */
+static const struct command_registration stlink_dap_subcommand_handlers[] = {
+ {
+ .name = "serial",
+ .handler = stlink_dap_serial_command,
+ .mode = COMMAND_CONFIG,
+ .help = "set the serial number of the adapter",
+ .usage = "<serial_number>",
+ },
+ {
+ .name = "vid_pid",
+ .handler = stlink_dap_vid_pid,
+ .mode = COMMAND_CONFIG,
+ .help = "USB VID and PID of the adapter",
+ .usage = "(vid pid)+",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+/** */
+static const struct command_registration stlink_dap_command_handlers[] = {
+ {
+ .name = "st-link",
+ .mode = COMMAND_ANY,
+ .help = "perform st-link management",
+ .chain = stlink_dap_subcommand_handlers,
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+/** */
+static int stlink_dap_init(void)
+{
+ enum reset_types jtag_reset_config = jtag_get_reset_config();
+ enum stlink_mode mode;
+ int retval;
+
+ LOG_DEBUG("stlink_dap_init()");
+
+ if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
+ if (jtag_reset_config & RESET_SRST_NO_GATING)
+ stlink_dap_param.connect_under_reset = true;
+ else
+ LOG_WARNING("\'srst_nogate\' reset_config option is required");
+ }
+
+ if (transport_is_dapdirect_swd())
+ mode = STLINK_MODE_DEBUG_SWD;
+ else if (transport_is_dapdirect_jtag())
+ mode = STLINK_MODE_DEBUG_JTAG;
+ else if (transport_is_swim())
+ mode = STLINK_MODE_DEBUG_SWIM;
+ else {
+ LOG_ERROR("Unsupported transport");
+ return ERROR_FAIL;
+ }
+
+ retval = stlink_usb_open(&stlink_dap_param, mode, (void **)&stlink_dap_handle);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if ((mode != STLINK_MODE_DEBUG_SWIM) &&
+ !(stlink_dap_handle->version.flags & STLINK_F_HAS_DAP_REG)) {
+ LOG_ERROR("ST-Link version does not support DAP direct transport");
+ return ERROR_FAIL;
+ }
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_quit(void)
+{
+ LOG_DEBUG("stlink_dap_quit()");
+
+ free((void *)stlink_dap_param.serial);
+ stlink_dap_param.serial = NULL;
+
+ return stlink_usb_close(stlink_dap_handle);
+}
+
+/** */
+static int stlink_dap_reset(int req_trst, int req_srst)
+{
+ LOG_DEBUG("stlink_dap_reset(%d)", req_srst);
+ return stlink_usb_assert_srst(stlink_dap_handle,
+ req_srst ? STLINK_DEBUG_APIV2_DRIVE_NRST_LOW
+ : STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH);
+}
+
+/** */
+static int stlink_dap_speed(int speed)
+{
+ if (speed == 0) {
+ LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
+ return ERROR_JTAG_NOT_IMPLEMENTED;
+ }
+
+ stlink_dap_param.initial_interface_speed = speed;
+ stlink_speed(stlink_dap_handle, speed, false);
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_khz(int khz, int *jtag_speed)
+{
+ if (khz == 0) {
+ LOG_ERROR("RCLK not supported");
+ return ERROR_FAIL;
+ }
+
+ *jtag_speed = stlink_speed(stlink_dap_handle, khz, true);
+ return ERROR_OK;
+}
+
+/** */
+static int stlink_dap_speed_div(int speed, int *khz)
+{
+ *khz = speed;
+ return ERROR_OK;
+}
+
+static const struct dap_ops stlink_dap_ops = {
+ .connect = stlink_dap_op_connect,
+ .send_sequence = stlink_dap_op_send_sequence,
+ .queue_dp_read = stlink_dap_op_queue_dp_read,
+ .queue_dp_write = stlink_dap_op_queue_dp_write,
+ .queue_ap_read = stlink_dap_op_queue_ap_read,
+ .queue_ap_write = stlink_dap_op_queue_ap_write,
+ .queue_ap_abort = stlink_dap_op_queue_ap_abort,
+ .run = stlink_dap_op_run,
+ .sync = NULL, /* optional */
+ .quit = stlink_dap_op_quit, /* optional */
+};
+
+static const struct swim_driver stlink_swim_ops = {
+ .srst = stlink_swim_op_srst,
+ .read_mem = stlink_swim_op_read_mem,
+ .write_mem = stlink_swim_op_write_mem,
+ .reconnect = stlink_swim_op_reconnect,
+};
+
+static const char *const stlink_dap_transport[] = { "dapdirect_swd", "dapdirect_jtag", "swim", NULL };
+
+struct adapter_driver stlink_dap_adapter_driver = {
+ .name = "st-link",
+ .transports = stlink_dap_transport,
+ .commands = stlink_dap_command_handlers,
+
+ .init = stlink_dap_init,
+ .quit = stlink_dap_quit,
+ .reset = stlink_dap_reset,
+ .speed = stlink_dap_speed,
+ .khz = stlink_dap_khz,
+ .speed_div = stlink_dap_speed_div,
+ .config_trace = stlink_dap_config_trace,
+ .poll_trace = stlink_dap_trace_read,
+
+ .dap_jtag_ops = &stlink_dap_ops,
+ .dap_swd_ops = &stlink_dap_ops,
+ .swim_ops = &stlink_swim_ops,
+};
diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c
index eb4941e..a4d7ad9 100644
--- a/src/jtag/drivers/sysfsgpio.c
+++ b/src/jtag/drivers/sysfsgpio.c
@@ -52,6 +52,7 @@
#include "config.h"
#endif
+#include <helper/time_support.h>
#include <jtag/interface.h>
#include "bitbang.h"
@@ -60,7 +61,7 @@
*
* Assume here that there will be less than 10000 gpios on a system
*/
-static int is_gpio_valid(int gpio)
+static bool is_gpio_valid(int gpio)
{
return gpio >= 0 && gpio < 10000;
}
@@ -97,8 +98,6 @@ static void unexport_sysfs_gpio(int gpio)
snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0)
LOG_ERROR("Couldn't unexport gpio %d", gpio);
-
- return;
}
/*
@@ -112,6 +111,7 @@ static void unexport_sysfs_gpio(int gpio)
*/
static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
{
+ struct timeval timeout, now;
char buf[40];
char gpiostr[5];
int ret;
@@ -131,8 +131,19 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
}
}
+ gettimeofday(&timeout, NULL);
+ timeval_add_time(&timeout, 0, 500000);
+
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
- ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
+ for (;;) {
+ ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
+ if (ret >= 0 || errno != EACCES)
+ break;
+ gettimeofday(&now, NULL);
+ if (timeval_compare(&now, &timeout) >= 0)
+ break;
+ jtag_sleep(10000);
+ }
if (ret < 0) {
LOG_ERROR("Couldn't set direction for gpio %d", gpio);
perror("sysfsgpio: ");
@@ -141,7 +152,15 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
}
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
- ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
+ for (;;) {
+ ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
+ if (ret >= 0 || errno != EACCES)
+ break;
+ gettimeofday(&now, NULL);
+ if (timeval_compare(&now, &timeout) >= 0)
+ break;
+ jtag_sleep(10000);
+ }
if (ret < 0) {
LOG_ERROR("Couldn't open value for gpio %d", gpio);
perror("sysfsgpio: ");
@@ -530,21 +549,27 @@ static int sysfsgpio_quit(void);
static const char * const sysfsgpio_transports[] = { "jtag", "swd", NULL };
-struct jtag_interface sysfsgpio_interface = {
- .name = "sysfsgpio",
+static struct jtag_interface sysfsgpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
+};
+
+struct adapter_driver sysfsgpio_adapter_driver = {
+ .name = "sysfsgpio",
.transports = sysfsgpio_transports,
- .swd = &bitbang_swd,
.commands = sysfsgpio_command_handlers,
+
.init = sysfsgpio_init,
.quit = sysfsgpio_quit,
+ .reset = sysfsgpio_reset,
+
+ .jtag_ops = &sysfsgpio_interface,
+ .swd_ops = &bitbang_swd,
};
static struct bitbang_interface sysfsgpio_bitbang = {
.read = sysfsgpio_read,
.write = sysfsgpio_write,
- .reset = sysfsgpio_reset,
.swdio_read = sysfsgpio_swdio_read,
.swdio_drive = sysfsgpio_swdio_drive,
.blink = 0
@@ -576,23 +601,23 @@ static void cleanup_all_fds(void)
static bool sysfsgpio_jtag_mode_possible(void)
{
if (!is_gpio_valid(tck_gpio))
- return 0;
+ return false;
if (!is_gpio_valid(tms_gpio))
- return 0;
+ return false;
if (!is_gpio_valid(tdi_gpio))
- return 0;
+ return false;
if (!is_gpio_valid(tdo_gpio))
- return 0;
- return 1;
+ return false;
+ return true;
}
static bool sysfsgpio_swd_mode_possible(void)
{
if (!is_gpio_valid(swclk_gpio))
- return 0;
+ return false;
if (!is_gpio_valid(swdio_gpio))
- return 0;
- return 1;
+ return false;
+ return true;
}
static int sysfsgpio_init(void)
@@ -688,4 +713,3 @@ static int sysfsgpio_quit(void)
cleanup_all_fds();
return ERROR_OK;
}
-
diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c
index bbe08aa..242c04f 100644
--- a/src/jtag/drivers/ulink.c
+++ b/src/jtag/drivers/ulink.c
@@ -235,7 +235,7 @@ int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd);
int ulink_post_process_scan(struct ulink_cmd *ulink_cmd);
int ulink_post_process_queue(struct ulink *device);
-/* JTAG driver functions (registered in struct jtag_interface) */
+/* adapter driver functions */
static int ulink_execute_queue(void);
static int ulink_khz(int khz, int *jtag_speed);
static int ulink_speed(int speed);
@@ -650,7 +650,7 @@ void ulink_clear_queue(struct ulink *device)
int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd)
{
int newsize_out, newsize_in;
- int ret;
+ int ret = ERROR_OK;
newsize_out = ulink_get_queue_size(device, PAYLOAD_DIRECTION_OUT) + 1
+ ulink_cmd->payload_out_size;
@@ -663,14 +663,12 @@ int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd)
/* New command does not fit. Execute all commands in queue before starting
* new queue with the current command as first entry. */
ret = ulink_execute_queued_commands(device, USB_TIMEOUT);
- if (ret != ERROR_OK)
- return ret;
- ret = ulink_post_process_queue(device);
- if (ret != ERROR_OK)
- return ret;
+ if (ret == ERROR_OK)
+ ret = ulink_post_process_queue(device);
- ulink_clear_queue(device);
+ if (ret == ERROR_OK)
+ ulink_clear_queue(device);
}
if (device->queue_start == NULL) {
@@ -687,7 +685,10 @@ int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd)
device->queue_end = ulink_cmd;
}
- return ERROR_OK;
+ if (ret != ERROR_OK)
+ ulink_clear_queue(device);
+
+ return ret;
}
/**
@@ -764,58 +765,40 @@ static const char *ulink_cmd_id_string(uint8_t id)
switch (id) {
case CMD_SCAN_IN:
return "CMD_SCAN_IN";
- break;
case CMD_SLOW_SCAN_IN:
return "CMD_SLOW_SCAN_IN";
- break;
case CMD_SCAN_OUT:
return "CMD_SCAN_OUT";
- break;
case CMD_SLOW_SCAN_OUT:
return "CMD_SLOW_SCAN_OUT";
- break;
case CMD_SCAN_IO:
return "CMD_SCAN_IO";
- break;
case CMD_SLOW_SCAN_IO:
return "CMD_SLOW_SCAN_IO";
- break;
case CMD_CLOCK_TMS:
return "CMD_CLOCK_TMS";
- break;
case CMD_SLOW_CLOCK_TMS:
return "CMD_SLOW_CLOCK_TMS";
- break;
case CMD_CLOCK_TCK:
return "CMD_CLOCK_TCK";
- break;
case CMD_SLOW_CLOCK_TCK:
return "CMD_SLOW_CLOCK_TCK";
- break;
case CMD_SLEEP_US:
return "CMD_SLEEP_US";
- break;
case CMD_SLEEP_MS:
return "CMD_SLEEP_MS";
- break;
case CMD_GET_SIGNALS:
return "CMD_GET_SIGNALS";
- break;
case CMD_SET_SIGNALS:
return "CMD_SET_SIGNALS";
- break;
case CMD_CONFIGURE_TCK_FREQ:
return "CMD_CONFIGURE_TCK_FREQ";
- break;
case CMD_SET_LEDS:
return "CMD_SET_LEDS";
- break;
case CMD_TEST:
return "CMD_TEST";
- break;
default:
return "CMD_UNKNOWN";
- break;
}
}
@@ -1627,6 +1610,7 @@ int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd)
if (ret != ERROR_OK) {
free(tdi_buffer_start);
+ free(tdo_buffer_start);
return ret;
}
}
@@ -2209,14 +2193,17 @@ static int ulink_init(void)
}
ulink_clear_queue(ulink_handle);
- ulink_append_get_signals_cmd(ulink_handle);
- ulink_execute_queued_commands(ulink_handle, 200);
+ ret = ulink_append_get_signals_cmd(ulink_handle);
+ if (ret == ERROR_OK)
+ ret = ulink_execute_queued_commands(ulink_handle, 200);
- /* Post-process the single CMD_GET_SIGNALS command */
- input_signals = ulink_handle->queue_start->payload_in[0];
- output_signals = ulink_handle->queue_start->payload_in[1];
+ if (ret == ERROR_OK) {
+ /* Post-process the single CMD_GET_SIGNALS command */
+ input_signals = ulink_handle->queue_start->payload_in[0];
+ output_signals = ulink_handle->queue_start->payload_in[1];
- ulink_print_signal_states(input_signals, output_signals);
+ ulink_print_signal_states(input_signals, output_signals);
+ }
ulink_clear_queue(ulink_handle);
@@ -2272,17 +2259,20 @@ static const struct command_registration ulink_command_handlers[] = {
COMMAND_REGISTRATION_DONE,
};
-struct jtag_interface ulink_interface = {
- .name = "ulink",
+static struct jtag_interface ulink_interface = {
+ .execute_queue = ulink_execute_queue,
+};
- .commands = ulink_command_handlers,
+struct adapter_driver ulink_adapter_driver = {
+ .name = "ulink",
.transports = jtag_only,
+ .commands = ulink_command_handlers,
- .execute_queue = ulink_execute_queue,
- .khz = ulink_khz,
+ .init = ulink_init,
+ .quit = ulink_quit,
.speed = ulink_speed,
+ .khz = ulink_khz,
.speed_div = ulink_speed_div,
- .init = ulink_init,
- .quit = ulink_quit
+ .jtag_ops = &ulink_interface,
};
diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c
index d991733..e2556ce 100644
--- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c
+++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c
@@ -23,7 +23,7 @@
#endif
#include <jtag/interface.h>
#include <jtag/commands.h>
-#include <libusb_common.h>
+#include <libusb_helper.h>
#include <target/image.h>
#include "ublast_access.h"
@@ -42,28 +42,37 @@
static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf,
unsigned size, uint32_t *bytes_read)
{
- *bytes_read = jtag_libusb_bulk_read(low->libusb_dev,
- USBBLASTER_EPIN | \
+ int ret, tmp = 0;
+
+ ret = jtag_libusb_bulk_read(low->libusb_dev,
+ USBBLASTER_EPIN |
LIBUSB_ENDPOINT_IN,
(char *)buf,
size,
- 100);
- return ERROR_OK;
+ 100, &tmp);
+ *bytes_read = tmp;
+
+ return ret;
}
static int ublast2_libusb_write(struct ublast_lowlevel *low, uint8_t *buf,
int size, uint32_t *bytes_written)
{
- *bytes_written = jtag_libusb_bulk_write(low->libusb_dev,
- USBBLASTER_EPOUT | \
+ int ret, tmp = 0;
+
+ ret = jtag_libusb_bulk_write(low->libusb_dev,
+ USBBLASTER_EPOUT |
LIBUSB_ENDPOINT_OUT,
(char *)buf,
size,
- 100);
- return ERROR_OK;
+ 100, &tmp);
+ *bytes_written = tmp;
+
+ return ret;
+
}
-static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libusb_dev,
+static int ublast2_write_firmware_section(struct libusb_device_handle *libusb_dev,
struct image *firmware_image, int section_index)
{
uint16_t chunk_size;
@@ -97,7 +106,7 @@ static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libu
chunk_size = bytes_remaining;
jtag_libusb_control_transfer(libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
+ LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT,
USBBLASTER_CTRL_LOAD_FIRM,
addr,
@@ -114,7 +123,7 @@ static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libu
return ERROR_OK;
}
-static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_dev,
+static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
struct ublast_lowlevel *low)
{
struct image ublast2_firmware_image;
@@ -143,7 +152,7 @@ static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_de
char value = CPU_RESET;
jtag_libusb_control_transfer(libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
+ LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT,
USBBLASTER_CTRL_LOAD_FIRM,
EZUSB_CPUCS,
@@ -164,7 +173,7 @@ static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_de
value = !CPU_RESET;
jtag_libusb_control_transfer(libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
+ LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT,
USBBLASTER_CTRL_LOAD_FIRM,
EZUSB_CPUCS,
@@ -182,11 +191,11 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
{
const uint16_t vids[] = { low->ublast_vid_uninit, 0 };
const uint16_t pids[] = { low->ublast_pid_uninit, 0 };
- struct jtag_libusb_device_handle *temp;
+ struct libusb_device_handle *temp;
bool renumeration = false;
int ret;
- if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) {
+ if (jtag_libusb_open(vids, pids, NULL, &temp, NULL) == ERROR_OK) {
LOG_INFO("Altera USB-Blaster II (uninitialized) found");
LOG_INFO("Loading firmware...");
ret = load_usb_blaster_firmware(temp, low);
@@ -200,13 +209,15 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
const uint16_t pids_renum[] = { low->ublast_pid, 0 };
if (renumeration == false) {
- if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) {
+ if (jtag_libusb_open(vids_renum, pids_renum, NULL,
+ &low->libusb_dev, NULL) != ERROR_OK) {
LOG_ERROR("Altera USB-Blaster II not found");
return ERROR_FAIL;
}
} else {
int retry = 10;
- while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) {
+ while (jtag_libusb_open(vids_renum, pids_renum, NULL,
+ &low->libusb_dev, NULL) != ERROR_OK && retry--) {
usleep(1000000);
LOG_INFO("Waiting for renumerate...");
}
@@ -219,7 +230,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
char buffer[5];
jtag_libusb_control_transfer(low->libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
+ LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN,
USBBLASTER_CTRL_READ_REV,
0,
diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h
index 252f003..ad20d65 100644
--- a/src/jtag/drivers/usb_blaster/ublast_access.h
+++ b/src/jtag/drivers/usb_blaster/ublast_access.h
@@ -28,8 +28,6 @@
#ifndef OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H
#define OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H
-#include <libusb_common.h>
-
/* Low level flags */
#define COPY_TDO_BUFFER (1 << 0)
@@ -39,7 +37,7 @@ struct ublast_lowlevel {
uint16_t ublast_vid_uninit;
uint16_t ublast_pid_uninit;
char *ublast_device_desc;
- struct jtag_libusb_device_handle *libusb_dev;
+ struct libusb_device_handle *libusb_dev;
char *firmware_path;
int (*write)(struct ublast_lowlevel *low, uint8_t *buf, int size,
diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c
index 165ebdc..d30483b 100644
--- a/src/jtag/drivers/usb_blaster/usb_blaster.c
+++ b/src/jtag/drivers/usb_blaster/usb_blaster.c
@@ -816,6 +816,11 @@ static int ublast_execute_queue(void)
case JTAG_SCAN:
ret = ublast_scan(cmd->cmd.scan);
break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type 0x%X",
+ cmd->type);
+ ret = ERROR_FAIL;
+ break;
}
}
@@ -1037,8 +1042,8 @@ static const struct command_registration ublast_command_handlers[] = {
.name = "usb_blaster_vid_pid",
.handler = ublast_handle_vid_pid_command,
.mode = COMMAND_CONFIG,
- .help = "the vendor ID and product ID of the USB-Blaster and " \
- "vendor ID and product ID of the uninitialized device " \
+ .help = "the vendor ID and product ID of the USB-Blaster and "
+ "vendor ID and product ID of the uninitialized device "
"for USB-Blaster II",
.usage = "vid pid vid_uninit pid_uninit",
},
@@ -1066,13 +1071,18 @@ static const struct command_registration ublast_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface usb_blaster_interface = {
+static struct jtag_interface usb_blaster_interface = {
+ .supported = DEBUG_CAP_TMS_SEQ,
+ .execute_queue = ublast_execute_queue,
+};
+
+struct adapter_driver usb_blaster_adapter_driver = {
.name = "usb_blaster",
.transports = jtag_only,
.commands = ublast_command_handlers,
- .supported = DEBUG_CAP_TMS_SEQ,
- .execute_queue = ublast_execute_queue,
.init = ublast_init,
.quit = ublast_quit,
+
+ .jtag_ops = &usb_blaster_interface,
};
diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c
index 35a9520..7b27eaf 100644
--- a/src/jtag/drivers/usbprog.c
+++ b/src/jtag/drivers/usbprog.c
@@ -381,7 +381,7 @@ static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
{
int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg, msglen, 100);
- if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \
+ if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) ||
(msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
return 1;
if (res == msglen) {
@@ -596,11 +596,16 @@ static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
}
}
-struct jtag_interface usbprog_interface = {
+static struct jtag_interface usbprog_interface = {
+ .execute_queue = usbprog_execute_queue,
+};
+
+struct adapter_driver usbprog_adapter_driver = {
.name = "usbprog",
.transports = jtag_only,
- .execute_queue = usbprog_execute_queue,
.init = usbprog_init,
- .quit = usbprog_quit
+ .quit = usbprog_quit,
+
+ .jtag_ops = &usbprog_interface,
};
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c
index 53a7e98..678b097 100644
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c
+++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c
@@ -48,7 +48,7 @@ uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
#define usbtoxxx_get_type_name(type) \
types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
- % (sizeof(types_name) / sizeof(types_name[0]))]
+ % ARRAY_SIZE(types_name)]
static uint8_t type_pre;
static uint16_t usbtoxxx_buffer_index;
diff --git a/src/jtag/drivers/versaloon/versaloon_internal.h b/src/jtag/drivers/versaloon/versaloon_internal.h
index 497b6b9..8372970 100644
--- a/src/jtag/drivers/versaloon/versaloon_internal.h
+++ b/src/jtag/drivers/versaloon/versaloon_internal.h
@@ -91,7 +91,7 @@ struct versaloon_pending_t {
void *extra_data;
versaloon_callback_t callback;
};
-extern struct versaloon_pending_t \
+extern struct versaloon_pending_t
versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
extern uint16_t versaloon_pending_idx;
void versaloon_set_pending_id(uint32_t id);
diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c
index 4907ef0..5fb9bcd 100644
--- a/src/jtag/drivers/vsllink.c
+++ b/src/jtag/drivers/vsllink.c
@@ -59,7 +59,7 @@ static void vsllink_runtest(int num_cycles);
static void vsllink_stableclocks(int num_cycles, int tms);
static void vsllink_scan(bool ir_scan, enum scan_type type,
uint8_t *buffer, int scan_size, struct scan_command *command);
-static void vsllink_reset(int trst, int srst);
+static int vsllink_reset(int trst, int srst);
/* VSLLink tap buffer functions */
static void vsllink_tap_append_step(int tms, int tdi);
@@ -164,20 +164,6 @@ static int vsllink_execute_queue(void)
cmd->cmd.scan);
break;
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-
- vsllink_tap_execute();
-
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
-
- vsllink_reset(cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
- break;
-
case JTAG_SLEEP:
LOG_DEBUG_IO("sleep %i", cmd->cmd.sleep->us);
vsllink_tap_execute();
@@ -306,7 +292,7 @@ static int vsllink_interface_init(void)
libusb_init(&vsllink_handle->libusb_ctx);
if (ERROR_OK != vsllink_usb_open(vsllink_handle)) {
- LOG_ERROR("Can't find USB JTAG Interface!" \
+ LOG_ERROR("Can't find USB JTAG Interface!"
"Please check connection and permissions.");
return ERROR_JTAG_INIT_FAILED;
}
@@ -478,7 +464,7 @@ static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
vsllink_state_move();
}
-static void vsllink_reset(int trst, int srst)
+static int vsllink_reset(int trst, int srst)
{
LOG_DEBUG("trst: %i, srst: %i", trst, srst);
@@ -494,7 +480,7 @@ static void vsllink_reset(int trst, int srst)
versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, 0);
}
- versaloon_interface.adaptors.peripheral_commit();
+ return versaloon_interface.adaptors.peripheral_commit();
}
COMMAND_HANDLER(vsllink_handle_usb_vid_command)
@@ -962,17 +948,23 @@ static const struct swd_driver vsllink_swd_driver = {
.run = vsllink_swd_run_queue,
};
-struct jtag_interface vsllink_interface = {
- .name = "vsllink",
+static struct jtag_interface vsllink_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
- .commands = vsllink_command_handlers,
+ .execute_queue = vsllink_execute_queue,
+};
+
+struct adapter_driver vsllink_adapter_driver = {
+ .name = "vsllink",
.transports = vsllink_transports,
- .swd = &vsllink_swd_driver,
+ .commands = vsllink_command_handlers,
.init = vsllink_init,
.quit = vsllink_quit,
- .khz = vsllink_khz,
+ .reset = vsllink_reset,
.speed = vsllink_speed,
+ .khz = vsllink_khz,
.speed_div = vsllink_speed_div,
- .execute_queue = vsllink_execute_queue,
+
+ .jtag_ops = &vsllink_interface,
+ .swd_ops = &vsllink_swd_driver,
};
diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c
index f25023b..5e4df93 100644
--- a/src/jtag/drivers/xds110.c
+++ b/src/jtag/drivers/xds110.c
@@ -41,6 +41,12 @@
#define OCD_FIRMWARE_UPGRADE \
"XDS110: upgrade to version 2.3.0.11+ for improved support"
+/* Firmware version that introduced improved TCK performance */
+#define FAST_TCK_FIRMWARE_VERSION 0x03000000
+
+/* Firmware version that introduced 10 MHz and 12 MHz TCK support */
+#define FAST_TCK_PLUS_FIRMWARE_VERSION 0x03000003
+
/***************************************************************************
* USB Connection Buffer Definitions *
***************************************************************************/
@@ -61,15 +67,6 @@
#define MAX_RESULT_QUEUE (MAX_DATA_BLOCK / 4)
/***************************************************************************
- * USB Connection Endpoints *
- ***************************************************************************/
-
-/* Bulk endpoints used by the XDS110 debug interface */
-#define INTERFACE_DEBUG (2)
-#define ENDPOINT_DEBUG_IN (3 | LIBUSB_ENDPOINT_IN)
-#define ENDPOINT_DEBUG_OUT (2 | LIBUSB_ENDPOINT_OUT)
-
-/***************************************************************************
* XDS110 Firmware API Definitions *
***************************************************************************/
@@ -91,8 +88,17 @@
/* TCK frequency limits */
#define XDS110_MIN_TCK_SPEED 100 /* kHz */
-#define XDS110_MAX_TCK_SPEED 2500 /* kHz */
-#define XDS110_TCK_PULSE_INCREMENT 66.0
+#define XDS110_MAX_SLOW_TCK_SPEED 2500 /* kHz */
+#define XDS110_MAX_FAST_TCK_SPEED 14000 /* kHz */
+#define XDS110_DEFAULT_TCK_SPEED 2500 /* kHz */
+
+/* Fixed TCK delay values for "Fast" TCK frequencies */
+#define FAST_TCK_DELAY_14000_KHZ 0
+#define FAST_TCK_DELAY_10000_KHZ 0xfffffffd
+#define FAST_TCK_DELAY_12000_KHZ 0xfffffffe
+#define FAST_TCK_DELAY_8500_KHZ 1
+#define FAST_TCK_DELAY_5500_KHZ 2
+/* For TCK frequencies below 5500 kHz, use calculated delay */
/* Scan mode on connect */
#define MODE_JTAG 1
@@ -212,6 +218,13 @@ struct xds110_info {
unsigned char read_payload[USB_PAYLOAD_SIZE];
unsigned char write_packet[3];
unsigned char write_payload[USB_PAYLOAD_SIZE];
+ /* Device vid/pid */
+ uint16_t vid;
+ uint16_t pid;
+ /* Debug interface */
+ uint8_t interface;
+ uint8_t endpoint_in;
+ uint8_t endpoint_out;
/* Status flags */
bool is_connected;
bool is_cmapi_connected;
@@ -244,12 +257,17 @@ struct xds110_info {
static struct xds110_info xds110 = {
.ctx = NULL,
.dev = NULL,
+ .vid = 0,
+ .pid = 0,
+ .interface = 0,
+ .endpoint_in = 0,
+ .endpoint_out = 0,
.is_connected = false,
.is_cmapi_connected = false,
.is_cmapi_acquired = false,
.is_swd_mode = false,
.is_ap_dirty = false,
- .speed = XDS110_MAX_TCK_SPEED,
+ .speed = XDS110_DEFAULT_TCK_SPEED,
.delay_count = 0,
.serial = {0},
.voltage = 0,
@@ -305,12 +323,20 @@ static bool usb_connect(void)
struct libusb_device_descriptor desc;
- uint16_t vid = 0x0451;
- uint16_t pid = 0xbef3;
+ /* The vid/pids of possible XDS110 configurations */
+ uint16_t vids[] = { 0x0451, 0x0451, 0x1cbe };
+ uint16_t pids[] = { 0xbef3, 0xbef4, 0x02a5 };
+ /* Corresponding interface and endpoint numbers for configurations */
+ uint8_t interfaces[] = { 2, 2, 0 };
+ uint8_t endpoints_in[] = { 3, 3, 1 };
+ uint8_t endpoints_out[] = { 2, 2, 1 };
+
ssize_t count = 0;
ssize_t i = 0;
int result = 0;
bool found = false;
+ uint32_t device = 0;
+ bool match = false;
/* Initialize libusb context */
result = libusb_init(&ctx);
@@ -327,13 +353,21 @@ static bool usb_connect(void)
if (0 == result) {
/* Scan through list of devices for any XDS110s */
for (i = 0; i < count; i++) {
- /* Check for device VID/PID match */
+ /* Check for device vid/pid match */
libusb_get_device_descriptor(list[i], &desc);
- if (desc.idVendor == vid && desc.idProduct == pid) {
+ match = false;
+ for (device = 0; device < sizeof(vids)/sizeof(vids[0]); device++) {
+ if (desc.idVendor == vids[device] &&
+ desc.idProduct == pids[device]) {
+ match = true;
+ break;
+ }
+ }
+ if (match) {
result = libusb_open(list[i], &dev);
if (0 == result) {
- const int MAX_DATA = 256;
- unsigned char data[MAX_DATA + 1];
+ const int max_data = 256;
+ unsigned char data[max_data + 1];
*data = '\0';
/* May be the requested device if serial number matches */
@@ -344,7 +378,7 @@ static bool usb_connect(void)
} else {
/* Get the device's serial number string */
result = libusb_get_string_descriptor_ascii(dev,
- desc.iSerialNumber, data, MAX_DATA);
+ desc.iSerialNumber, data, max_data);
if (0 < result &&
0 == strcmp((char *)data, (char *)xds110.serial)) {
found = true;
@@ -372,6 +406,15 @@ static bool usb_connect(void)
}
if (found) {
+ /* Save the vid/pid of the device we're using */
+ xds110.vid = vids[device];
+ xds110.pid = pids[device];
+
+ /* Save the debug interface and endpoints for the device */
+ xds110.interface = interfaces[device];
+ xds110.endpoint_in = endpoints_in[device] | LIBUSB_ENDPOINT_IN;
+ xds110.endpoint_out = endpoints_out[device] | LIBUSB_ENDPOINT_OUT;
+
/* Save the context and device handles */
xds110.ctx = ctx;
xds110.dev = dev;
@@ -380,7 +423,7 @@ static bool usb_connect(void)
(void)libusb_set_auto_detach_kernel_driver(dev, 1);
/* Claim the debug interface on the XDS110 */
- result = libusb_claim_interface(dev, INTERFACE_DEBUG);
+ result = libusb_claim_interface(dev, xds110.interface);
} else {
/* Couldn't find an XDS110, flag the error */
result = -1;
@@ -390,7 +433,7 @@ static bool usb_connect(void)
if (0 != result) {
if (NULL != dev) {
/* Release the debug and data interface on the XDS110 */
- (void)libusb_release_interface(dev, INTERFACE_DEBUG);
+ (void)libusb_release_interface(dev, xds110.interface);
libusb_close(dev);
}
if (NULL != ctx)
@@ -412,7 +455,7 @@ static void usb_disconnect(void)
{
if (NULL != xds110.dev) {
/* Release the debug and data interface on the XDS110 */
- (void)libusb_release_interface(xds110.dev, INTERFACE_DEBUG);
+ (void)libusb_release_interface(xds110.dev, xds110.interface);
libusb_close(xds110.dev);
xds110.dev = NULL;
}
@@ -436,7 +479,7 @@ static bool usb_read(unsigned char *buffer, int size, int *bytes_read,
if (0 == timeout)
timeout = DEFAULT_TIMEOUT;
- result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_IN, buffer, size,
+ result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_in, buffer, size,
bytes_read, timeout);
return (0 == result) ? true : false;
@@ -451,13 +494,13 @@ static bool usb_write(unsigned char *buffer, int size, int *written)
if (NULL == xds110.dev || NULL == buffer)
return false;
- result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer,
+ result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_out, buffer,
size, &bytes_written, 0);
while (LIBUSB_ERROR_PIPE == result && retries < 3) {
/* Try clearing the pipe stall and retry transfer */
- libusb_clear_halt(xds110.dev, ENDPOINT_DEBUG_OUT);
- result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer,
+ libusb_clear_halt(xds110.dev, xds110.endpoint_out);
+ result = libusb_bulk_transfer(xds110.dev, xds110.endpoint_out, buffer,
size, &bytes_written, 0);
retries++;
}
@@ -1345,6 +1388,7 @@ static void xds110_show_info(void)
{
uint32_t firmware = xds110.firmware;
+ LOG_INFO("XDS110: vid/pid = %04x/%04x", xds110.vid, xds110.pid);
LOG_INFO("XDS110: firmware version = %d.%d.%d.%d",
(((firmware >> 28) & 0xf) * 10) + ((firmware >> 24) & 0xf),
(((firmware >> 20) & 0xf) * 10) + ((firmware >> 16) & 0xf),
@@ -1592,48 +1636,58 @@ static void xds110_flush(void)
xds110.txn_result_count = 0;
}
-static void xds110_execute_reset(struct jtag_command *cmd)
+static int xds110_reset(int trst, int srst)
{
- char trst;
- char srst;
+ uint8_t value;
+ bool success;
+ int retval = ERROR_OK;
- if (cmd->cmd.reset->trst != -1) {
- if (cmd->cmd.reset->trst == 0) {
+ if (trst != -1) {
+ if (trst == 0) {
/* Deassert nTRST (active low) */
- trst = 1;
+ value = 1;
} else {
/* Assert nTRST (active low) */
- trst = 0;
+ value = 0;
}
- (void)xds_set_trst(trst);
+ success = xds_set_trst(value);
+ if (!success)
+ retval = ERROR_FAIL;
}
- if (cmd->cmd.reset->srst != -1) {
- if (cmd->cmd.reset->srst == 0) {
+ if (srst != -1) {
+ if (srst == 0) {
/* Deassert nSRST (active low) */
- srst = 1;
+ value = 1;
} else {
/* Assert nSRST (active low) */
- srst = 0;
+ value = 0;
}
- (void)xds_set_srst(srst);
+ success = xds_set_srst(value);
+ if (!success)
+ retval = ERROR_FAIL;
/* Toggle TCK to trigger HIB on CC13x/CC26x devices */
- (void)xds_cycle_tck(60000);
+ if (success && !xds110.is_swd_mode) {
+ /* Toggle TCK for about 50 ms */
+ success = xds_cycle_tck(xds110.speed * 50);
+ }
+
+ if (!success)
+ retval = ERROR_FAIL;
}
+
+ return retval;
}
static void xds110_execute_sleep(struct jtag_command *cmd)
{
jtag_sleep(cmd->cmd.sleep->us);
- return;
}
static void xds110_execute_tlr_reset(struct jtag_command *cmd)
{
(void)xds_goto_state(XDS_JTAG_STATE_RESET);
-
- return;
}
static void xds110_execute_pathmove(struct jtag_command *cmd)
@@ -1669,8 +1723,6 @@ static void xds110_execute_pathmove(struct jtag_command *cmd)
}
free((void *)path);
-
- return;
}
static void xds110_queue_scan(struct jtag_command *cmd)
@@ -1742,8 +1794,6 @@ static void xds110_queue_scan(struct jtag_command *cmd)
}
xds110.txn_request_size += total_bytes;
xds110.txn_result_size += total_bytes;
-
- return;
}
static void xds110_queue_runtest(struct jtag_command *cmd)
@@ -1763,8 +1813,6 @@ static void xds110_queue_runtest(struct jtag_command *cmd)
xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 16) & 0xff;
xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 24) & 0xff;
xds110.txn_requests[xds110.txn_request_size++] = end_state;
-
- return;
}
static void xds110_queue_stableclocks(struct jtag_command *cmd)
@@ -1781,17 +1829,11 @@ static void xds110_queue_stableclocks(struct jtag_command *cmd)
xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 8) & 0xff;
xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 16) & 0xff;
xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 24) & 0xff;
-
- return;
}
static void xds110_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
- case JTAG_RESET:
- xds110_flush();
- xds110_execute_reset(cmd);
- break;
case JTAG_SLEEP:
xds110_flush();
xds110_execute_sleep(cmd);
@@ -1837,6 +1879,8 @@ static int xds110_execute_queue(void)
static int xds110_speed(int speed)
{
+ double freq_to_use;
+ uint32_t delay_count;
bool success;
if (speed == 0) {
@@ -1844,61 +1888,110 @@ static int xds110_speed(int speed)
return ERROR_JTAG_NOT_IMPLEMENTED;
}
- if (speed > XDS110_MAX_TCK_SPEED) {
- LOG_INFO("XDS110: reduce speed request: %dkHz to %dkHz maximum",
- speed, XDS110_MAX_TCK_SPEED);
- speed = XDS110_MAX_TCK_SPEED;
- }
-
if (speed < XDS110_MIN_TCK_SPEED) {
- LOG_INFO("XDS110: increase speed request: %dkHz to %dkHz minimum",
+ LOG_INFO("XDS110: increase speed request: %d kHz to %d kHz minimum",
speed, XDS110_MIN_TCK_SPEED);
speed = XDS110_MIN_TCK_SPEED;
}
- /* The default is the maximum frequency the XDS110 can support */
- uint32_t freq_to_use = XDS110_MAX_TCK_SPEED * 1000; /* Hz */
- uint32_t delay_count = 0;
+ /* Older XDS110 firmware had inefficient scan routines and could only */
+ /* achieve a peak TCK frequency of about 2500 kHz */
+ if (xds110.firmware < FAST_TCK_FIRMWARE_VERSION) {
- if (XDS110_MAX_TCK_SPEED != speed) {
- freq_to_use = speed * 1000; /* Hz */
+ /* Check for request for top speed or higher */
+ if (speed >= XDS110_MAX_SLOW_TCK_SPEED) {
- /* Calculate the delay count value */
- double one_giga = 1000000000;
- /* Get the pulse duration for the maximum frequency supported in ns */
- double max_freq_pulse_duration = one_giga /
- (XDS110_MAX_TCK_SPEED * 1000);
+ /* Inform user that speed was adjusted down to max possible */
+ if (speed > XDS110_MAX_SLOW_TCK_SPEED) {
+ LOG_INFO(
+ "XDS110: reduce speed request: %d kHz to %d kHz maximum",
+ speed, XDS110_MAX_SLOW_TCK_SPEED);
+ speed = XDS110_MAX_SLOW_TCK_SPEED;
+ }
+ delay_count = 0;
- /* Convert frequency to pulse duration */
- double freq_to_pulse_width_in_ns = one_giga / freq_to_use;
+ } else {
- /*
- * Start with the pulse duration for the maximum frequency. Keep
- * decrementing the time added by each count value till the requested
- * frequency pulse is less than the calculated value.
- */
- double current_value = max_freq_pulse_duration;
+ const double XDS110_TCK_PULSE_INCREMENT = 66.0;
+ freq_to_use = speed * 1000; /* Hz */
+ delay_count = 0;
+
+ /* Calculate the delay count value */
+ double one_giga = 1000000000;
+ /* Get the pulse duration for the max frequency supported in ns */
+ double max_freq_pulse_duration = one_giga /
+ (XDS110_MAX_SLOW_TCK_SPEED * 1000);
- while (current_value < freq_to_pulse_width_in_ns) {
- current_value += XDS110_TCK_PULSE_INCREMENT;
- ++delay_count;
+ /* Convert frequency to pulse duration */
+ double freq_to_pulse_width_in_ns = one_giga / freq_to_use;
+
+ /*
+ * Start with the pulse duration for the maximum frequency. Keep
+ * decrementing time added by each count value till the requested
+ * frequency pulse is less than the calculated value.
+ */
+ double current_value = max_freq_pulse_duration;
+
+ while (current_value < freq_to_pulse_width_in_ns) {
+ current_value += XDS110_TCK_PULSE_INCREMENT;
+ ++delay_count;
+ }
+
+ /*
+ * Determine which delay count yields the best match.
+ * The one obtained above or one less.
+ */
+ if (delay_count) {
+ double diff_freq_1 = freq_to_use -
+ (one_giga / (max_freq_pulse_duration +
+ (XDS110_TCK_PULSE_INCREMENT * delay_count)));
+ double diff_freq_2 = (one_giga / (max_freq_pulse_duration +
+ (XDS110_TCK_PULSE_INCREMENT * (delay_count - 1)))) -
+ freq_to_use;
+
+ /* One less count value yields a better match */
+ if (diff_freq_1 > diff_freq_2)
+ --delay_count;
+ }
}
- /*
- * Determine which delay count yields the best match.
- * The one obtained above or one less.
- */
- if (delay_count) {
- double diff_freq_1 = freq_to_use -
- (one_giga / (max_freq_pulse_duration +
- (XDS110_TCK_PULSE_INCREMENT * delay_count)));
- double diff_freq_2 = (one_giga / (max_freq_pulse_duration +
- (XDS110_TCK_PULSE_INCREMENT * (delay_count - 1)))) -
- freq_to_use;
-
- /* One less count value yields a better match */
- if (diff_freq_1 > diff_freq_2)
- --delay_count;
+ /* Newer firmware has reworked TCK routines that are much more efficient */
+ /* and can now achieve a peak TCK frequency of 14000 kHz */
+ } else {
+
+ if (speed >= XDS110_MAX_FAST_TCK_SPEED) {
+ if (speed > XDS110_MAX_FAST_TCK_SPEED) {
+ LOG_INFO(
+ "XDS110: reduce speed request: %d kHz to %d kHz maximum",
+ speed, XDS110_MAX_FAST_TCK_SPEED);
+ speed = XDS110_MAX_FAST_TCK_SPEED;
+ }
+ delay_count = 0;
+ } else if (speed >= 12000 && xds110.firmware >=
+ FAST_TCK_PLUS_FIRMWARE_VERSION) {
+ delay_count = FAST_TCK_DELAY_12000_KHZ;
+ } else if (speed >= 10000 && xds110.firmware >=
+ FAST_TCK_PLUS_FIRMWARE_VERSION) {
+ delay_count = FAST_TCK_DELAY_10000_KHZ;
+ } else if (speed >= 8500) {
+ delay_count = FAST_TCK_DELAY_8500_KHZ;
+ } else if (speed >= 5500) {
+ delay_count = FAST_TCK_DELAY_5500_KHZ;
+ } else {
+ /* Calculate the delay count to set the frequency */
+ /* Formula determined by measuring the waveform on Saeleae logic */
+ /* analyzer using known values for delay count */
+ const double m = 17100000.0; /* slope */
+ const double b = -1.02; /* y-intercept */
+
+ freq_to_use = speed * 1000; /* Hz */
+ double period = 1.0/freq_to_use;
+ double delay = m * period + b;
+
+ if (delay < 1.0)
+ delay_count = 1;
+ else
+ delay_count = (uint32_t)delay;
}
}
@@ -1953,11 +2046,8 @@ COMMAND_HANDLER(xds110_handle_serial_command)
xds110.serial[i] = (char)serial[i];
xds110.serial[len] = 0;
- } else {
- LOG_ERROR("XDS110: expected exactly one argument to xds110_serial "
- "<serial-number>");
- return ERROR_FAIL;
- }
+ } else
+ return ERROR_COMMAND_SYNTAX_ERROR;
return ERROR_OK;
}
@@ -1978,11 +2068,8 @@ COMMAND_HANDLER(xds110_handle_supply_voltage_command)
return ERROR_FAIL;
}
xds110.voltage = voltage;
- } else {
- LOG_ERROR("XDS110: expected one argument to xds110_supply_voltage "
- "<millivolts>");
- return ERROR_FAIL;
- }
+ } else
+ return ERROR_COMMAND_SYNTAX_ERROR;
return ERROR_OK;
}
@@ -1992,33 +2079,33 @@ static const struct command_registration xds110_subcommand_handlers[] = {
.name = "info",
.handler = &xds110_handle_info_command,
.mode = COMMAND_EXEC,
- .usage = "",
.help = "show XDS110 info",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration xds110_command_handlers[] = {
- {
- .name = "xds110",
- .mode = COMMAND_ANY,
- .help = "perform XDS110 management",
- .usage = "<cmd>",
- .chain = xds110_subcommand_handlers,
+ .usage = "",
},
{
- .name = "xds110_serial",
+ .name = "serial",
.handler = &xds110_handle_serial_command,
.mode = COMMAND_CONFIG,
.help = "set the XDS110 probe serial number",
.usage = "serial_string",
},
{
- .name = "xds110_supply_voltage",
+ .name = "supply",
.handler = &xds110_handle_supply_voltage_command,
.mode = COMMAND_CONFIG,
.help = "set the XDS110 probe supply voltage",
- .usage = "supply_voltage (millivolts)",
+ .usage = "voltage_in_millivolts",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration xds110_command_handlers[] = {
+ {
+ .name = "xds110",
+ .mode = COMMAND_ANY,
+ .help = "perform XDS110 management",
+ .usage = "",
+ .chain = xds110_subcommand_handlers,
},
COMMAND_REGISTRATION_DONE
};
@@ -2033,16 +2120,22 @@ static const struct swd_driver xds110_swd_driver = {
static const char * const xds110_transport[] = { "swd", "jtag", NULL };
-struct jtag_interface xds110_interface = {
+static struct jtag_interface xds110_interface = {
+ .execute_queue = xds110_execute_queue,
+};
+
+struct adapter_driver xds110_adapter_driver = {
.name = "xds110",
- .commands = xds110_command_handlers,
- .swd = &xds110_swd_driver,
.transports = xds110_transport,
+ .commands = xds110_command_handlers,
- .execute_queue = xds110_execute_queue,
- .speed = xds110_speed,
- .speed_div = xds110_speed_div,
- .khz = xds110_khz,
.init = xds110_init,
.quit = xds110_quit,
+ .reset = xds110_reset,
+ .speed = xds110_speed,
+ .khz = xds110_khz,
+ .speed_div = xds110_speed_div,
+
+ .jtag_ops = &xds110_interface,
+ .swd_ops = &xds110_swd_driver,
};
diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c
new file mode 100644
index 0000000..1743859
--- /dev/null
+++ b/src/jtag/drivers/xlnx-pcie-xvc.c
@@ -0,0 +1,487 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2019 Google, LLC.
+ * Author: Moritz Fischer <moritzf@google.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <linux/pci.h>
+
+#include <jtag/interface.h>
+#include <jtag/swd.h>
+#include <jtag/commands.h>
+#include <helper/replacements.h>
+#include <helper/bits.h>
+
+/* Available only from kernel v4.10 */
+#ifndef PCI_CFG_SPACE_EXP_SIZE
+#define PCI_CFG_SPACE_EXP_SIZE 4096
+#endif
+
+#define PCIE_EXT_CAP_LST 0x100
+
+#define XLNX_XVC_EXT_CAP 0x00
+#define XLNX_XVC_VSEC_HDR 0x04
+#define XLNX_XVC_LEN_REG 0x0C
+#define XLNX_XVC_TMS_REG 0x10
+#define XLNX_XVC_TDx_REG 0x14
+
+#define XLNX_XVC_CAP_SIZE 0x20
+#define XLNX_XVC_VSEC_ID 0x8
+#define XLNX_XVC_MAX_BITS 0x20
+
+struct xlnx_pcie_xvc {
+ int fd;
+ unsigned offset;
+ char *device;
+};
+
+static struct xlnx_pcie_xvc xlnx_pcie_xvc_state;
+static struct xlnx_pcie_xvc *xlnx_pcie_xvc = &xlnx_pcie_xvc_state;
+
+static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
+{
+ uint32_t res;
+ int err;
+
+ /* Note: This should be ok endianess-wise because by going
+ * through sysfs the kernel does the conversion in the config
+ * space accessor functions
+ */
+ err = pread(xlnx_pcie_xvc->fd, &res, sizeof(res),
+ xlnx_pcie_xvc->offset + offset);
+ if (err != sizeof(res)) {
+ LOG_ERROR("Failed to read offset %x", offset);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+
+ if (val)
+ *val = res;
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
+{
+ int err;
+
+ /* Note: This should be ok endianess-wise because by going
+ * through sysfs the kernel does the conversion in the config
+ * space accessor functions
+ */
+ err = pwrite(xlnx_pcie_xvc->fd, &val, sizeof(val),
+ xlnx_pcie_xvc->offset + offset);
+ if (err != sizeof(val)) {
+ LOG_ERROR("Failed to write offset: %x with value: %x",
+ offset, val);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
+ uint32_t *tdo)
+{
+ int err;
+
+ err = xlnx_pcie_xvc_write_reg(XLNX_XVC_LEN_REG, num_bits);
+ if (err != ERROR_OK)
+ return err;
+
+ err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TMS_REG, tms);
+ if (err != ERROR_OK)
+ return err;
+
+ err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TDx_REG, tdi);
+ if (err != ERROR_OK)
+ return err;
+
+ err = xlnx_pcie_xvc_read_reg(XLNX_XVC_TDx_REG, tdo);
+ if (err != ERROR_OK)
+ return err;
+
+ if (tdo)
+ LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: %x",
+ num_bits, tms, tdi, *tdo);
+ else
+ LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: <null>",
+ num_bits, tms, tdi);
+ return ERROR_OK;
+}
+
+int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
+{
+ int tms = tap_get_state() == TAP_RESET ? 1 : 0;
+ size_t left = cmd->cmd.stableclocks->num_cycles;
+ size_t write;
+ int err;
+
+ LOG_DEBUG("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
+
+ while (left) {
+ write = MIN(XLNX_XVC_MAX_BITS, left);
+ err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
+ if (err != ERROR_OK)
+ return err;
+ left -= write;
+ };
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_statemove(size_t skip)
+{
+ uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
+ tap_get_end_state());
+ int tms_count = tap_get_tms_path_len(tap_get_state(),
+ tap_get_end_state());
+ int err;
+
+ LOG_DEBUG("statemove starting at (skip: %zu) %s end in %s", skip,
+ tap_state_name(tap_get_state()),
+ tap_state_name(tap_get_end_state()));
+
+
+ err = xlnx_pcie_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL);
+ if (err != ERROR_OK)
+ return err;
+
+ tap_set_state(tap_get_end_state());
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
+{
+ int err = ERROR_OK;
+
+ LOG_DEBUG("runtest %i cycles, end in %i",
+ cmd->cmd.runtest->num_cycles,
+ cmd->cmd.runtest->end_state);
+
+ tap_state_t tmp_state = tap_get_end_state();
+
+ if (tap_get_state() != TAP_IDLE) {
+ tap_set_end_state(TAP_IDLE);
+ err = xlnx_pcie_xvc_execute_statemove(0);
+ if (err != ERROR_OK)
+ return err;
+ };
+
+ size_t left = cmd->cmd.runtest->num_cycles;
+ size_t write;
+
+ while (left) {
+ write = MIN(XLNX_XVC_MAX_BITS, left);
+ err = xlnx_pcie_xvc_transact(write, 0, 0, NULL);
+ if (err != ERROR_OK)
+ return err;
+ left -= write;
+ };
+
+ tap_set_end_state(tmp_state);
+ if (tap_get_state() != tap_get_end_state())
+ err = xlnx_pcie_xvc_execute_statemove(0);
+
+ return err;
+}
+
+static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
+{
+ size_t num_states = cmd->cmd.pathmove->num_states;
+ tap_state_t *path = cmd->cmd.pathmove->path;
+ int err = ERROR_OK;
+ size_t i;
+
+ LOG_DEBUG("pathmove: %i states, end in %i",
+ cmd->cmd.pathmove->num_states,
+ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+
+ for (i = 0; i < num_states; i++) {
+ if (path[i] == tap_state_transition(tap_get_state(), false)) {
+ err = xlnx_pcie_xvc_transact(1, 1, 0, NULL);
+ } else if (path[i] == tap_state_transition(tap_get_state(), true)) {
+ err = xlnx_pcie_xvc_transact(1, 0, 0, NULL);
+ } else {
+ LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.",
+ tap_state_name(tap_get_state()),
+ tap_state_name(path[i]));
+ err = ERROR_JTAG_QUEUE_FAILED;
+ }
+ if (err != ERROR_OK)
+ return err;
+ tap_set_state(path[i]);
+ }
+
+ tap_set_end_state(tap_get_state());
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
+{
+ enum scan_type type = jtag_scan_type(cmd->cmd.scan);
+ tap_state_t saved_end_state = cmd->cmd.scan->end_state;
+ bool ir_scan = cmd->cmd.scan->ir_scan;
+ uint32_t tdi, tms, tdo;
+ uint8_t *buf, *rd_ptr;
+ int err, scan_size;
+ size_t write;
+ size_t left;
+
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buf);
+ rd_ptr = buf;
+ LOG_DEBUG("%s scan type %d %d bits; starts in %s end in %s",
+ (cmd->cmd.scan->ir_scan) ? "IR" : "DR", type, scan_size,
+ tap_state_name(tap_get_state()),
+ tap_state_name(cmd->cmd.scan->end_state));
+
+ /* If we're in TAP_DR_SHIFT state but need to do a IR_SCAN or
+ * vice-versa, do a statemove to corresponding other state, then restore
+ * end state
+ */
+ if (ir_scan && tap_get_state() != TAP_IRSHIFT) {
+ tap_set_end_state(TAP_IRSHIFT);
+ err = xlnx_pcie_xvc_execute_statemove(0);
+ if (err != ERROR_OK)
+ goto out_err;
+ tap_set_end_state(saved_end_state);
+ } else if (!ir_scan && (tap_get_state() != TAP_DRSHIFT)) {
+ tap_set_end_state(TAP_DRSHIFT);
+ err = xlnx_pcie_xvc_execute_statemove(0);
+ if (err != ERROR_OK)
+ goto out_err;
+ tap_set_end_state(saved_end_state);
+ }
+
+ left = scan_size;
+ while (left) {
+ write = MIN(XLNX_XVC_MAX_BITS, left);
+ /* the last TMS should be a 1, to leave the state */
+ tms = left <= XLNX_XVC_MAX_BITS ? BIT(write - 1) : 0;
+ tdi = (type != SCAN_IN) ? buf_get_u32(rd_ptr, 0, write) : 0;
+ err = xlnx_pcie_xvc_transact(write, tms, tdi, type != SCAN_OUT ?
+ &tdo : NULL);
+ if (err != ERROR_OK)
+ goto out_err;
+ left -= write;
+ if (type != SCAN_OUT)
+ buf_set_u32(rd_ptr, 0, write, tdo);
+ rd_ptr += sizeof(uint32_t);
+ };
+
+ err = jtag_read_buffer(buf, cmd->cmd.scan);
+ if (buf)
+ free(buf);
+
+ if (tap_get_state() != tap_get_end_state())
+ err = xlnx_pcie_xvc_execute_statemove(1);
+
+ return err;
+
+out_err:
+ if (buf)
+ free(buf);
+ return err;
+}
+
+static void xlnx_pcie_xvc_execute_reset(struct jtag_command *cmd)
+{
+ LOG_DEBUG("reset trst: %i srst: %i", cmd->cmd.reset->trst,
+ cmd->cmd.reset->srst);
+}
+
+static void xlnx_pcie_xvc_execute_sleep(struct jtag_command *cmd)
+{
+ LOG_DEBUG("sleep %" PRIi32 "", cmd->cmd.sleep->us);
+ usleep(cmd->cmd.sleep->us);
+}
+
+static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
+{
+ const size_t num_bits = cmd->cmd.tms->num_bits;
+ const uint8_t *bits = cmd->cmd.tms->bits;
+ size_t left, write;
+ uint32_t tms;
+ int err;
+
+ LOG_DEBUG("execute tms %zu", num_bits);
+
+ left = num_bits;
+ while (left) {
+ write = MIN(XLNX_XVC_MAX_BITS, left);
+ tms = buf_get_u32(bits, 0, write);
+ err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
+ if (err != ERROR_OK)
+ return err;
+ left -= write;
+ bits += 4;
+ };
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd)
+{
+ LOG_DEBUG("%s: cmd->type: %u", __func__, cmd->type);
+ switch (cmd->type) {
+ case JTAG_STABLECLOCKS:
+ return xlnx_pcie_xvc_execute_stableclocks(cmd);
+ case JTAG_RUNTEST:
+ return xlnx_pcie_xvc_execute_runtest(cmd);
+ case JTAG_TLR_RESET:
+ tap_set_end_state(cmd->cmd.statemove->end_state);
+ return xlnx_pcie_xvc_execute_statemove(0);
+ case JTAG_PATHMOVE:
+ return xlnx_pcie_xvc_execute_pathmove(cmd);
+ case JTAG_SCAN:
+ return xlnx_pcie_xvc_execute_scan(cmd);
+ case JTAG_RESET:
+ xlnx_pcie_xvc_execute_reset(cmd);
+ break;
+ case JTAG_SLEEP:
+ xlnx_pcie_xvc_execute_sleep(cmd);
+ break;
+ case JTAG_TMS:
+ return xlnx_pcie_xvc_execute_tms(cmd);
+ default:
+ LOG_ERROR("BUG: Unknown JTAG command type encountered.");
+ return ERROR_JTAG_QUEUE_FAILED;
+ }
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_execute_queue(void)
+{
+ struct jtag_command *cmd = jtag_command_queue;
+ int ret;
+
+ while (cmd) {
+ ret = xlnx_pcie_xvc_execute_command(cmd);
+
+ if (ret != ERROR_OK)
+ return ret;
+
+ cmd = cmd->next;
+ }
+
+ return ERROR_OK;
+}
+
+
+static int xlnx_pcie_xvc_init(void)
+{
+ char filename[PATH_MAX];
+ uint32_t cap, vh;
+ int err;
+
+ snprintf(filename, PATH_MAX, "/sys/bus/pci/devices/%s/config",
+ xlnx_pcie_xvc->device);
+ xlnx_pcie_xvc->fd = open(filename, O_RDWR | O_SYNC);
+ if (xlnx_pcie_xvc->fd < 0) {
+ LOG_ERROR("Failed to open device: %s", filename);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ LOG_INFO("Scanning PCIe device %s's for Xilinx XVC/PCIe ...",
+ xlnx_pcie_xvc->device);
+ /* Parse the PCIe extended capability list and try to find
+ * vendor specific header */
+ xlnx_pcie_xvc->offset = PCIE_EXT_CAP_LST;
+ while (xlnx_pcie_xvc->offset <= PCI_CFG_SPACE_EXP_SIZE - sizeof(cap) &&
+ xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) {
+ err = xlnx_pcie_xvc_read_reg(XLNX_XVC_EXT_CAP, &cap);
+ if (err != ERROR_OK)
+ return err;
+ LOG_DEBUG("Checking capability at 0x%x; id=0x%04x version=0x%x next=0x%x",
+ xlnx_pcie_xvc->offset,
+ PCI_EXT_CAP_ID(cap),
+ PCI_EXT_CAP_VER(cap),
+ PCI_EXT_CAP_NEXT(cap));
+ if (PCI_EXT_CAP_ID(cap) == PCI_EXT_CAP_ID_VNDR) {
+ err = xlnx_pcie_xvc_read_reg(XLNX_XVC_VSEC_HDR, &vh);
+ if (err != ERROR_OK)
+ return err;
+ LOG_DEBUG("Checking possible match at 0x%x; id: 0x%x; rev: 0x%x; length: 0x%x",
+ xlnx_pcie_xvc->offset,
+ PCI_VNDR_HEADER_ID(vh),
+ PCI_VNDR_HEADER_REV(vh),
+ PCI_VNDR_HEADER_LEN(vh));
+ if ((PCI_VNDR_HEADER_ID(vh) == XLNX_XVC_VSEC_ID) &&
+ (PCI_VNDR_HEADER_LEN(vh) == XLNX_XVC_CAP_SIZE))
+ break;
+ }
+ xlnx_pcie_xvc->offset = PCI_EXT_CAP_NEXT(cap);
+ }
+ if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_XVC_CAP_SIZE) ||
+ xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) {
+ close(xlnx_pcie_xvc->fd);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ LOG_INFO("Found Xilinx XVC/PCIe capability at offset: 0x%x", xlnx_pcie_xvc->offset);
+
+ return ERROR_OK;
+}
+
+static int xlnx_pcie_xvc_quit(void)
+{
+ int err;
+
+ err = close(xlnx_pcie_xvc->fd);
+ if (err)
+ return err;
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(xlnx_pcie_xvc_handle_config_command)
+{
+ if (CMD_ARGC < 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ /* we can't really free this in a safe manner, so at least
+ * limit the memory we're leaking by freeing the old one first
+ * before allocating a new one ...
+ */
+ if (xlnx_pcie_xvc->device)
+ free(xlnx_pcie_xvc->device);
+
+ xlnx_pcie_xvc->device = strdup(CMD_ARGV[0]);
+ return ERROR_OK;
+}
+
+static const struct command_registration xlnx_pcie_xvc_command_handlers[] = {
+ {
+ .name = "xlnx_pcie_xvc_config",
+ .handler = xlnx_pcie_xvc_handle_config_command,
+ .mode = COMMAND_CONFIG,
+ .help = "Configure XVC/PCIe JTAG adapter",
+ .usage = "device",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static struct jtag_interface xlnx_pcie_xvc_interface = {
+ .execute_queue = &xlnx_pcie_xvc_execute_queue,
+};
+
+struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
+ .name = "xlnx_pcie_xvc",
+ .transports = jtag_only,
+ .commands = xlnx_pcie_xvc_command_handlers,
+
+ .init = &xlnx_pcie_xvc_init,
+ .quit = &xlnx_pcie_xvc_quit,
+
+ .jtag_ops = &xlnx_pcie_xvc_interface,
+};
diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c
index 2abed21..6d5cdc5 100644
--- a/src/jtag/hla/hla_interface.c
+++ b/src/jtag/hla/hla_interface.c
@@ -35,7 +35,7 @@
#include <target/target.h>
-static struct hl_interface_s hl_if = { {0, 0, { 0 }, { 0 }, 0, HL_TRANSPORT_UNKNOWN, false, -1}, 0, 0 };
+static struct hl_interface_s hl_if = { {0, 0, { 0 }, { 0 }, HL_TRANSPORT_UNKNOWN, false, -1}, 0, 0 };
int hl_interface_open(enum hl_transports tr)
{
@@ -127,22 +127,19 @@ static int hl_interface_quit(void)
return ERROR_OK;
}
-static int hl_interface_execute_queue(void)
+static int hl_interface_reset(int req_trst, int req_srst)
{
- LOG_DEBUG("hl_interface_execute_queue: ignored");
-
- return ERROR_OK;
+ return hl_if.layout->api->assert_srst(hl_if.handle, req_srst ? 0 : 1);
}
int hl_interface_init_reset(void)
{
- /* incase the adapter has not already handled asserting srst
+ /* in case the adapter has not already handled asserting srst
* we will attempt it again */
if (hl_if.param.connect_under_reset) {
- jtag_add_reset(0, 1);
- hl_if.layout->api->assert_srst(hl_if.handle, 0);
+ adapter_assert_reset();
} else {
- jtag_add_reset(0, 0);
+ adapter_deassert_reset();
}
return ERROR_OK;
@@ -192,11 +189,12 @@ int hl_interface_override_target(const char **targetname)
}
int hl_interface_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
+ uint32_t port_size, unsigned int *trace_freq,
+ unsigned int traceclkin_freq, uint16_t *prescaler)
{
if (hl_if.layout->api->config_trace)
- return hl_if.layout->api->config_trace(hl_if.handle, enabled, pin_protocol,
- port_size, trace_freq);
+ return hl_if.layout->api->config_trace(hl_if.handle, enabled,
+ pin_protocol, port_size, trace_freq, traceclkin_freq, prescaler);
else if (enabled) {
LOG_ERROR("The selected interface does not support tracing");
return ERROR_FAIL;
@@ -348,17 +346,19 @@ static const struct command_registration hl_interface_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct jtag_interface hl_interface = {
+struct adapter_driver hl_adapter_driver = {
.name = "hla",
- .supported = 0,
- .commands = hl_interface_command_handlers,
.transports = hl_transports,
+ .commands = hl_interface_command_handlers,
+
.init = hl_interface_init,
.quit = hl_interface_quit,
- .execute_queue = hl_interface_execute_queue,
+ .reset = hl_interface_reset,
.speed = &hl_interface_speed,
.khz = &hl_interface_khz,
.speed_div = &hl_interface_speed_div,
.config_trace = &hl_interface_config_trace,
.poll_trace = &hl_interface_poll_trace,
+
+ /* no ops for HLA, targets hla_target and stm8 intercept them all */
};
diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h
index 262025e..b6e4a8b 100644
--- a/src/jtag/hla/hla_interface.h
+++ b/src/jtag/hla/hla_interface.h
@@ -41,8 +41,6 @@ struct hl_interface_param_s {
/** List of recognised PIDs */
uint16_t pid[HLA_MAX_USB_IDS + 1];
/** */
- unsigned api;
- /** */
enum hl_transports transport;
/** */
bool connect_under_reset;
diff --git a/src/jtag/hla/hla_layout.h b/src/jtag/hla/hla_layout.h
index 9f41b59..1d759e1 100644
--- a/src/jtag/hla/hla_layout.h
+++ b/src/jtag/hla/hla_layout.h
@@ -91,8 +91,10 @@ struct hl_layout_api_s {
* its maximum supported rate there
* @returns ERROR_OK on success, an error code on failure.
*/
- int (*config_trace)(void *handle, bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq);
+ int (*config_trace)(void *handle, bool enabled,
+ enum tpiu_pin_protocol pin_protocol, uint32_t port_size,
+ unsigned int *trace_freq, unsigned int traceclkin_freq,
+ uint16_t *prescaler);
/**
* Poll for new trace data
*
diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c
index ddacea3..fbdddfd 100644
--- a/src/jtag/hla/hla_transport.c
+++ b/src/jtag/hla/hla_transport.c
@@ -175,8 +175,6 @@ static int hl_transport_init(struct command_context *cmd_ctx)
tr = HL_TRANSPORT_SWD;
else if (strcmp(transport->name, "hla_jtag") == 0)
tr = HL_TRANSPORT_JTAG;
- else if (strcmp(transport->name, "stlink_swim") == 0)
- tr = HL_TRANSPORT_SWIM;
int retval = hl_interface_open(tr);
@@ -218,26 +216,18 @@ static struct transport hl_jtag_transport = {
.override_target = hl_interface_override_target,
};
-static struct transport stlink_swim_transport = {
- .name = "stlink_swim",
- .select = hl_transport_select,
- .init = hl_transport_init,
-};
-
-const char *hl_transports[] = { "hla_swd", "hla_jtag", "stlink_swim", NULL };
+const char *hl_transports[] = { "hla_swd", "hla_jtag", NULL };
static void hl_constructor(void) __attribute__ ((constructor));
static void hl_constructor(void)
{
transport_register(&hl_swd_transport);
transport_register(&hl_jtag_transport);
- transport_register(&stlink_swim_transport);
}
bool transport_is_hla(void)
{
struct transport *t;
t = get_current_transport();
- return t == &hl_swd_transport || t == &hl_jtag_transport
- || t == &stlink_swim_transport;
+ return t == &hl_swd_transport || t == &hl_jtag_transport;
}
diff --git a/src/jtag/hla/hla_transport.h b/src/jtag/hla/hla_transport.h
index 07eb751..0e0bea2 100644
--- a/src/jtag/hla/hla_transport.h
+++ b/src/jtag/hla/hla_transport.h
@@ -26,7 +26,6 @@ enum hl_transports {
HL_TRANSPORT_UNKNOWN = 0,
HL_TRANSPORT_SWD,
HL_TRANSPORT_JTAG,
- HL_TRANSPORT_SWIM
};
#endif /* OPENOCD_JTAG_HLA_HLA_TRANSPORT_H */
diff --git a/src/jtag/interface.c b/src/jtag/interface.c
index de132bb..56bbf6e 100644
--- a/src/jtag/interface.c
+++ b/src/jtag/interface.c
@@ -45,7 +45,7 @@ void tap_set_state_impl(tap_state_t new_state)
state_follower = new_state;
}
-tap_state_t tap_get_state()
+tap_state_t tap_get_state(void)
{
return state_follower;
}
@@ -64,7 +64,7 @@ void tap_set_end_state(tap_state_t new_end_state)
end_state_follower = new_end_state;
}
-tap_state_t tap_get_end_state()
+tap_state_t tap_get_end_state(void)
{
return end_state_follower;
}
diff --git a/src/jtag/interface.h b/src/jtag/interface.h
index 905f1eb..42598c1 100644
--- a/src/jtag/interface.h
+++ b/src/jtag/interface.h
@@ -26,6 +26,7 @@
#define OPENOCD_JTAG_INTERFACE_H
#include <jtag/jtag.h>
+#include <jtag/swim.h>
#include <target/armv7m_trace.h>
/* @file
@@ -192,32 +193,34 @@ static inline tap_state_t jtag_debug_state_machine(const void *tms_buf,
* debugging interface.
*/
struct jtag_interface {
- /** The name of the JTAG interface driver. */
- const char * const name;
-
/**
* Bit vector listing capabilities exposed by this driver.
*/
unsigned supported;
#define DEBUG_CAP_TMS_SEQ (1 << 0)
- /** transports supported in C code (NULL terminated vector) */
- const char * const *transports;
-
- const struct swd_driver *swd;
-
/**
* Execute queued commands.
* @returns ERROR_OK on success, or an error code on failure.
*/
int (*execute_queue)(void);
+};
- /**
- * Set the interface speed.
- * @param speed The new interface speed setting.
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*speed)(int speed);
+/**
+ * Represents a driver for a debugging interface
+ *
+ * @todo We need a per-instance structure too, and changes to pass
+ * that structure to the driver. Instances can for example be in
+ * either SWD or JTAG modes. This will help remove globals, and
+ * eventually to cope with systems which have more than one such
+ * debugging interface.
+ */
+struct adapter_driver {
+ /** The name of the interface driver. */
+ const char * const name;
+
+ /** transports supported in C code (NULL terminated vector) */
+ const char * const *transports;
/**
* The interface driver may register additional commands to expose
@@ -247,6 +250,29 @@ struct jtag_interface {
int (*quit)(void);
/**
+ * Control (assert/deassert) the signals SRST and TRST on the interface.
+ * This function is synchronous and should be called after the adapter
+ * queue has been properly flushed.
+ * This function is optional.
+ * Adapters that don't support resets can either not define this function
+ * or return an error code.
+ * Adapters that don't support one of the two reset should ignore the
+ * request to assert the missing signal and eventually log an error.
+ *
+ * @param srst 1 to assert SRST, 0 to deassert SRST.
+ * @param trst 1 to assert TRST, 0 to deassert TRST.
+ * @returns ERROR_OK on success, or an error code on failure.
+ */
+ int (*reset)(int srst, int trst);
+
+ /**
+ * Set the interface speed.
+ * @param speed The new interface speed setting.
+ * @returns ERROR_OK on success, or an error code on failure.
+ */
+ int (*speed)(int speed);
+
+ /**
* Returns JTAG maxium speed for KHz. 0 = RTCK. The function returns
* a failure if it can't support the KHz/RTCK.
*
@@ -303,10 +329,14 @@ struct jtag_interface {
* @param trace_freq A pointer to the configured trace
* frequency; if it points to 0, the adapter driver must write
* its maximum supported rate there
+ * @param traceclkin_freq TRACECLKIN frequency provided to the TPIU in Hz
+ * @param prescaler Pointer to the SWO prescaler calculated by the
+ * adapter
* @returns ERROR_OK on success, an error code on failure.
*/
int (*config_trace)(bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq);
+ uint32_t port_size, unsigned int *trace_freq,
+ unsigned int traceclkin_freq, uint16_t *prescaler);
/**
* Poll for new trace data
@@ -318,14 +348,31 @@ struct jtag_interface {
* @returns ERROR_OK on success, an error code on failure.
*/
int (*poll_trace)(uint8_t *buf, size_t *size);
+
+ /** Low-level JTAG APIs */
+ struct jtag_interface *jtag_ops;
+
+ /** Low-level SWD APIs */
+ const struct swd_driver *swd_ops;
+
+ /* DAP APIs over JTAG transport */
+ const struct dap_ops *dap_jtag_ops;
+
+ /* DAP APIs over SWD transport */
+ const struct dap_ops *dap_swd_ops;
+
+ /* SWIM APIs */
+ const struct swim_driver *swim_ops;
};
extern const char * const jtag_only[];
-void adapter_assert_reset(void);
-void adapter_deassert_reset(void);
+int adapter_resets(int assert_trst, int assert_srst);
+int adapter_assert_reset(void);
+int adapter_deassert_reset(void);
int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq);
+ uint32_t port_size, unsigned int *trace_freq,
+ unsigned int traceclkin_freq, uint16_t *prescaler);
int adapter_poll_trace(uint8_t *buf, size_t *size);
#endif /* OPENOCD_JTAG_INTERFACE_H */
diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
index 286a73a..7d3f8a8 100644
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -34,106 +34,115 @@
/** @file
* This file includes declarations for all built-in jtag interfaces,
- * which are then listed in the jtag_interfaces array.
+ * which are then listed in the adapter_drivers array.
*
* Dynamic loading can be implemented be searching for shared libraries
- * that contain a jtag_interface structure that can added to this list.
+ * that contain an adapter_driver structure that can added to this list.
*/
#if BUILD_ZY1000 == 1
-extern struct jtag_interface zy1000_interface;
+extern struct adapter_driver zy1000_adapter_driver;
#elif defined(BUILD_MINIDRIVER_DUMMY)
-extern struct jtag_interface minidummy_interface;
+extern struct adapter_driver minidummy_adapter_driver;
#else /* standard drivers */
#if BUILD_PARPORT == 1
-extern struct jtag_interface parport_interface;
+extern struct adapter_driver parport_adapter_driver;
#endif
#if BUILD_DUMMY == 1
-extern struct jtag_interface dummy_interface;
+extern struct adapter_driver dummy_adapter_driver;
#endif
#if BUILD_FTDI == 1
-extern struct jtag_interface ftdi_interface;
+extern struct adapter_driver ftdi_adapter_driver;
#endif
#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1
-extern struct jtag_interface usb_blaster_interface;
+extern struct adapter_driver usb_blaster_adapter_driver;
#endif
#if BUILD_JTAG_VPI == 1
-extern struct jtag_interface jtag_vpi_interface;
+extern struct adapter_driver jtag_vpi_adapter_driver;
#endif
#if BUILD_FT232R == 1
-extern struct jtag_interface ft232r_interface;
+extern struct adapter_driver ft232r_adapter_driver;
#endif
#if BUILD_AMTJTAGACCEL == 1
-extern struct jtag_interface amt_jtagaccel_interface;
+extern struct adapter_driver amt_jtagaccel_adapter_driver;
#endif
#if BUILD_EP93XX == 1
-extern struct jtag_interface ep93xx_interface;
+extern struct adapter_driver ep93xx_adapter_driver;
#endif
#if BUILD_AT91RM9200 == 1
-extern struct jtag_interface at91rm9200_interface;
+extern struct adapter_driver at91rm9200_adapter_driver;
#endif
#if BUILD_GW16012 == 1
-extern struct jtag_interface gw16012_interface;
+extern struct adapter_driver gw16012_adapter_driver;
#endif
#if BUILD_PRESTO
-extern struct jtag_interface presto_interface;
+extern struct adapter_driver presto_adapter_driver;
#endif
#if BUILD_USBPROG == 1
-extern struct jtag_interface usbprog_interface;
+extern struct adapter_driver usbprog_adapter_driver;
#endif
#if BUILD_OPENJTAG == 1
-extern struct jtag_interface openjtag_interface;
+extern struct adapter_driver openjtag_adapter_driver;
#endif
#if BUILD_JLINK == 1
-extern struct jtag_interface jlink_interface;
+extern struct adapter_driver jlink_adapter_driver;
#endif
#if BUILD_VSLLINK == 1
-extern struct jtag_interface vsllink_interface;
+extern struct adapter_driver vsllink_adapter_driver;
#endif
#if BUILD_RLINK == 1
-extern struct jtag_interface rlink_interface;
+extern struct adapter_driver rlink_adapter_driver;
#endif
#if BUILD_ULINK == 1
-extern struct jtag_interface ulink_interface;
+extern struct adapter_driver ulink_adapter_driver;
#endif
#if BUILD_ARMJTAGEW == 1
-extern struct jtag_interface armjtagew_interface;
+extern struct adapter_driver armjtagew_adapter_driver;
#endif
#if BUILD_BUSPIRATE == 1
-extern struct jtag_interface buspirate_interface;
+extern struct adapter_driver buspirate_adapter_driver;
#endif
#if BUILD_REMOTE_BITBANG == 1
-extern struct jtag_interface remote_bitbang_interface;
+extern struct adapter_driver remote_bitbang_adapter_driver;
#endif
#if BUILD_HLADAPTER == 1
-extern struct jtag_interface hl_interface;
+extern struct adapter_driver hl_adapter_driver;
#endif
#if BUILD_OSBDM == 1
-extern struct jtag_interface osbdm_interface;
+extern struct adapter_driver osbdm_adapter_driver;
#endif
#if BUILD_OPENDOUS == 1
-extern struct jtag_interface opendous_interface;
+extern struct adapter_driver opendous_adapter_driver;
#endif
#if BUILD_SYSFSGPIO == 1
-extern struct jtag_interface sysfsgpio_interface;
+extern struct adapter_driver sysfsgpio_adapter_driver;
+#endif
+#if BUILD_XLNX_PCIE_XVC == 1
+extern struct adapter_driver xlnx_pcie_xvc_adapter_driver;
#endif
#if BUILD_AICE == 1
-extern struct jtag_interface aice_interface;
+extern struct adapter_driver aice_adapter_driver;
#endif
#if BUILD_BCM2835GPIO == 1
-extern struct jtag_interface bcm2835gpio_interface;
+extern struct adapter_driver bcm2835gpio_adapter_driver;
#endif
#if BUILD_CMSIS_DAP == 1
-extern struct jtag_interface cmsis_dap_interface;
+extern struct adapter_driver cmsis_dap_adapter_driver;
#endif
#if BUILD_KITPROG == 1
-extern struct jtag_interface kitprog_interface;
+extern struct adapter_driver kitprog_adapter_driver;
#endif
#if BUILD_IMX_GPIO == 1
-extern struct jtag_interface imx_gpio_interface;
+extern struct adapter_driver imx_gpio_adapter_driver;
#endif
#if BUILD_XDS110 == 1
-extern struct jtag_interface xds110_interface;
+extern struct adapter_driver xds110_adapter_driver;
+#endif
+#if BUILD_HLADAPTER == 1
+extern struct adapter_driver stlink_dap_adapter_driver;
+#endif
+#if BUILD_RSHIM == 1
+extern struct adapter_driver rshim_dap_adapter_driver;
#endif
#endif /* standard drivers */
@@ -144,107 +153,111 @@ extern struct jtag_interface xds110_interface;
* The list should be defined to contain either one minidriver interface
* or some number of standard driver interfaces, never both.
*/
-struct jtag_interface *jtag_interfaces[] = {
+struct adapter_driver *adapter_drivers[] = {
#if BUILD_ZY1000 == 1
- &zy1000_interface,
+ &zy1000_adapter_driver,
#elif defined(BUILD_MINIDRIVER_DUMMY)
- &minidummy_interface,
+ &minidummy_adapter_driver,
#else /* standard drivers */
#if BUILD_PARPORT == 1
- &parport_interface,
+ &parport_adapter_driver,
#endif
#if BUILD_DUMMY == 1
- &dummy_interface,
+ &dummy_adapter_driver,
#endif
#if BUILD_FTDI == 1
- &ftdi_interface,
+ &ftdi_adapter_driver,
#endif
#if BUILD_USB_BLASTER || BUILD_USB_BLASTER_2 == 1
- &usb_blaster_interface,
+ &usb_blaster_adapter_driver,
#endif
#if BUILD_JTAG_VPI == 1
- &jtag_vpi_interface,
+ &jtag_vpi_adapter_driver,
#endif
#if BUILD_FT232R == 1
- &ft232r_interface,
+ &ft232r_adapter_driver,
#endif
#if BUILD_AMTJTAGACCEL == 1
- &amt_jtagaccel_interface,
+ &amt_jtagaccel_adapter_driver,
#endif
#if BUILD_EP93XX == 1
- &ep93xx_interface,
+ &ep93xx_adapter_driver,
#endif
#if BUILD_AT91RM9200 == 1
- &at91rm9200_interface,
+ &at91rm9200_adapter_driver,
#endif
#if BUILD_GW16012 == 1
- &gw16012_interface,
+ &gw16012_adapter_driver,
#endif
#if BUILD_PRESTO
- &presto_interface,
+ &presto_adapter_driver,
#endif
#if BUILD_USBPROG == 1
- &usbprog_interface,
+ &usbprog_adapter_driver,
#endif
#if BUILD_OPENJTAG == 1
- &openjtag_interface,
+ &openjtag_adapter_driver,
#endif
#if BUILD_JLINK == 1
- &jlink_interface,
+ &jlink_adapter_driver,
#endif
#if BUILD_VSLLINK == 1
- &vsllink_interface,
+ &vsllink_adapter_driver,
#endif
#if BUILD_RLINK == 1
- &rlink_interface,
+ &rlink_adapter_driver,
#endif
#if BUILD_ULINK == 1
- &ulink_interface,
+ &ulink_adapter_driver,
#endif
#if BUILD_ARMJTAGEW == 1
- &armjtagew_interface,
+ &armjtagew_adapter_driver,
#endif
#if BUILD_BUSPIRATE == 1
- &buspirate_interface,
+ &buspirate_adapter_driver,
#endif
#if BUILD_REMOTE_BITBANG == 1
- &remote_bitbang_interface,
+ &remote_bitbang_adapter_driver,
#endif
#if BUILD_HLADAPTER == 1
- &hl_interface,
+ &hl_adapter_driver,
#endif
#if BUILD_OSBDM == 1
- &osbdm_interface,
+ &osbdm_adapter_driver,
#endif
#if BUILD_OPENDOUS == 1
- &opendous_interface,
+ &opendous_adapter_driver,
#endif
#if BUILD_SYSFSGPIO == 1
- &sysfsgpio_interface,
+ &sysfsgpio_adapter_driver,
+#endif
+#if BUILD_XLNX_PCIE_XVC == 1
+ &xlnx_pcie_xvc_adapter_driver,
#endif
#if BUILD_AICE == 1
- &aice_interface,
+ &aice_adapter_driver,
#endif
#if BUILD_BCM2835GPIO == 1
- &bcm2835gpio_interface,
+ &bcm2835gpio_adapter_driver,
#endif
#if BUILD_CMSIS_DAP == 1
- &cmsis_dap_interface,
+ &cmsis_dap_adapter_driver,
#endif
#if BUILD_KITPROG == 1
- &kitprog_interface,
+ &kitprog_adapter_driver,
#endif
#if BUILD_IMX_GPIO == 1
- &imx_gpio_interface,
+ &imx_gpio_adapter_driver,
#endif
#if BUILD_XDS110 == 1
- &xds110_interface,
+ &xds110_adapter_driver,
+#endif
+#if BUILD_HLADAPTER == 1
+ &stlink_dap_adapter_driver,
+#endif
+#if BUILD_RSHIM == 1
+ &rshim_dap_adapter_driver,
#endif
#endif /* standard drivers */
NULL,
};
-
-void jtag_interface_modules_load(const char *path)
-{
- /* @todo: implement dynamic module loading for JTAG interface drivers */
-}
diff --git a/src/jtag/interfaces.h b/src/jtag/interfaces.h
index 02d201b..ddbd735 100644
--- a/src/jtag/interfaces.h
+++ b/src/jtag/interfaces.h
@@ -36,9 +36,6 @@
#include <jtag/interface.h>
-/** Dynamically load all JTAG interface modules from specified directory. */
-void jtag_interface_modules_load(const char *path);
-
-extern struct jtag_interface *jtag_interfaces[];
+extern struct adapter_driver *adapter_drivers[];
#endif /* OPENOCD_JTAG_INTERFACES_H */
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index c93243c..7f033e0 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -77,6 +77,14 @@ typedef enum tap_state {
} tap_state_t;
/**
+ * Defines arguments for reset functions
+ */
+#define SRST_DEASSERT 0
+#define SRST_ASSERT 1
+#define TRST_DEASSERT 0
+#define TRST_ASSERT 1
+
+/**
* Function tap_state_name
* Returns a string suitable for display representing the JTAG tap_state
*/
@@ -154,8 +162,8 @@ void jtag_tap_free(struct jtag_tap *tap);
struct jtag_tap *jtag_all_taps(void);
const char *jtag_tap_name(const struct jtag_tap *tap);
-struct jtag_tap *jtag_tap_by_string(const char* dotted_name);
-struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp* interp, Jim_Obj *obj);
+struct jtag_tap *jtag_tap_by_string(const char *dotted_name);
+struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *obj);
struct jtag_tap *jtag_tap_by_position(unsigned abs_position);
struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p);
unsigned jtag_tap_count_enabled(void);
diff --git a/src/jtag/minidummy/minidummy.c b/src/jtag/minidummy/minidummy.c
index 2f26004..7ee2067 100644
--- a/src/jtag/minidummy/minidummy.c
+++ b/src/jtag/minidummy/minidummy.c
@@ -24,18 +24,24 @@
#include <jtag/minidriver.h>
#include <jtag/interface.h>
-struct jtag_interface minidummy_interface = {
- .name = "minidummy",
+static struct jtag_interface minidummy_interface = {
.execute_queue = NULL,
- .speed = NULL,
+};
+
+struct adapter_driver minidummy_adapter_driver = {
+ .name = "minidummy",
.transports = jtag_only,
.commands = NULL,
+
.init = NULL,
.quit = NULL,
+ .speed = NULL,
.khz = NULL,
.speed_div = NULL,
.power_dropout = NULL,
.srst_asserted = NULL,
+
+ .jtag_ops = &minidummy_interface,
};
int interface_jtag_execute_queue(void)
@@ -77,7 +83,7 @@ int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits,
return ERROR_OK;
}
-int interface_jtag_add_tlr()
+int interface_jtag_add_tlr(void)
{
/* synchronously do the operation here */
@@ -164,7 +170,7 @@ void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *bu
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, uint32_t opcode,
uint32_t *data, size_t count)
{
- int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap, \
+ int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap,
uint32_t opcode, uint32_t *data, size_t count);
return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
}
diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl
index d57cafb..f8c4ca0 100644
--- a/src/jtag/startup.tcl
+++ b/src/jtag/startup.tcl
@@ -34,16 +34,16 @@ proc init_reset { mode } {
proc power_restore {} {
echo "Sensed power restore, running reset init and halting GDB."
reset init
-
+
# Halt GDB so user can deal with a detected power restore.
#
# After GDB is halted, then output is no longer forwarded
# to the GDB console.
- set targets [target names]
+ set targets [target names]
foreach t $targets {
# New event script.
$t invoke-event arp_halt_gdb
- }
+ }
}
add_help_text power_restore "Overridable procedure run when power restore is detected. Runs 'reset init' by default."
@@ -65,11 +65,11 @@ proc srst_deasserted {} {
#
# After GDB is halted, then output is no longer forwarded
# to the GDB console.
- set targets [target names]
+ set targets [target names]
foreach t $targets {
# New event script.
$t invoke-event arp_halt_gdb
- }
+ }
}
add_help_text srst_deasserted "Overridable procedure run when srst deassert is detected. Runs 'reset init' by default."
@@ -120,18 +120,34 @@ proc jtag_ntrst_assert_width args {
# FIXME phase these aids out after about April 2011
#
proc jtag_khz args {
- echo "DEPRECATED! use 'adapter_khz' not 'jtag_khz'"
- eval adapter_khz $args
+ echo "DEPRECATED! use 'adapter speed' not 'jtag_khz'"
+ eval adapter speed $args
}
proc jtag_nsrst_delay args {
- echo "DEPRECATED! use 'adapter_nsrst_delay' not 'jtag_nsrst_delay'"
- eval adapter_nsrst_delay $args
+ echo "DEPRECATED! use 'adapter srst delay' not 'jtag_nsrst_delay'"
+ eval adapter srst delay $args
}
proc jtag_nsrst_assert_width args {
- echo "DEPRECATED! use 'adapter_nsrst_assert_width' not 'jtag_nsrst_assert_width'"
- eval adapter_nsrst_assert_width $args
+ echo "DEPRECATED! use 'adapter srst pulse_width' not 'jtag_nsrst_assert_width'"
+ eval adapter srst pulse_width $args
+}
+
+proc jtag_reset args {
+ echo "DEPRECATED! use 'adapter \[de\]assert' not 'jtag_reset'"
+ switch $args {
+ "0 0"
+ {eval adapter deassert trst deassert srst}
+ "0 1"
+ {eval adapter deassert trst assert srst}
+ "1 0"
+ {eval adapter assert trst deassert srst}
+ "1 1"
+ {eval adapter assert trst assert srst}
+ default
+ {return -code 1 -level 1 "jtag_reset: syntax error"}
+ }
}
# stlink migration helpers
@@ -160,4 +176,54 @@ proc stlink args {
eval hla $args
}
+proc adapter_khz args {
+ echo "DEPRECATED! use 'adapter speed' not 'adapter_khz'"
+ eval adapter speed $args
+}
+
+proc adapter_name args {
+ echo "DEPRECATED! use 'adapter name' not 'adapter_name'"
+ eval adapter name $args
+}
+
+proc adapter_nsrst_delay args {
+ echo "DEPRECATED! use 'adapter srst delay' not 'adapter_nsrst_delay'"
+ eval adapter srst delay $args
+}
+
+proc adapter_nsrst_assert_width args {
+ echo "DEPRECATED! use 'adapter srst pulse_width' not 'adapter_nsrst_assert_width'"
+ eval adapter srst pulse_width $args
+}
+
+proc interface args {
+ echo "DEPRECATED! use 'adapter driver' not 'interface'"
+ eval adapter driver $args
+}
+
+proc interface_transports args {
+ echo "DEPRECATED! use 'adapter transports' not 'interface_transports'"
+ eval adapter transports $args
+}
+
+proc interface_list args {
+ echo "DEPRECATED! use 'adapter list' not 'interface_list'"
+ eval adapter list $args
+}
+
+proc ftdi_location args {
+ echo "DEPRECATED! use 'adapter usb location' not 'ftdi_location'"
+ eval adapter usb location $args
+}
+
+proc xds110_serial args {
+ echo "DEPRECATED! use 'xds110 serial' not 'xds110_serial'"
+ eval xds110 serial $args
+}
+
+proc xds110_supply_voltage args {
+ echo "DEPRECATED! use 'xds110 supply' not 'xds110_supply_voltage'"
+ eval xds110 supply $args
+}
+
# END MIGRATION AIDS
diff --git a/src/jtag/swd.h b/src/jtag/swd.h
index 0b32105..487cb85 100644
--- a/src/jtag/swd.h
+++ b/src/jtag/swd.h
@@ -213,14 +213,6 @@ static const uint8_t swd_seq_dormant_to_jtag[] = {
};
static const unsigned swd_seq_dormant_to_jtag_len = 160;
-enum swd_special_seq {
- LINE_RESET,
- JTAG_TO_SWD,
- SWD_TO_JTAG,
- SWD_TO_DORMANT,
- DORMANT_TO_SWD,
-};
-
struct swd_driver {
/**
* Initialize the debug link so it can perform SWD operations.
@@ -285,6 +277,5 @@ struct swd_driver {
};
int swd_init_reset(struct command_context *cmd_ctx);
-void swd_add_reset(int req_srst);
#endif /* OPENOCD_JTAG_SWD_H */
diff --git a/src/jtag/swim.c b/src/jtag/swim.c
new file mode 100644
index 0000000..936268b
--- /dev/null
+++ b/src/jtag/swim.c
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Copyright (C) 2020 by Antonio Borneo <borneo.antonio@gmail.com
+ *
+ * SWIM (Single Wire Interface Module) is a low-pin-count debug protocol
+ * used by STMicroelectronics MCU family STM8 and documented in UM470
+ * https://www.st.com/resource/en/user_manual/cd00173911.pdf
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "interface.h"
+#include "swim.h"
+#include <helper/command.h>
+#include <transport/transport.h>
+
+extern struct adapter_driver *adapter_driver;
+
+int swim_system_reset(void)
+{
+ assert(adapter_driver->swim_ops);
+
+ return adapter_driver->swim_ops->srst();
+}
+
+int swim_read_mem(uint32_t addr, uint32_t size, uint32_t count,
+ uint8_t *buffer)
+{
+ assert(adapter_driver->swim_ops);
+
+ return adapter_driver->swim_ops->read_mem(addr, size, count, buffer);
+}
+
+int swim_write_mem(uint32_t addr, uint32_t size, uint32_t count,
+ const uint8_t *buffer)
+{
+ assert(adapter_driver->swim_ops);
+
+ return adapter_driver->swim_ops->write_mem(addr, size, count, buffer);
+}
+
+int swim_reconnect(void)
+{
+ assert(adapter_driver->swim_ops);
+
+ return adapter_driver->swim_ops->reconnect();
+}
+
+COMMAND_HANDLER(handle_swim_newtap_command)
+{
+ struct jtag_tap *tap;
+
+ /*
+ * only need "basename" and "tap_type", but for backward compatibility
+ * ignore extra parameters
+ */
+ if (CMD_ARGC < 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ tap = calloc(1, sizeof(*tap));
+ if (!tap) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+
+ tap->chip = strdup(CMD_ARGV[0]);
+ tap->tapname = strdup(CMD_ARGV[1]);
+ tap->dotted_name = alloc_printf("%s.%s", CMD_ARGV[0], CMD_ARGV[1]);
+ if (!tap->chip || !tap->tapname || !tap->dotted_name) {
+ LOG_ERROR("Out of memory");
+ free(tap->dotted_name);
+ free(tap->tapname);
+ free(tap->chip);
+ free(tap);
+ return ERROR_FAIL;
+ }
+
+ LOG_DEBUG("Creating new SWIM \"tap\", Chip: %s, Tap: %s, Dotted: %s",
+ tap->chip, tap->tapname, tap->dotted_name);
+
+ /* default is enabled-after-reset */
+ tap->enabled = true;
+
+ jtag_tap_init(tap);
+ return ERROR_OK;
+}
+
+static const struct command_registration swim_transport_subcommand_handlers[] = {
+ {
+ .name = "newtap",
+ .handler = handle_swim_newtap_command,
+ .mode = COMMAND_CONFIG,
+ .help = "Create a new TAP instance named basename.tap_type, "
+ "and appends it to the scan chain.",
+ .usage = "basename tap_type",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration swim_transport_command_handlers[] = {
+ {
+ .name = "swim",
+ .mode = COMMAND_ANY,
+ .help = "perform swim adapter actions",
+ .usage = "",
+ .chain = swim_transport_subcommand_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static int swim_transport_select(struct command_context *cmd_ctx)
+{
+ LOG_DEBUG(__func__);
+
+ return register_commands(cmd_ctx, NULL, swim_transport_command_handlers);
+}
+
+static int swim_transport_init(struct command_context *cmd_ctx)
+{
+ enum reset_types jtag_reset_config = jtag_get_reset_config();
+
+ LOG_DEBUG(__func__);
+
+ if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
+ if (jtag_reset_config & RESET_SRST_NO_GATING)
+ adapter_assert_reset();
+ else
+ LOG_WARNING("\'srst_nogate\' reset_config option is required");
+ } else
+ adapter_deassert_reset();
+
+ return ERROR_OK;
+}
+
+static struct transport swim_transport = {
+ .name = "swim",
+ .select = swim_transport_select,
+ .init = swim_transport_init,
+};
+
+static void swim_constructor(void) __attribute__ ((constructor));
+static void swim_constructor(void)
+{
+ transport_register(&swim_transport);
+}
+
+bool transport_is_swim(void)
+{
+ return get_current_transport() == &swim_transport;
+}
diff --git a/src/jtag/swim.h b/src/jtag/swim.h
new file mode 100644
index 0000000..186e0cc
--- /dev/null
+++ b/src/jtag/swim.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Copyright (C) 2020 by Antonio Borneo <borneo.antonio@gmail.com
+ */
+
+/**
+ * @file
+ * This file implements support for STMicroelectronics debug protocol SWIM
+ * (Single Wire Interface Module).
+ */
+
+#ifndef OPENOCD_JTAG_SWIM_H
+#define OPENOCD_JTAG_SWIM_H
+
+#define SWIM_FREQ_LOW 363
+#define SWIM_FREQ_HIGH 800
+
+struct swim_driver {
+ /**
+ * Send SRST (system reset) command to target.
+ *
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*srst)(void);
+
+ /**
+ * Read target memory through ROTF (read on-the-fly) command.
+ *
+ * @param addr Start address to read data from target memory.
+ * @param size Size in bytes of data units, 1, 2 or 4.
+ * @param count Number of units (size units, not bytes) to read.
+ * @param buffer Data buffer to receive data.
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*read_mem)(uint32_t addr, uint32_t size, uint32_t count,
+ uint8_t *buffer);
+
+ /**
+ * Write target memory through WOTF (write on-the-fly) command.
+ *
+ * @param addr Start address to write data to target memory.
+ * @param size Size in bytes of data units, 1, 2 or 4.
+ * @param count Number of units (size units, not bytes) to write.
+ * @param buffer Data buffer to write.
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*write_mem)(uint32_t addr, uint32_t size, uint32_t count,
+ const uint8_t *buffer);
+
+ /**
+ * Reconnect to the target.
+ * Should be reworked to be more generic and not linked to current
+ * implementation in stlink driver.
+ *
+ * @return ERROR_OK on success, else a fault code.
+ */
+ int (*reconnect)(void);
+};
+
+int swim_system_reset(void);
+int swim_read_mem(uint32_t addr, uint32_t size, uint32_t count,
+ uint8_t *buffer);
+int swim_write_mem(uint32_t addr, uint32_t size, uint32_t count,
+ const uint8_t *buffer);
+int swim_reconnect(void);
+
+#endif /* OPENOCD_JTAG_SWIM_H */
diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
index cbdf2ad..d2f1f0d 100644
--- a/src/jtag/tcl.c
+++ b/src/jtag/tcl.c
@@ -108,7 +108,7 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
endstate = TAP_IDLE;
- script_debug(interp, "drscan", argc, args);
+ script_debug(interp, argc, args);
/* validate arguments as numbers */
e = JIM_OK;
@@ -229,7 +229,7 @@ static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_ERR;
}
- script_debug(interp, "pathmove", argc, args);
+ script_debug(interp, argc, args);
int i;
for (i = 0; i < argc-1; i++) {
@@ -261,7 +261,7 @@ static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *ar
static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args)
{
- script_debug(interp, "flush_count", argc, args);
+ script_debug(interp, argc, args);
Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count()));
@@ -965,7 +965,7 @@ COMMAND_HANDLER(handle_scan_chain_command)
while (tap) {
uint32_t expected, expected_mask, ii;
- snprintf(expected_id, sizeof expected_id, "0x%08x",
+ snprintf(expected_id, sizeof(expected_id), "0x%08x",
(unsigned)((tap->expected_ids_cnt > 0)
? tap->expected_ids[0]
: 0));
@@ -987,7 +987,7 @@ COMMAND_HANDLER(handle_scan_chain_command)
(unsigned int)(expected_mask));
for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
- snprintf(expected_id, sizeof expected_id, "0x%08x",
+ snprintf(expected_id, sizeof(expected_id), "0x%08x",
(unsigned) tap->expected_ids[ii]);
if (tap->ignore_version)
expected_id[2] = '*';
@@ -1059,34 +1059,6 @@ COMMAND_HANDLER(handle_jtag_rclk_command)
return retval;
}
-COMMAND_HANDLER(handle_jtag_reset_command)
-{
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int trst = -1;
- if (CMD_ARGV[0][0] == '1')
- trst = 1;
- else if (CMD_ARGV[0][0] == '0')
- trst = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int srst = -1;
- if (CMD_ARGV[1][0] == '1')
- srst = 1;
- else if (CMD_ARGV[1][0] == '0')
- srst = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (adapter_init(CMD_CTX) != ERROR_OK)
- return ERROR_JTAG_INIT_FAILED;
-
- jtag_add_reset(trst, srst);
- return jtag_execute_queue();
-}
-
COMMAND_HANDLER(handle_runtest_command)
{
if (CMD_ARGC != 1)
@@ -1157,14 +1129,19 @@ COMMAND_HANDLER(handle_irscan_command)
return ERROR_FAIL;
}
- int field_size = tap->ir_length;
- fields[i].num_bits = field_size;
- uint8_t *v = malloc(DIV_ROUND_UP(field_size, 8));
-
uint64_t value;
retval = parse_u64(CMD_ARGV[i * 2 + 1], &value);
if (ERROR_OK != retval)
goto error_return;
+
+ int field_size = tap->ir_length;
+ fields[i].num_bits = field_size;
+ uint8_t *v = calloc(1, DIV_ROUND_UP(field_size, 8));
+ if (!v) {
+ LOG_ERROR("Out of memory");
+ goto error_return;
+ }
+
buf_set_u64(v, 0, field_size, value);
fields[i].out_value = v;
fields[i].in_value = NULL;
@@ -1332,14 +1309,6 @@ static const struct command_registration jtag_command_handlers[] = {
.usage = ""
},
{
- .name = "jtag_reset",
- .handler = handle_jtag_reset_command,
- .mode = COMMAND_EXEC,
- .help = "Set reset line values. Value '1' is active, "
- "value '0' is inactive.",
- .usage = "trst_active srst_active",
- },
- {
.name = "runtest",
.handler = handle_runtest_command,
.mode = COMMAND_EXEC,
@@ -1350,7 +1319,7 @@ static const struct command_registration jtag_command_handlers[] = {
.name = "irscan",
.handler = handle_irscan_command,
.mode = COMMAND_EXEC,
- .help = "Execute Instruction Register (DR) scan. The "
+ .help = "Execute Instruction Register (IR) scan. The "
"specified opcodes are put into each TAP's IR, "
"and other TAPs are put in BYPASS.",
.usage = "[tap_name instruction]* ['-endstate' state_name]",
diff --git a/src/jtag/zy1000/zy1000.c b/src/jtag/zy1000/zy1000.c
index 1734983..37af2f7 100644
--- a/src/jtag/zy1000/zy1000.c
+++ b/src/jtag/zy1000/zy1000.c
@@ -486,7 +486,7 @@ int interface_jtag_add_plain_dr_scan(int num_bits,
return ERROR_OK;
}
-int interface_jtag_add_tlr()
+int interface_jtag_add_tlr(void)
{
setCurrentState(TAP_RESET);
return ERROR_OK;
@@ -1237,17 +1237,23 @@ int zy1000_init(void)
return ERROR_OK;
}
-struct jtag_interface zy1000_interface = {
- .name = "ZY1000",
+static struct jtag_interface zy1000_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = NULL,
- .speed = zy1000_speed,
+};
+
+struct adapter_driver zy1000_adapter_driver = {
+ .name = "ZY1000",
.transports = jtag_only,
.commands = zy1000_commands,
+
.init = zy1000_init,
.quit = zy1000_quit,
+ .speed = zy1000_speed,
.khz = zy1000_khz,
.speed_div = zy1000_speed_div,
.power_dropout = zy1000_power_dropout,
.srst_asserted = zy1000_srst_asserted,
+
+ .jtag_ops = &zy1000_interface,
};