aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO3
-rw-r--r--doc/openocd.texi24
-rw-r--r--src/jtag/core.c9
-rw-r--r--src/jtag/drivers/stlink_usb.c39
-rw-r--r--src/jtag/hla/hla_transport.c14
-rw-r--r--src/jtag/hla/hla_transport.h1
-rw-r--r--src/jtag/interface.h4
-rw-r--r--src/jtag/swim.c124
-rw-r--r--src/transport/transport.h1
-rw-r--r--tcl/interface/stlink-dap.cfg11
-rw-r--r--tcl/target/stm8l.cfg4
-rw-r--r--tcl/target/stm8s.cfg4
12 files changed, 197 insertions, 41 deletions
diff --git a/TODO b/TODO
index c73d772..ebb6c99 100644
--- a/TODO
+++ b/TODO
@@ -59,8 +59,7 @@ changes pending in gerrit.
- tap_set_state(TAP_RESET) is already done in src/jtag/core.c. No need
to replicate it in the drivers, apart in case the driver sets TRST
independently
-- separate SWIM from HLA and make it independent
-- add .hla_ops and .swim_ops to "adapter"
+- add .hla_ops to "adapter"
- HLA is a API level (.hla_ops). Transport should simply be {jtag,swd},
not {hla_jtag,hla_swd}.
diff --git a/doc/openocd.texi b/doc/openocd.texi
index ef77993..1ddf09f 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -3304,6 +3304,24 @@ The Serial Peripheral Interface (SPI) is a general purpose transport
which uses four wire signaling. Some processors use it as part of a
solution for flash programming.
+@anchor{swimtransport}
+@subsection SWIM Transport
+@cindex SWIM
+@cindex Single Wire Interface Module
+The Single Wire Interface Module (SWIM) is a low-pin-count debug protocol used
+by the STMicroelectronics MCU family STM8 and documented in the
+@uref{https://www.st.com/resource/en/user_manual/cd00173911.pdf, User Manual UM470}.
+
+SWIM does not support boundary scan testing nor multiple cores.
+
+The SWIM transport is selected with the command @command{transport select swim}.
+
+The concept of TAPs does not fit in the protocol since SWIM does not implement
+a scan chain. Nevertheless, the current SW model of OpenOCD requires defining a
+virtual SWIM TAP through the command @command{swim newtap basename tap_type}.
+The TAP definition must precede the target definition command
+@command{target create target_name stm8 -chain-position basename.tap_type}.
+
@anchor{jtagspeed}
@section JTAG Speed
JTAG clock setup is part of system setup.
@@ -9831,6 +9849,12 @@ This command is similar to @command{arc jtag get-aux-reg} but is for core
registers.
@end deffn
+@section STM8 Architecture
+@uref{http://st.com/stm8/, STM8} is a 8-bit microcontroller platform from
+STMicroelectronics, based on a proprietary 8-bit core architecture.
+
+OpenOCD supports debugging STM8 through the STMicroelectronics debug
+protocol SWIM, @pxref{swimtransport,,SWIM}.
@anchor{softwaredebugmessagesandtracing}
@section Software Debug Messages and Tracing
diff --git a/src/jtag/core.c b/src/jtag/core.c
index d83f195..1d424b2 100644
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -2027,7 +2027,8 @@ int adapter_resets(int trst, int srst)
jtag_execute_queue();
return ERROR_OK;
} else if (transport_is_swd() || transport_is_hla() ||
- transport_is_dapdirect_swd() || transport_is_dapdirect_jtag()) {
+ 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);
@@ -2060,7 +2061,8 @@ int adapter_assert_reset(void)
jtag_add_reset(0, 1);
return ERROR_OK;
} else if (transport_is_swd() || transport_is_hla() ||
- transport_is_dapdirect_jtag() || transport_is_dapdirect_swd())
+ 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",
@@ -2076,7 +2078,8 @@ int adapter_deassert_reset(void)
jtag_add_reset(0, 0);
return ERROR_OK;
} else if (transport_is_swd() || transport_is_hla() ||
- transport_is_dapdirect_jtag() || transport_is_dapdirect_swd())
+ 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",
diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index 485a95c..4c5081c 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -1288,8 +1288,6 @@ 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;
}
@@ -3546,6 +3544,28 @@ static void stlink_dap_op_quit(struct adiv5_dap *dap)
LOG_ERROR("Error closing APs");
}
+static int stlink_swim_op_srst(void)
+{
+ return stlink_usb_reset(stlink_dap_handle);
+}
+
+static int stlink_swim_op_read_mem(uint32_t addr, uint32_t size,
+ uint32_t count, uint8_t *buffer)
+{
+ return stlink_usb_read_mem(stlink_dap_handle, addr, size, count, buffer);
+}
+
+static int stlink_swim_op_write_mem(uint32_t addr, uint32_t size,
+ uint32_t count, const uint8_t *buffer)
+{
+ return stlink_usb_write_mem(stlink_dap_handle, addr, size, count, buffer);
+}
+
+static int stlink_swim_op_reconnect(void)
+{
+ return stlink_usb_state(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,
@@ -3656,6 +3676,8 @@ static int stlink_dap_init(void)
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;
@@ -3665,7 +3687,8 @@ static int stlink_dap_init(void)
if (retval != ERROR_OK)
return retval;
- if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_DAP_REG)) {
+ 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;
}
@@ -3737,7 +3760,14 @@ static const struct dap_ops stlink_dap_ops = {
.quit = stlink_dap_op_quit, /* optional */
};
-static const char *const stlink_dap_transport[] = { "dapdirect_jtag", "dapdirect_swd", NULL };
+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_jtag", "dapdirect_swd", "swim", NULL };
struct adapter_driver stlink_dap_adapter_driver = {
.name = "st-link",
@@ -3755,4 +3785,5 @@ struct adapter_driver stlink_dap_adapter_driver = {
.dap_jtag_ops = &stlink_dap_ops,
.dap_swd_ops = &stlink_dap_ops,
+ .swim_ops = &stlink_swim_ops,
};
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.h b/src/jtag/interface.h
index 91291db..a471aa9 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
@@ -363,6 +364,9 @@ struct adapter_driver {
/* DAP APIs over SWD transport */
const struct dap_ops *dap_swd_ops;
+ /* SWIM APIs */
+ const struct swim_driver *swim_ops;
+
/* FIXME: helper to simplify transition of HLA drivers. To be removed */
struct hl_interface_s *hla_if;
};
diff --git a/src/jtag/swim.c b/src/jtag/swim.c
index 965018c..936268b 100644
--- a/src/jtag/swim.c
+++ b/src/jtag/swim.c
@@ -14,38 +14,140 @@
#include "interface.h"
#include "swim.h"
-#include "jtag/hla/hla_transport.h"
-#include "jtag/hla/hla_interface.h"
-#include "jtag/hla/hla_layout.h"
+#include <helper/command.h>
+#include <transport/transport.h>
extern struct adapter_driver *adapter_driver;
int swim_system_reset(void)
{
- assert(adapter_driver->hla_if);
+ assert(adapter_driver->swim_ops);
- return adapter_driver->hla_if->layout->api->reset(adapter_driver->hla_if->handle);
+ 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->hla_if);
+ assert(adapter_driver->swim_ops);
- return adapter_driver->hla_if->layout->api->read_mem(adapter_driver->hla_if->handle, addr, size, count, buffer);
+ 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->hla_if);
+ assert(adapter_driver->swim_ops);
- return adapter_driver->hla_if->layout->api->write_mem(adapter_driver->hla_if->handle, addr, size, count, buffer);
+ return adapter_driver->swim_ops->write_mem(addr, size, count, buffer);
}
int swim_reconnect(void)
{
- assert(adapter_driver->hla_if);
+ assert(adapter_driver->swim_ops);
- return adapter_driver->hla_if->layout->api->state(adapter_driver->hla_if->handle);
+ 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/transport/transport.h b/src/transport/transport.h
index 4effca5..809564e 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -98,6 +98,7 @@ bool transport_is_jtag(void);
bool transport_is_swd(void);
bool transport_is_dapdirect_jtag(void);
bool transport_is_dapdirect_swd(void);
+bool transport_is_swim(void);
#if BUILD_HLADAPTER
bool transport_is_hla(void);
diff --git a/tcl/interface/stlink-dap.cfg b/tcl/interface/stlink-dap.cfg
index 4576ad3..ac4de18 100644
--- a/tcl/interface/stlink-dap.cfg
+++ b/tcl/interface/stlink-dap.cfg
@@ -1,16 +1,19 @@
#
-# STMicroelectronics ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit
+# STMicroelectronics ST-LINK/V1, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit
# debugger/programmer
#
-# This new interface driver creates a ST-Link wrapper for ARM-DAP
-# Old ST-LINK/V1 and ST-LINK/V2 pre version V2J24 don't support this method
+# This new interface driver creates a ST-Link wrapper for ARM-DAP named "dapdirect"
+# Old ST-LINK/V1 and ST-LINK/V2 pre version V2J24 don't support "dapdirect"
+#
+# SWIM transport is natively supported
#
adapter driver st-link
-st-link vid_pid 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753
+st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753
# transport select dapdirect_jtag
# transport select dapdirect_swd
+# transport select swim
# Optionally specify the serial number of usb device
# e.g.
diff --git a/tcl/target/stm8l.cfg b/tcl/target/stm8l.cfg
index f3c9428..782350f 100644
--- a/tcl/target/stm8l.cfg
+++ b/tcl/target/stm8l.cfg
@@ -4,7 +4,7 @@
# stm8 devices support SWIM transports only.
#
-transport select stlink_swim
+transport select swim
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
@@ -62,7 +62,7 @@ if { [info exists BLOCKSIZE] } {
set _BLOCKSIZE 0x80
}
-hla newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0
+swim newtap $_CHIPNAME cpu
set _TARGETNAME $_CHIPNAME.cpu
diff --git a/tcl/target/stm8s.cfg b/tcl/target/stm8s.cfg
index 5d52aea..277cdc9 100644
--- a/tcl/target/stm8s.cfg
+++ b/tcl/target/stm8s.cfg
@@ -4,7 +4,7 @@
# stm8 devices support SWIM transports only.
#
-transport select stlink_swim
+transport select swim
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
@@ -62,7 +62,7 @@ if { [info exists BLOCKSIZE] } {
set _BLOCKSIZE 0x80
}
-hla newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0
+swim newtap $_CHIPNAME cpu
set _TARGETNAME $_CHIPNAME.cpu