swim: add new transport

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
This commit is contained in:
Antonio Borneo 2020-01-27 18:45:10 +01:00
parent ac05f929ed
commit ffe6bc8220
12 changed files with 197 additions and 41 deletions

3
TODO
View File

@ -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}.

View 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

View 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",

View 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,
};

View 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;
}

View 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 */

View 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;
};

View File

@ -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;
}

View 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);

View 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.

View 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

View 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