#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>
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 {
/** */
/** */
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
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;
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 (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;
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)
- return stlink_swim_generate_rst(handle);
-
stlink_usb_init_buffer(handle, h->rx_ep, 2);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
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.
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.
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
}
/** */
-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 : "");
}
/* 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_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,
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;
}
.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_swd", "dapdirect_jtag", "swim", NULL };
struct adapter_driver stlink_dap_adapter_driver = {
.name = "st-link",
.dap_jtag_ops = &stlink_dap_ops,
.dap_swd_ops = &stlink_dap_ops,
+ .swim_ops = &stlink_swim_ops,
};