swim: add new transport 30/5530/6
authorAntonio Borneo <borneo.antonio@gmail.com>
Mon, 27 Jan 2020 17:45:10 +0000 (18:45 +0100)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sun, 24 May 2020 20:32:05 +0000 (21:32 +0100)
Add SWIM and STM8 to documentation and update TODO file.
Introduce transport "swim" and command "swim newtap".
Switch in swim.c from HLA API to the new SWIM API.
Implement in stlink driver the SWIM APIs as wrappers of existing
HLA functions.
Remove any SWIM related reference from HLA files.
Update stm8 config files and stlink-dap interface config file.

Change-Id: I2bb9f58d52900f6eb4df05f979f7ef11fd439c24
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/5530
Tested-by: jenkins
12 files changed:
TODO
doc/openocd.texi
src/jtag/core.c
src/jtag/drivers/stlink_usb.c
src/jtag/hla/hla_transport.c
src/jtag/hla/hla_transport.h
src/jtag/interface.h
src/jtag/swim.c
src/transport/transport.h
tcl/interface/stlink-dap.cfg
tcl/target/stm8l.cfg
tcl/target/stm8s.cfg

diff --git a/TODO b/TODO
index c73d772..ebb6c99 100644 (file)
--- 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}.
 
index ef77993..1ddf09f 100644 (file)
@@ -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
index d83f195..1d424b2 100644 (file)
@@ -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",
index 485a95c..4c5081c 100644 (file)
@@ -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,
 };
index ddacea3..fbdddfd 100644 (file)
@@ -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;
 }
index 07eb751..0e0bea2 100644 (file)
@@ -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 */
index 91291db..a471aa9 100644 (file)
@@ -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;
 };
index 965018c..936268b 100644 (file)
 
 #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;
 }
index 4effca5..809564e 100644 (file)
@@ -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);
index 4576ad3..ac4de18 100644 (file)
@@ -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.
index f3c9428..782350f 100644 (file)
@@ -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
 
index 5d52aea..277cdc9 100644 (file)
@@ -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