#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)
/*
* 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)
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 {
/** */
/** */
struct stlink_usb_handle_s {
/** */
- struct jtag_libusb_device_handle *fd;
+ struct libusb_device_handle *fd;
/** */
struct libusb_transfer *trans;
/** */
/** */
uint32_t max_mem_packet;
/** */
- enum hl_transports transport;
+ enum stlink_mode st_mode;
/** */
struct stlink_usb_version version;
/** */
#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
#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)
/* aliases */
#define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE
/* JTAG clock speed */
static const struct speed_map stlink_khz_to_speed_map_jtag[] = {
- {18000, 2},
{9000, 4},
{4500, 8},
{2250, 16},
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;
};
static int jtag_libusb_bulk_transfer_n(
- jtag_libusb_device_handle * dev_handle,
+ struct libusb_device_handle *dev_handle,
struct jtag_xfer *transfers,
size_t n_transfers,
int timeout)
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;
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;
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;
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;
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:
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:
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;
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;
}
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");
}
/* 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);
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);
}
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;
}
assert(handle != NULL);
- if (h->transport == HL_TRANSPORT_SWIM) {
- res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport));
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
+ res = stlink_usb_mode_enter(handle, h->st_mode);
if (res != ERROR_OK)
return TARGET_UNKNOWN;
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;
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)
assert(handle != NULL);
- if (h->transport == HL_TRANSPORT_SWIM)
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM)
return stlink_swim_generate_rst(handle);
stlink_usb_init_buffer(handle, h->rx_ep, 2);
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) {
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
retval = stlink_swim_readbytes(handle, addr, bytes_remaining, buffer);
if (retval != ERROR_OK)
return retval;
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) {
+ if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
retval = stlink_swim_writebytes(handle, addr, bytes_remaining, buffer);
if (retval != ERROR_OK)
return retval;
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)
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);
}
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
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;
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 : "");
}
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;
}
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;
}
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;
/* 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;
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)");
return ERROR_FAIL;
}
+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,
/** */
struct hl_layout_api_s stlink_usb_layout_api = {
/** */
- .open = stlink_usb_open,
+ .open = stlink_usb_hl_open,
/** */
.close = stlink_usb_close,
/** */
static int stlink_dap_reinit_interface(void)
{
int retval;
- enum stlink_mode mode;
/*
* On JTAG only, it should be enough to call stlink_usb_reset(). But on
* select the mode again.
*/
- mode = stlink_get_mode(stlink_dap_param.transport);
if (!stlink_dap_handle->reconnect_pending) {
stlink_dap_handle->reconnect_pending = true;
- stlink_usb_mode_leave(stlink_dap_handle, mode);
+ stlink_usb_mode_leave(stlink_dap_handle, stlink_dap_handle->st_mode);
}
- retval = stlink_usb_mode_enter(stlink_dap_handle, mode);
+ retval = stlink_usb_mode_enter(stlink_dap_handle, stlink_dap_handle->st_mode);
if (retval != ERROR_OK)
return retval;
retval = stlink_usb_idcode(stlink_dap_handle, &idcode);
if (retval == ERROR_OK)
LOG_INFO("%s %#8.8" PRIx32,
- (stlink_dap_handle->transport == HL_TRANSPORT_JTAG) ? "JTAG IDCODE" : "SWD DPIDR",
+ (stlink_dap_handle->st_mode == STLINK_MODE_DEBUG_JTAG) ? "JTAG IDCODE" : "SWD DPIDR",
idcode);
else
dap->do_reconnect = true;
data = data ? : &dummy;
if (stlink_dap_handle->version.flags & STLINK_F_QUIRK_JTAG_DP_READ
- && stlink_dap_handle->transport == HL_TRANSPORT_JTAG) {
+ && 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 (ctrlstat & SSTICKYERR) {
- if (stlink_dap_param.transport == HL_TRANSPORT_JTAG)
+ 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
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,
+ 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)
{
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 (transport_is_dapdirect_swd())
- stlink_dap_param.transport = HL_TRANSPORT_SWD;
+ mode = STLINK_MODE_DEBUG_SWD;
else if (transport_is_dapdirect_jtag())
- stlink_dap_param.transport = HL_TRANSPORT_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, (void **)&stlink_dap_handle);
+ retval = stlink_usb_open(&stlink_dap_param, mode, (void **)&stlink_dap_handle);
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;
}
/** */
static int stlink_dap_khz(int khz, int *jtag_speed)
{
- *jtag_speed = khz;
+ if (khz == 0) {
+ LOG_ERROR("RCLK not supported");
+ return ERROR_FAIL;
+ }
+
+ *jtag_speed = stlink_speed(stlink_dap_handle, khz, true);
return ERROR_OK;
}
.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",
.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,
};