#define STLINK_SWD_AP_FAULT 0x11
#define STLINK_SWD_AP_ERROR 0x12
#define STLINK_SWD_AP_PARITY_ERROR 0x13
+#define STLINK_JTAG_GET_IDCODE_ERROR 0x09
#define STLINK_JTAG_WRITE_ERROR 0x0c
#define STLINK_JTAG_WRITE_VERIF_ERROR 0x0d
#define STLINK_SWD_DP_WAIT 0x14
static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size);
static int stlink_swim_status(void *handle);
+void stlink_dump_speed_map(const struct speed_map *map, unsigned int map_size);
+static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map *map);
+static int stlink_speed(void *handle, int khz, bool query);
/** */
static unsigned int stlink_usb_block(void *handle)
transfers block in cmdbuf
<size> indicates number of bytes in the following
data phase.
+ Ignore the (eventual) error code in the received packet.
*/
-static int stlink_usb_xfer(void *handle, const uint8_t *buf, int size)
+static int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size)
{
int err, cmdsize = STLINK_CMD_SIZE_V2;
struct stlink_usb_handle_s *h = handle;
case STLINK_SWD_DP_WAIT:
LOG_DEBUG("wait status SWD_DP_WAIT (0x%x)", STLINK_SWD_DP_WAIT);
return ERROR_WAIT;
+ case STLINK_JTAG_GET_IDCODE_ERROR:
+ LOG_DEBUG("STLINK_JTAG_GET_IDCODE_ERROR");
+ return ERROR_FAIL;
case STLINK_JTAG_WRITE_ERROR:
LOG_DEBUG("Write error");
return ERROR_FAIL;
}
}
+/*
+ * Wrapper around stlink_usb_xfer_noerrcheck()
+ * to check the error code in the received packet
+ */
+static int stlink_usb_xfer_errcheck(void *handle, const uint8_t *buf, int size)
+{
+ int retval;
+
+ assert(size > 0);
+
+ retval = stlink_usb_xfer_noerrcheck(handle, buf, size);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return stlink_usb_error_check(handle);
+}
/** Issue an STLINK command via USB transfer, with retries on any wait status responses.
while (1) {
if ((h->transport != HL_TRANSPORT_SWIM) || !retries) {
- res = stlink_usb_xfer(handle, buf, size);
+ res = stlink_usb_xfer_noerrcheck(handle, buf, size);
if (res != ERROR_OK)
return res;
}
h->cmdbuf[h->cmdidx++] = STLINK_GET_VERSION;
- res = stlink_usb_xfer(handle, h->databuf, 6);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 6);
if (res != ERROR_OK)
return res;
h->cmdbuf[h->cmdidx++] = STLINK_APIV3_GET_VERSION_EX;
- res = stlink_usb_xfer(handle, h->databuf, 12);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 12);
if (res != ERROR_OK)
return res;
h->cmdbuf[h->cmdidx++] = STLINK_GET_TARGET_VOLTAGE;
- int result = stlink_usb_xfer(handle, h->databuf, 8);
+ int result = stlink_usb_xfer_noerrcheck(handle, h->databuf, 8);
if (result != ERROR_OK)
return result;
h->cmdbuf[h->cmdidx++] = STLINK_GET_CURRENT_MODE;
- res = stlink_usb_xfer(handle, h->databuf, 2);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 2);
if (res != ERROR_OK)
return res;
return ERROR_FAIL;
}
- res = stlink_usb_xfer(handle, 0, 0);
+ res = stlink_usb_xfer_noerrcheck(handle, 0, 0);
if (res != ERROR_OK)
return res;
}
/** */
-static int stlink_usb_init_mode(void *handle, bool connect_under_reset)
+static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int initial_interface_speed)
{
int res;
uint8_t mode;
return ERROR_FAIL;
}
+ /* 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 (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) {
+ 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_dump_speed_map(map, ARRAY_SIZE(map));
+ stlink_speed(h, initial_interface_speed, false);
+ }
+
/* preliminary SRST assert:
* We want SRST is asserted before activating debug signals (mode_enter).
* As the required mode has not been set, the adapter may not know what pin to use.
stlink_usb_init_buffer(handle, h->rx_ep, 4);
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READSTATUS;
- res = stlink_usb_xfer(handle, h->databuf, 4);
+ /* error is checked by the caller */
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4);
if (res != ERROR_OK)
return res;
return ERROR_OK;
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READ_CAP;
h->cmdbuf[h->cmdidx++] = 0x01;
- res = stlink_usb_xfer(handle, h->databuf, 8);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 8);
if (res != ERROR_OK)
return res;
memcpy(cap, h->databuf, 8);
stlink_usb_init_buffer(handle, h->rx_ep, len);
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READBUF;
- res = stlink_usb_xfer(handle, data, len);
+ res = stlink_usb_xfer_noerrcheck(handle, data, len);
if (res != ERROR_OK)
return res;
/** */
static int stlink_usb_idcode(void *handle, uint32_t *idcode)
{
- int res;
+ int res, offset;
struct stlink_usb_handle_s *h = handle;
assert(handle != NULL);
return ERROR_OK;
}
- stlink_usb_init_buffer(handle, h->rx_ep, 4);
+ stlink_usb_init_buffer(handle, h->rx_ep, 12);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID;
+ if (h->version.jtag_api == STLINK_JTAG_API_V1) {
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID;
- res = stlink_usb_xfer(handle, h->databuf, 4);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4);
+ offset = 0;
+ } else {
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READ_IDCODES;
+
+ res = stlink_usb_xfer_errcheck(handle, h->databuf, 12);
+ offset = 4;
+ }
if (res != ERROR_OK)
return res;
- *idcode = le_to_h_u32(h->databuf);
+ *idcode = le_to_h_u32(h->databuf + offset);
LOG_DEBUG("IDCODE: 0x%08" PRIX32, *idcode);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GET_TRACE_NB;
- res = stlink_usb_xfer(handle, h->databuf, 2);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 2);
if (res != ERROR_OK)
return res;
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_GETSTATUS;
- res = stlink_usb_xfer(handle, h->databuf, 2);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 2);
if (res != ERROR_OK)
return TARGET_UNKNOWN;
stlink_usb_init_buffer(handle, h->rx_ep, 2);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_STOP_TRACE_RX;
- res = stlink_usb_xfer(handle, h->databuf, 2);
+ res = stlink_usb_xfer_errcheck(handle, h->databuf, 2);
if (res == ERROR_OK)
h->trace.enabled = false;
h_u32_to_le(h->cmdbuf+h->cmdidx, h->trace.source_hz);
h->cmdidx += 4;
- res = stlink_usb_xfer(handle, h->databuf, 2);
+ res = stlink_usb_xfer_errcheck(handle, h->databuf, 2);
if (res == ERROR_OK) {
h->trace.enabled = true;
assert(handle != NULL);
- stlink_usb_init_buffer(handle, h->rx_ep, 84);
+ stlink_usb_init_buffer(handle, h->rx_ep, 88);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->version.jtag_api == STLINK_JTAG_API_V1)
+ if (h->version.jtag_api == STLINK_JTAG_API_V1) {
+
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READALLREGS;
- else
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 84);
+ /* regs data from offset 0 */
+ } else {
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READALLREGS;
+ res = stlink_usb_xfer_errcheck(handle, h->databuf, 88);
+ /* status at offset 0, regs data from offset 4 */
+ }
- res = stlink_usb_xfer(handle, h->databuf, 84);
-
- if (res != ERROR_OK)
- return res;
-
- return ERROR_OK;
+ return res;
}
/** */
h->cmdbuf[h->cmdidx++] = num;
if (h->version.jtag_api == STLINK_JTAG_API_V1) {
- res = stlink_usb_xfer(handle, h->databuf, 4);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4);
if (res != ERROR_OK)
return res;
*val = le_to_h_u32(h->databuf);
static int stlink_usb_get_rw_status(void *handle)
{
- int res;
struct stlink_usb_handle_s *h = handle;
assert(handle != NULL);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
if (h->version.flags & STLINK_F_HAS_GETLASTRWSTATUS2) {
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS2;
-
- res = stlink_usb_xfer(handle, h->databuf, 12);
+ return stlink_usb_xfer_errcheck(handle, h->databuf, 12);
} else {
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS;
-
- res = stlink_usb_xfer(handle, h->databuf, 2);
+ return stlink_usb_xfer_errcheck(handle, h->databuf, 2);
}
-
- if (res != ERROR_OK)
- return res;
-
- return stlink_usb_error_check(h);
}
/** */
if (read_len == 1)
read_len++;
- res = stlink_usb_xfer(handle, h->databuf, read_len);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, read_len);
if (res != ERROR_OK)
return res;
h_u16_to_le(h->cmdbuf+h->cmdidx, len);
h->cmdidx += 2;
- res = stlink_usb_xfer(handle, buffer, len);
+ res = stlink_usb_xfer_noerrcheck(handle, buffer, len);
if (res != ERROR_OK)
return res;
h_u16_to_le(h->cmdbuf+h->cmdidx, len);
h->cmdidx += 2;
- res = stlink_usb_xfer(handle, h->databuf, len);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len);
if (res != ERROR_OK)
return res;
h_u16_to_le(h->cmdbuf+h->cmdidx, len);
h->cmdidx += 2;
- res = stlink_usb_xfer(handle, buffer, len);
+ res = stlink_usb_xfer_noerrcheck(handle, buffer, len);
if (res != ERROR_OK)
return res;
h_u16_to_le(h->cmdbuf+h->cmdidx, len);
h->cmdidx += 2;
- res = stlink_usb_xfer(handle, h->databuf, len);
+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len);
if (res != ERROR_OK)
return res;
h_u16_to_le(h->cmdbuf+h->cmdidx, len);
h->cmdidx += 2;
- res = stlink_usb_xfer(handle, buffer, len);
+ res = stlink_usb_xfer_noerrcheck(handle, buffer, len);
if (res != ERROR_OK)
return res;
h->cmdbuf[h->cmdidx++] = STLINK_APIV3_GET_COM_FREQ;
h->cmdbuf[h->cmdidx++] = is_jtag ? 1 : 0;
- int res = stlink_usb_xfer(handle, h->databuf, 52);
+ int res = stlink_usb_xfer_errcheck(handle, h->databuf, 52);
int size = h->databuf[8];
h_u32_to_le(&h->cmdbuf[4], frequency);
- return stlink_usb_xfer(handle, h->databuf, 8);
+ return stlink_usb_xfer_errcheck(handle, h->databuf, 8);
}
static int stlink_speed_v3(void *handle, bool is_jtag, int khz, bool query)
}
/* initialize the debug hardware */
- err = stlink_usb_init_mode(h, param->connect_under_reset);
+ err = stlink_usb_init_mode(h, param->connect_under_reset, param->initial_interface_speed);
if (err != ERROR_OK) {
LOG_ERROR("init mode failed (unable to connect to the target)");
return ERROR_OK;
}
- if (h->transport == HL_TRANSPORT_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, param->initial_interface_speed, false);
- }
- } else if (h->transport == HL_TRANSPORT_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, param->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_dump_speed_map(map, ARRAY_SIZE(map));
- stlink_speed(h, param->initial_interface_speed, false);
- }
-
/* get cpuid, so we can determine the max page size
* start with a safe default */
h->max_mem_packet = (1 << 10);