summaryrefslogtreecommitdiff
path: root/src/stlink-lib/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stlink-lib/usb.c')
-rw-r--r--src/stlink-lib/usb.c829
1 files changed, 382 insertions, 447 deletions
diff --git a/src/stlink-lib/usb.c b/src/stlink-lib/usb.c
index 2754db0..83e2652 100644
--- a/src/stlink-lib/usb.c
+++ b/src/stlink-lib/usb.c
@@ -1,36 +1,44 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <limits.h>
+/*
+ * File: usb.c
+ *
+ * USB commands & interaction with ST-LINK devices
+ */
#if !defined(_MSC_VER)
#include <sys/time.h>
-#endif
-
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
+#endif // _MSC_VER
#if defined(_WIN32)
#include <win32_socket.h>
-#endif
+#endif // _WIN32
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <unistd.h>
#include <stlink.h>
-#include <helper.h>
#include "usb.h"
-enum SCSI_Generic_Direction {SG_DXFER_TO_DEV = 0, SG_DXFER_FROM_DEV = 0x80};
+#include "commands.h"
+#include "logging.h"
+#include "read_write.h"
+#include "register.h"
static inline uint32_t le_to_h_u32(const uint8_t* buf) {
- return((uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24));
+ return ((uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24));
}
-static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, uint32_t khz) {
- unsigned int i;
- int speed_index = -1;
- int speed_diff = INT_MAX;
- int last_valid_speed = -1;
+static int32_t _stlink_match_speed_map(const uint32_t *map, uint32_t map_size, uint32_t khz) {
+ uint32_t i;
+ int32_t speed_index = -1;
+ int32_t speed_diff = INT_MAX;
+ int32_t last_valid_speed = -1;
bool match = true;
for (i = 0; i < map_size; i++) {
@@ -42,7 +50,7 @@ static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, u
speed_index = i;
break;
} else {
- int current_diff = khz - map[i];
+ int32_t current_diff = khz - map[i];
// get abs value for comparison
current_diff = (current_diff > 0) ? current_diff : -current_diff;
@@ -66,7 +74,7 @@ static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, u
ILOG("Unable to match requested speed %d kHz, using %d kHz\n", khz, map[speed_index]);
}
- return(speed_index);
+ return (speed_index);
}
void _stlink_usb_close(stlink_t* sl) {
@@ -83,58 +91,92 @@ void _stlink_usb_close(stlink_t* sl) {
}
}
-ssize_t send_recv(struct stlink_libusb* handle, int terminate,
- unsigned char* txbuf, size_t txsize, unsigned char* rxbuf, size_t rxsize) {
+ssize_t send_recv(struct stlink_libusb* handle, int32_t terminate, unsigned char* txbuf, uint32_t txsize,
+ unsigned char* rxbuf, uint32_t rxsize, int32_t check_error, const char *cmd) {
// Note: txbuf and rxbuf can point to the same area
- int res = 0;
- int t;
+ int32_t res, t, retry = 0;
- t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, txbuf, (int)txsize, &res, 3000);
+ while (1) {
+ res = 0;
+ t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, txbuf, (int32_t)txsize, &res, 3000);
- if (t) {
- printf("[!] send_recv send request failed: %s\n", libusb_error_name(t));
- return(-1);
- } else if ((size_t)res != txsize) {
- printf("[!] send_recv send request wrote %u bytes (instead of %u).\n",
- (unsigned int)res, (unsigned int)txsize);
- }
+ if (t) {
+ ELOG("%s send request failed: %s\n", cmd, libusb_error_name(t));
+ return (-1);
+ } else if ((size_t)res != txsize) {
+ ELOG("%s send request wrote %u bytes, instead of %u\n", cmd, (uint32_t)res, (uint32_t)txsize);
+ }
- if (rxsize != 0) {
- t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, rxbuf, (int)rxsize, &res, 3000);
+ if (rxsize != 0) {
+ t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, rxbuf, (int32_t)rxsize, &res, 3000);
- if (t) {
- printf("[!] send_recv read reply failed: %s\n", libusb_error_name(t));
- return(-1);
+ if (t) {
+ ELOG("%s read reply failed: %s\n", cmd, libusb_error_name(t));
+ return (-1);
+ }
+
+ /* Checking the command execution status stored in the first byte of the response */
+ if (handle->protocoll != 1 && check_error >= CMD_CHECK_STATUS &&
+ rxbuf[0] != STLINK_DEBUG_ERR_OK) {
+ switch(rxbuf[0]) {
+ case STLINK_DEBUG_ERR_AP_WAIT:
+ case STLINK_DEBUG_ERR_DP_WAIT:
+ if (check_error == CMD_CHECK_RETRY && retry < 3) {
+ uint32_t delay_us = (1<<retry) * 1000;
+ DLOG("%s wait error (0x%02X), delaying %u us and retry\n", cmd, rxbuf[0], delay_us);
+ usleep(delay_us);
+ retry++;
+ continue;
+ }
+ DLOG("%s wait error (0x%02X)\n", cmd, rxbuf[0]);
+ break;
+ case STLINK_DEBUG_ERR_FAULT: DLOG("%s response fault\n", cmd); break;
+ case STLINK_DEBUG_ERR_AP_FAULT: DLOG("%s access port fault\n", cmd); break;
+ case STLINK_DEBUG_ERR_DP_FAULT: DLOG("%s debug port fault\n", cmd); break;
+ case STLINK_DEBUG_ERR_AP_ERROR: DLOG("%s access port error\n", cmd); break;
+ case STLINK_DEBUG_ERR_DP_ERROR: DLOG("%s debug port error\n", cmd); break;
+ case STLINK_DEBUG_ERR_WRITE_VERIFY: DLOG("%s verification error\n", cmd); break;
+ case STLINK_DEBUG_ERR_WRITE: DLOG("%s write error\n", cmd); break;
+ default: DLOG("%s error (0x%02X)\n", cmd, rxbuf[0]); break;
+ }
+
+ return (-1);
+ }
+
+ if (check_error == CMD_CHECK_REP_LEN && res != (int32_t)rxsize) {
+ ELOG("%s wrong reply length\n", cmd);
+ res = -1;
+ }
}
- }
- if ((handle->protocoll == 1) && terminate) {
- // read the SG reply
- unsigned char sg_buf[13];
- t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, sg_buf, 13, &res, 3000);
+ if ((handle->protocoll == 1) && terminate) {
+ // read the SG reply
+ unsigned char sg_buf[13];
+ t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, sg_buf, 13, &res, 3000);
- if (t) {
- printf("[!] send_recv read storage failed: %s\n", libusb_error_name(t));
- return(-1);
+ if (t) {
+ ELOG("%s read storage failed: %s\n", cmd, libusb_error_name(t));
+ return (-1);
+ }
+
+ // The STLink doesn't seem to evaluate the sequence number.
+ handle->sg_transfer_idx++;
}
- // The STLink doesn't seem to evaluate the sequence number.
- handle->sg_transfer_idx++;
+ return (res);
}
-
- return(res);
}
-static inline int send_only(struct stlink_libusb* handle, int terminate,
- unsigned char* txbuf, size_t txsize) {
- return((int)send_recv(handle, terminate, txbuf, txsize, NULL, 0));
+static inline int32_t send_only(struct stlink_libusb* handle, int32_t terminate, unsigned char* txbuf,
+ uint32_t txsize, const char *cmd) {
+ return ((int32_t)send_recv(handle, terminate, txbuf, txsize, NULL, 0, CMD_CHECK_NO, cmd));
}
-static int fill_command(stlink_t * sl, enum SCSI_Generic_Direction dir, uint32_t len) {
+static int32_t fill_command(stlink_t * sl, enum SCSI_Generic_Direction dir, uint32_t len) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
- int i = 0;
+ int32_t i = 0;
memset(cmd, 0, sizeof(sl->c_buf));
if (slu->protocoll == 1) {
@@ -149,42 +191,31 @@ static int fill_command(stlink_t * sl, enum SCSI_Generic_Direction dir, uint32_t
cmd[i++] = 0; // logical unit
cmd[i++] = 0xa; // command length
}
-
- return(i);
+ return (i);
}
-int _stlink_usb_version(stlink_t *sl) {
+int32_t _stlink_usb_version(stlink_t *sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- uint32_t rep_len = 6;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ uint32_t rep_len;
+ int32_t i;
- cmd[i++] = STLINK_GET_VERSION;
-
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_GET_VERSION\n");
- return((int)size);
- }
-
- /* STLINK-V3 requires a specific command */
if (sl->version.stlink_v == 3) {
+ // STLINK-V3 version is determined by another command
rep_len = 12;
i = fill_command(sl, SG_DXFER_FROM_DEV, 16);
- cmd[i++] = STLINK_APIV3_GET_VERSION_EX;
-
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size != (ssize_t)rep_len) {
- printf("[!] send_recv STLINK_APIV3_GET_VERSION_EX\n");
- return((int)size);
- }
+ cmd[i++] = STLINK_GET_VERSION_APIV3;
+ } else {
+ rep_len = 6;
+ i = fill_command(sl, SG_DXFER_FROM_DEV, 6);
+ cmd[i++] = STLINK_GET_VERSION;
}
- return(0);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_REP_LEN, "GET_VERSION");
+
+ return (size < 0 ? -1 : 0);
}
int32_t _stlink_usb_target_voltage(stlink_t *sl) {
@@ -193,81 +224,77 @@ int32_t _stlink_usb_target_voltage(stlink_t *sl) {
unsigned char* const cmd = sl->c_buf;
ssize_t size;
uint32_t rep_len = 8;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
uint32_t factor, reading;
- int voltage;
+ int32_t voltage;
cmd[i++] = STLINK_GET_TARGET_VOLTAGE;
- size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len, CMD_CHECK_REP_LEN, "GET_TARGET_VOLTAGE");
- if (size == -1) {
- printf("[!] send_recv STLINK_GET_TARGET_VOLTAGE\n");
- return(-1);
- } else if (size != 8) {
- printf("[!] wrong length STLINK_GET_TARGET_VOLTAGE\n");
- return(-1);
+ if (size < 0) {
+ return (-1);
}
factor = (rdata[3] << 24) | (rdata[2] << 16) | (rdata[1] << 8) | (rdata[0] << 0);
reading = (rdata[7] << 24) | (rdata[6] << 16) | (rdata[5] << 8) | (rdata[4] << 0);
- voltage = 2400 * reading / factor;
+ DLOG("target voltage factor=%08x reading=%08x\n", factor, reading);
+ if (factor != 0 && reading != 0) {
+ voltage = 2400 * reading / factor;
+ } else {
+ DLOG("voltage reading failed at device side, bad STLink chip?\n");
+ voltage = 0;
+ }
- return(voltage);
+ return (voltage);
}
-int _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
+int32_t _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const rdata = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- const int rep_len = 8;
+ const int32_t rep_len = 8;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
- cmd[i++] = STLINK_JTAG_READDEBUG_32BIT;
+ cmd[i++] = STLINK_DEBUG_APIV2_READDEBUGREG;
write_uint32(&cmd[i], addr);
- size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len, CMD_CHECK_RETRY, "READDEBUGREG");
- if (size == -1) {
- printf("[!] send_recv STLINK_JTAG_READDEBUG_32BIT\n");
- return((int)size);
+ if (size < 0) {
+ return (-1);
}
*data = read_uint32(rdata, 4);
- return(0);
+ return (0);
}
-int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
+int32_t _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const rdata = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- const int rep_len = 2;
+ const int32_t rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
- cmd[i++] = STLINK_JTAG_WRITEDEBUG_32BIT;
+ cmd[i++] = STLINK_DEBUG_APIV2_WRITEDEBUGREG;
write_uint32(&cmd[i], addr);
write_uint32(&cmd[i + 4], data);
- size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len, CMD_CHECK_RETRY, "WRITEDEBUGREG");
- if (size == -1) {
- printf("[!] send_recv STLINK_JTAG_WRITEDEBUG_32BIT\n");
- return((int)size);
- }
-
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_get_rw_status(stlink_t *sl) {
- if (sl->version.jtag_api == STLINK_JTAG_API_V1) { return(0); }
+int32_t _stlink_usb_get_rw_status(stlink_t *sl) {
+ if (sl->version.jtag_api == STLINK_JTAG_API_V1) { return (0); }
unsigned char* const rdata = sl->q_buf;
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
- int i;
+ int32_t i;
int16_t ret = 0;
i = fill_command(sl, SG_DXFER_FROM_DEV, 12);
@@ -275,88 +302,90 @@ int _stlink_usb_get_rw_status(stlink_t *sl) {
if (sl->version.flags & STLINK_F_HAS_GETLASTRWSTATUS2) {
cmd[i++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS2;
- ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 12);
+ ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 12, CMD_CHECK_STATUS, "GETLASTRWSTATUS2");
} else {
cmd[i++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS;
- ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 2);
+ ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 2, CMD_CHECK_STATUS, "GETLASTRWSTATUS");
}
- if (ret < 0) { return(-1); }
-
- return(0);
+ return (ret < 0 ? -1 : 0);
}
-int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+int32_t _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
- int i, ret;
+ int32_t i, ret;
i = fill_command(sl, SG_DXFER_TO_DEV, len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_WRITEMEM_32BIT;
write_uint32(&cmd[i], addr);
write_uint16(&cmd[i + 4], len);
- ret = send_only(slu, 0, cmd, slu->cmd_len);
+ ret = send_only(slu, 0, cmd, slu->cmd_len, "WRITEMEM_32BIT");
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
- ret = send_only(slu, 1, data, len);
+ ret = send_only(slu, 1, data, len, "WRITEMEM_32BIT");
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
- return(_stlink_usb_get_rw_status(sl));
+ return (_stlink_usb_get_rw_status(sl));
}
-int _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
+int32_t _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
- int i, ret;
+ int32_t i, ret;
+
+ if ((sl->version.jtag_api < STLINK_JTAG_API_V3 && len > 64) ||
+ (sl->version.jtag_api >= STLINK_JTAG_API_V3 && len > 512)) {
+ ELOG("WRITEMEM_8BIT: bulk packet limits exceeded (data len %d byte)\n", len);
+ return (-1);
+ }
i = fill_command(sl, SG_DXFER_TO_DEV, 0);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_WRITEMEM_8BIT;
write_uint32(&cmd[i], addr);
write_uint16(&cmd[i + 4], len);
- ret = send_only(slu, 0, cmd, slu->cmd_len);
+ ret = send_only(slu, 0, cmd, slu->cmd_len, "WRITEMEM_8BIT");
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
- ret = send_only(slu, 1, data, len);
+ ret = send_only(slu, 1, data, len, "WRITEMEM_8BIT");
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
- return(0);
+ return (0);
}
-
-int _stlink_usb_current_mode(stlink_t * sl) {
+int32_t _stlink_usb_current_mode(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
unsigned char* const data = sl->q_buf;
ssize_t size;
- int rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t rep_len = 2;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_GET_CURRENT_MODE;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_NO, "GET_CURRENT_MODE");
- if (size == -1) {
- printf("[!] send_recv STLINK_GET_CURRENT_MODE\n");
- return(-1);
+ if (size < 0) {
+ return (-1);
}
- return(sl->q_buf[0]);
+ return (sl->q_buf[0]);
}
-int _stlink_usb_core_id(stlink_t * sl) {
+int32_t _stlink_usb_core_id(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
unsigned char* const data = sl->q_buf;
ssize_t size;
- int offset, rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 12;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t offset, rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 12;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
@@ -368,20 +397,19 @@ int _stlink_usb_core_id(stlink_t * sl) {
offset = 4;
}
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_STATUS, "READ_IDCODES");
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_READCOREID\n");
- return(-1);
+ if (size < 0) {
+ return (-1);
}
sl->core_id = read_uint32(data, offset);
- return(0);
+ return (0);
}
-int _stlink_usb_status_v2(stlink_t *sl) {
- int result;
+int32_t _stlink_usb_status_v2(stlink_t *sl) {
+ int32_t result;
uint32_t status = 0;
result = _stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &status);
@@ -399,31 +427,24 @@ int _stlink_usb_status_v2(stlink_t *sl) {
}
}
- return(result);
+ return (result);
}
-int _stlink_usb_status(stlink_t * sl) {
- if (sl->version.jtag_api != STLINK_JTAG_API_V1) { return(_stlink_usb_status_v2(sl)); }
+int32_t _stlink_usb_status(stlink_t * sl) {
+ if (sl->version.jtag_api != STLINK_JTAG_API_V1) { return (_stlink_usb_status_v2(sl)); }
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t rep_len = 2;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_GETSTATUS;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_NO, "GETSTATUS");
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_GETSTATUS\n");
- return((int)size);
- }
-
- sl->q_len = (int)size;
-
- if (sl->q_len > 1) {
+ if (size > 1) {
if (sl->q_buf[0] == STLINK_CORE_RUNNING) {
sl->core_stat = TARGET_RUNNING;
} else if (sl->q_buf[0] == STLINK_CORE_HALTED) {
@@ -435,84 +456,69 @@ int _stlink_usb_status(stlink_t * sl) {
sl->core_stat = TARGET_UNKNOWN;
}
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_force_debug(stlink_t *sl) {
+int32_t _stlink_usb_force_debug(stlink_t *sl) {
struct stlink_libusb *slu = sl->backend_data;
- int res;
+ int32_t res;
if (sl->version.jtag_api != STLINK_JTAG_API_V1) {
res = _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_HALT | STLINK_REG_DHCSR_C_DEBUGEN);
- return(res);
+ return (res);
}
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t rep_len = 2;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_FORCEDEBUG;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_FORCEDEBUG\n");
- return((int)size);
- }
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "FORCEDEBUG");
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_enter_swd_mode(stlink_t * sl) {
+int32_t _stlink_usb_enter_swd_mode(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
unsigned char* const data = sl->q_buf;
const uint32_t rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
// select correct API-Version for entering SWD mode: V1 API (0x20) or V2 API (0x30).
cmd[i++] = sl->version.jtag_api == STLINK_JTAG_API_V1 ? STLINK_DEBUG_APIV1_ENTER : STLINK_DEBUG_APIV2_ENTER;
cmd[i++] = STLINK_DEBUG_ENTER_SWD;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_ENTER\n");
- return((int)size);
- }
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "ENTER_SWD");
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_exit_dfu_mode(stlink_t* sl) {
+int32_t _stlink_usb_exit_dfu_mode(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
cmd[i++] = STLINK_DFU_COMMAND;
cmd[i++] = STLINK_DFU_EXIT;
- size = send_only(slu, 1, cmd, slu->cmd_len);
+ size = send_only(slu, 1, cmd, slu->cmd_len, "DFU_EXIT");
- if (size == -1) {
- printf("[!] send_recv STLINK_DFU_EXIT\n");
- return((int)size);
- }
-
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_reset(stlink_t * sl) {
+int32_t _stlink_usb_reset(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int i, rep_len = 2;
+ int32_t i, rep_len = 2;
// send reset command
i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
@@ -524,39 +530,29 @@ int _stlink_usb_reset(stlink_t * sl) {
cmd[i++] = STLINK_DEBUG_APIV2_RESETSYS;
}
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_RESETSYS\n");
- return((int)size);
- }
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "RESETSYS");
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_jtag_reset(stlink_t * sl, int value) {
+int32_t _stlink_usb_jtag_reset(stlink_t * sl, int32_t value) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t rep_len = 2;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
- cmd[i++] = STLINK_JTAG_DRIVE_NRST;
+ cmd[i++] = STLINK_DEBUG_APIV2_DRIVE_NRST;
cmd[i++] = value;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "DRIVE_NRST");
- if (size == -1) {
- printf("[!] send_recv STLINK_JTAG_DRIVE_NRST\n");
- return((int)size);
- }
-
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_step(stlink_t* sl) {
+int32_t _stlink_usb_step(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
if (sl->version.jtag_api != STLINK_JTAG_API_V1) {
@@ -566,25 +562,20 @@ int _stlink_usb_step(stlink_t* sl) {
_stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_STEP |
STLINK_REG_DHCSR_C_MASKINTS | STLINK_REG_DHCSR_C_DEBUGEN);
return _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_HALT |
- STLINK_REG_DHCSR_C_DEBUGEN);
+ STLINK_REG_DHCSR_C_DEBUGEN);
}
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t rep_len = 2;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_STEPCORE;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_STEPCORE\n");
- return((int)size);
- }
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "STEPCORE");
- return(0);
+ return (size < 0 ? -1 : 0);
}
/**
@@ -592,51 +583,45 @@ int _stlink_usb_step(stlink_t* sl) {
* @param sl
* @param type
*/
-int _stlink_usb_run(stlink_t* sl, enum run_type type) {
+int32_t _stlink_usb_run(stlink_t* sl, enum run_type type) {
struct stlink_libusb * const slu = sl->backend_data;
- int res;
+ int32_t res;
if (sl->version.jtag_api != STLINK_JTAG_API_V1) {
- res = _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR,
- STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN |
+ res = _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN |
((type==RUN_FLASH_LOADER)?STLINK_REG_DHCSR_C_MASKINTS:0));
- return(res);
+ return (res);
}
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t rep_len = 2;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_RUNCORE;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "RUNCORE");
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_RUNCORE\n");
- return((int)size);
- }
-
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_set_swdclk(stlink_t* sl, int clk_freq) {
+int32_t _stlink_usb_set_swdclk(stlink_t* sl, int32_t clk_freq) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int rep_len = 2;
- int i;
+ int32_t rep_len = 2;
+ int32_t i;
// clock speed only supported by stlink/v2 and for firmware >= 22
if (sl->version.stlink_v == 2 && sl->version.jtag_v >= 22) {
uint16_t clk_divisor;
if (clk_freq) {
const uint32_t map[] = {5, 15, 25, 50, 100, 125, 240, 480, 950, 1200, 1800, 4000};
- int speed_index = _stlink_match_speed_map(map, STLINK_ARRAY_SIZE(map), clk_freq);
+ int32_t speed_index = _stlink_match_speed_map(map, STLINK_ARRAY_SIZE(map), clk_freq);
switch (map[speed_index]) {
case 5: clk_divisor = STLINK_SWDCLK_5KHZ_DIVISOR; break;
case 15: clk_divisor = STLINK_SWDCLK_15KHZ_DIVISOR; break;
@@ -661,30 +646,24 @@ int _stlink_usb_set_swdclk(stlink_t* sl, int clk_freq) {
cmd[i++] = STLINK_DEBUG_APIV2_SWD_SET_FREQ;
cmd[i++] = clk_divisor & 0xFF;
cmd[i++] = (clk_divisor >> 8) & 0xFF;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_APIV2_SWD_SET_FREQ\n");
- return((int)size);
- }
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "SWD_SET_FREQ");
- return(0);
+ return (size < 0 ? -1 : 0);
} else if (sl->version.stlink_v == 3) {
- int speed_index;
+ int32_t speed_index;
uint32_t map[STLINK_V3_MAX_FREQ_NB];
i = fill_command(sl, SG_DXFER_FROM_DEV, 16);
cmd[i++] = STLINK_DEBUG_COMMAND;
- cmd[i++] = STLINK_APIV3_GET_COM_FREQ;
+ cmd[i++] = STLINK_DEBUG_APIV3_GET_COM_FREQ;
cmd[i++] = 0; // SWD mode
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, 52);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, 52, CMD_CHECK_STATUS, "GET_COM_FREQ");
- if (size == -1) {
- printf("[!] send_recv STLINK_APIV3_GET_COM_FREQ\n");
- return((int)size);
+ if (size < 0) {
+ return (-1);
}
- int speeds_size = data[8];
+ int32_t speeds_size = data[8];
if (speeds_size > STLINK_V3_MAX_FREQ_NB) {
speeds_size = STLINK_V3_MAX_FREQ_NB;
}
@@ -694,13 +673,13 @@ int _stlink_usb_set_swdclk(stlink_t* sl, int clk_freq) {
// Set to zero all the next entries
for (i = speeds_size; i < STLINK_V3_MAX_FREQ_NB; i++) map[i] = 0;
- if (!clk_freq) clk_freq = 1800; // set default frequency
+ if (!clk_freq) clk_freq = 1000; // set default frequency
speed_index = _stlink_match_speed_map(map, STLINK_ARRAY_SIZE(map), clk_freq);
i = fill_command(sl, SG_DXFER_FROM_DEV, 16);
cmd[i++] = STLINK_DEBUG_COMMAND;
- cmd[i++] = STLINK_APIV3_SET_COM_FREQ;
+ cmd[i++] = STLINK_DEBUG_APIV3_SET_COM_FREQ;
cmd[i++] = 0; // SWD mode
cmd[i++] = 0;
cmd[i++] = (uint8_t)((map[speed_index] >> 0) & 0xFF);
@@ -708,71 +687,60 @@ int _stlink_usb_set_swdclk(stlink_t* sl, int clk_freq) {
cmd[i++] = (uint8_t)((map[speed_index] >> 16) & 0xFF);
cmd[i++] = (uint8_t)((map[speed_index] >> 24) & 0xFF);
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, 8);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_APIV3_SET_COM_FREQ\n");
- return((int)size);
- }
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, 8, CMD_CHECK_STATUS, "SET_COM_FREQ");
- return(0);
+ return (size < 0 ? -1 : 0);
} else if (clk_freq) {
WLOG("ST-Link firmware does not support frequency setup\n");
}
- return(-1);
+ return (-1);
}
-int _stlink_usb_exit_debug_mode(stlink_t *sl) {
+int32_t _stlink_usb_exit_debug_mode(stlink_t *sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_EXIT;
- size = send_only(slu, 1, cmd, slu->cmd_len);
+ size = send_only(slu, 1, cmd, slu->cmd_len, "DEBUG_EXIT");
- if (size == -1) {
- printf("[!] send_only STLINK_DEBUG_EXIT\n");
- return((int)size);
- }
-
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+int32_t _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_READMEM_32BIT;
write_uint32(&cmd[i], addr);
write_uint16(&cmd[i + 4], len);
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, len, CMD_CHECK_NO, "READMEM_32BIT");
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_READMEM_32BIT\n");
- return((int)size);
+ if (size < 0) {
+ return (-1);
}
- sl->q_len = (int)size;
+ sl->q_len = (int32_t)size;
stlink_print_data(sl);
- return(0);
+ return (0);
}
-int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
+int32_t _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const cmd = sl->c_buf;
unsigned char* const data = sl->q_buf;
ssize_t size;
uint32_t rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 84 : 88;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
@@ -782,17 +750,16 @@ int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
cmd[i++] = STLINK_DEBUG_APIV2_READALLREGS;
}
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_STATUS, "READALLREGS");
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_READALLREGS\n");
- return((int)size);
+ if (size < 0) {
+ return (-1);
}
/* V1: regs data from offset 0 */
/* V2: status at offset 0, regs data from offset 4 */
- int reg_offset = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 4;
- sl->q_len = (int)size;
+ int32_t reg_offset = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 4;
+ sl->q_len = (int32_t)size;
stlink_print_data(sl);
for (i = 0; i < 16; i++) regp->r[i] = read_uint32(sl->q_buf, reg_offset + i * 4);
@@ -803,7 +770,7 @@ int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
regp->rw = read_uint32(sl->q_buf, reg_offset + 76);
regp->rw2 = read_uint32(sl->q_buf, reg_offset + 80);
- if (sl->verbose < 2) { return(0); }
+ if (sl->verbose < 2) { return (0); }
DLOG("xpsr = 0x%08x\n", regp->xpsr);
DLOG("main_sp = 0x%08x\n", regp->main_sp);
@@ -811,18 +778,18 @@ int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
DLOG("rw = 0x%08x\n", regp->rw);
DLOG("rw2 = 0x%08x\n", regp->rw2);
- return(0);
+ return (0);
}
-int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
+int32_t _stlink_usb_read_reg(stlink_t *sl, int32_t r_idx, struct stlink_reg *regp) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
uint32_t r;
uint32_t rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 8;
- int reg_offset = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 4;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t reg_offset = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 4;
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
@@ -833,14 +800,13 @@ int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
}
cmd[i++] = (uint8_t)r_idx;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "READREG");
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_READREG\n");
- return((int)size);
+ if (size < 0) {
+ return (-1);
}
- sl->q_len = (int)size;
+ sl->q_len = (int32_t)size;
stlink_print_data(sl);
r = read_uint32(sl->q_buf, reg_offset);
DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);
@@ -865,25 +831,25 @@ int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
regp->r[r_idx] = r;
}
- return(0);
+ return (0);
}
/* See section C1.6 of the ARMv7-M Architecture Reference Manual */
-int _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
+int32_t _stlink_usb_read_unsupported_reg(stlink_t *sl, int32_t r_idx, struct stlink_reg *regp) {
uint32_t r;
- int ret;
+ int32_t ret;
sl->q_buf[0] = (unsigned char)r_idx;
- for (int i = 1; i < 4; i++) sl->q_buf[i] = 0;
+ for (int32_t i = 1; i < 4; i++) sl->q_buf[i] = 0;
ret = _stlink_usb_write_mem32(sl, STLINK_REG_DCRSR, 4);
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
ret = _stlink_usb_read_mem32(sl, STLINK_REG_DCRDR, 4);
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
r = read_uint32(sl->q_buf, 0);
DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);
@@ -903,38 +869,38 @@ int _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, struct stlink_reg
break;
}
- return(0);
+ return (0);
}
-int _stlink_usb_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp) {
- int ret;
+int32_t _stlink_usb_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp) {
+ int32_t ret;
ret = _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
ret = _stlink_usb_read_unsupported_reg(sl, 0x21, regp);
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
- for (int i = 0; i < 32; i++) {
+ for (int32_t i = 0; i < 32; i++) {
ret = _stlink_usb_read_unsupported_reg(sl, 0x40 + i, regp);
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
}
- return(0);
+ return (0);
}
/* See section C1.6 of the ARMv7-M Architecture Reference Manual */
-int _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, struct stlink_reg *regp) {
- int ret;
+int32_t _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int32_t r_idx, struct stlink_reg *regp) {
+ int32_t ret;
if (r_idx >= 0x1C && r_idx <= 0x1F) { // primask, basepri, faultmask, or control
/* These are held in the same register */
ret = _stlink_usb_read_unsupported_reg(sl, 0x14, regp);
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
val = (uint8_t)(val >> 24);
@@ -972,23 +938,23 @@ int _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, str
ret = _stlink_usb_write_mem32(sl, STLINK_REG_DCRDR, 4);
- if (ret == -1) { return(ret); }
+ if (ret == -1) { return (ret); }
sl->q_buf[0] = (unsigned char)r_idx;
sl->q_buf[1] = 0;
sl->q_buf[2] = 0x01;
sl->q_buf[3] = 0;
- return(_stlink_usb_write_mem32(sl, STLINK_REG_DCRSR, 4));
+ return (_stlink_usb_write_mem32(sl, STLINK_REG_DCRSR, 4));
}
-int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
+int32_t _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int32_t idx) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
uint32_t rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
@@ -1000,87 +966,68 @@ int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
cmd[i++] = idx;
write_uint32(&cmd[i], reg);
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_recv STLINK_DEBUG_WRITEREG\n");
- return((int)size);
- }
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_RETRY, "WRITEREG");
- sl->q_len = (int)size;
- stlink_print_data(sl);
-
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_enable_trace(stlink_t* sl, uint32_t frequency) {
+int32_t _stlink_usb_enable_trace(stlink_t* sl, uint32_t frequency) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
uint32_t rep_len = 2;
+ uint32_t max_trace_buf_len = 0;
+
+ if(sl->version.stlink_v == 2) {
+ max_trace_buf_len = STLINK_V2_TRACE_BUF_LEN;
+ } else if (sl->version.stlink_v == 3) {
+ max_trace_buf_len = STLINK_V3_TRACE_BUF_LEN;
+ };
- int i = fill_command(sl, SG_DXFER_TO_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_TO_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_APIV2_START_TRACE_RX;
- write_uint16(&cmd[i + 0], 2 * STLINK_TRACE_BUF_LEN);
+ write_uint16(&cmd[i + 0], 2 * max_trace_buf_len);
write_uint32(&cmd[i + 2], frequency);
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
-
- if (size == -1) {
- printf("[!] send_only STLINK_DEBUG_APIV2_START_TRACE_RX\n");
- return((int)size);
- }
-
- sl->q_len = (int)size;
- stlink_print_data(sl);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_STATUS, "START_TRACE_RX");
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_disable_trace(stlink_t* sl) {
+int32_t _stlink_usb_disable_trace(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
uint32_t rep_len = 2;
- int i = fill_command(sl, SG_DXFER_TO_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_TO_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_APIV2_STOP_TRACE_RX;
- size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_STATUS, "STOP_TRACE_RX");
- if (size == -1) {
- printf("[!] send_only STLINK_DEBUG_APIV2_STOP_TRACE_RX\n");
- return((int)size);
- }
-
- sl->q_len = (int)size;
- stlink_print_data(sl);
-
- return(0);
+ return (size < 0 ? -1 : 0);
}
-int _stlink_usb_read_trace(stlink_t* sl, uint8_t* buf, size_t size) {
+int32_t _stlink_usb_read_trace(stlink_t* sl, uint8_t* buf, uint32_t size) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
uint32_t rep_len = 2;
- int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+ int32_t i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_APIV2_GET_TRACE_NB;
- ssize_t send_size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
+ ssize_t send_size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, CMD_CHECK_NO, "GET_TRACE_NB");
- if (send_size == -1) {
- printf("[!] send_recv STLINK_DEBUG_APIV2_GET_TRACE_NB\n");
- return((int)send_size);
- }
- if (send_size != 2) {
- printf("[!] send_recv STLINK_DEBUG_APIV2_GET_TRACE_NB %d\n", (int)send_size);
- return -1;
+ if (send_size < 0) {
+ return (-1);
+ } else if (send_size != 2) {
+ ELOG("STLINK_DEBUG_APIV2_GET_TRACE_NB reply size %d\n", (int32_t)send_size);
+ return (-1);
}
uint16_t trace_count = read_uint16(sl->q_buf, 0);
@@ -1091,12 +1038,12 @@ int _stlink_usb_read_trace(stlink_t* sl, uint8_t* buf, size_t size) {
}
if (trace_count != 0) {
- int res = 0;
- int t = libusb_bulk_transfer(slu->usb_handle, slu->ep_trace, buf, trace_count, &res, 3000);
+ int32_t res = 0;
+ int32_t t = libusb_bulk_transfer(slu->usb_handle, slu->ep_trace, buf, trace_count, &res, 3000);
- if (t || res != (int)trace_count) {
+ if (t || res != (int32_t)trace_count) {
ELOG("read_trace read error %d\n", t);
- return(-1);
+ return (-1);
}
}
@@ -1144,7 +1091,7 @@ size_t stlink_serial(struct libusb_device_handle *handle, struct libusb_device_d
serial[0] = '\0';
/* get the LANGID from String Descriptor Zero */
- int ret = libusb_get_string_descriptor(handle, 0, 0, desc_serial, sizeof(desc_serial));
+ int32_t ret = libusb_get_string_descriptor(handle, 0, 0, desc_serial, sizeof(desc_serial));
if (ret < 4) return 0;
uint32_t langid = desc_serial[2] | (desc_serial[3] << 8);
@@ -1163,7 +1110,7 @@ size_t stlink_serial(struct libusb_device_handle *handle, struct libusb_device_d
if (ret < 0) return 0;
} else if (len == ((STLINK_SERIAL_LENGTH / 2 + 1) * 2)) { /* len == 26 */
/* fix-up the buggy serial */
- for (unsigned int i = 0; i < STLINK_SERIAL_LENGTH; i += 2)
+ for (uint32_t i = 0; i < STLINK_SERIAL_LENGTH; i += 2)
sprintf(serial + i, "%02X", desc_serial[i + 2]);
serial[STLINK_SERIAL_LENGTH] = '\0';
} else {
@@ -1173,17 +1120,24 @@ size_t stlink_serial(struct libusb_device_handle *handle, struct libusb_device_d
return strlen(serial);
}
-stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect, char serial[STLINK_SERIAL_BUFFER_SIZE], int freq) {
+/**
+ * Open a stlink
+ * @param verbose Verbosity loglevel
+ * @param connect Type of connect to target
+ * @param serial Serial number to search for, when NULL the first stlink found is opened (binary format)
+ * @retval NULL Error while opening the stlink
+ * @retval !NULL Stlink found and ready to use
+ */
+stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect, char serial[STLINK_SERIAL_BUFFER_SIZE], int32_t freq) {
stlink_t* sl = NULL;
struct stlink_libusb* slu = NULL;
- int ret = -1;
- int config;
+ int32_t ret = -1;
+ int32_t config;
sl = calloc(1, sizeof(stlink_t));
- slu = calloc(1, sizeof(struct stlink_libusb));
-
if (sl == NULL) { goto on_malloc_error; }
+ slu = calloc(1, sizeof(struct stlink_libusb));
if (slu == NULL) { goto on_malloc_error; }
ugly_init(verbose);
@@ -1203,54 +1157,22 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect,
libusb_set_option(slu->libusb_ctx, LIBUSB_OPTION_LOG_LEVEL, ugly_libusb_log_level(verbose));
#endif
- libusb_device **list;
- // TODO: We should use ssize_t and use it as a counter if > 0.
- // As per libusb API: ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device ***list)
- int cnt = (int)libusb_get_device_list(slu->libusb_ctx, &list);
+ libusb_device **list = NULL;
+ ssize_t cnt = libusb_get_device_list(slu->libusb_ctx, &list);
struct libusb_device_descriptor desc;
- int devBus = 0;
- int devAddr = 0;
-
- // TODO: Reading a environment variable in a usb open function is not very nice, this should
- // be refactored and moved into the CLI tools, and instead of giving USB_BUS:USB_ADDR a real
- // stlink serial string should be passed to this function. Probably people are using this
- // but this is very odd because as programmer can change to multiple busses and it is better
- // to detect them based on serial.
- char *device = getenv("STLINK_DEVICE");
-
- if (device) {
- char *c = strchr(device, ':');
-
- if (c == NULL) {
- WLOG("STLINK_DEVICE must be <USB_BUS>:<USB_ADDR> format\n");
- goto on_error;
- }
-
- devBus = atoi(device);
- *c++ = 0;
- devAddr = atoi(c);
- ILOG("bus %03d dev %03d\n", devBus, devAddr);
- }
- while (cnt--) {
+ while (cnt-- > 0) {
struct libusb_device_handle *handle;
libusb_get_device_descriptor(list[cnt], &desc);
if (desc.idVendor != STLINK_USB_VID_ST) { continue; }
- if (devBus && devAddr) {
- if ((libusb_get_bus_number(list[cnt]) != devBus) ||
- (libusb_get_device_address(list[cnt]) != devAddr)) {
- continue;
- }
- }
-
ret = libusb_open(list[cnt], &handle);
if (ret) { continue; } // could not open device
- size_t serial_len = stlink_serial(handle, &desc, sl->serial);
+ uint32_t serial_len = stlink_serial(handle, &desc, sl->serial);
libusb_close(handle);
@@ -1272,7 +1194,8 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect,
}
if (cnt < 0) {
- WLOG ("Couldn't find %s ST-Link devices\n", (devBus && devAddr) ? "matched" : "any");
+ WLOG ("Couldn't find any ST-Link devices\n");
+ libusb_free_device_list(list, 1);
goto on_error;
} else {
ret = libusb_open(list[cnt], &slu->usb_handle);
@@ -1290,6 +1213,8 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect,
libusb_free_device_list(list, 1);
+// libusb_kernel_driver_active is not available on Windows.
+#if !defined(_WIN32)
if (libusb_kernel_driver_active(slu->usb_handle, 0) == 1) {
ret = libusb_detach_kernel_driver(slu->usb_handle, 0);
@@ -1298,6 +1223,7 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect,
goto on_libusb_error;
}
}
+#endif // NOT _WIN32
if (libusb_get_configuration(slu->usb_handle, &config)) {
// this may fail for a previous configured device
@@ -1329,7 +1255,8 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect,
desc.idProduct == STLINK_USB_PID_STLINK_V3_USBLOADER ||
desc.idProduct == STLINK_USB_PID_STLINK_V3E_PID ||
desc.idProduct == STLINK_USB_PID_STLINK_V3S_PID ||
- desc.idProduct == STLINK_USB_PID_STLINK_V3_2VCP_PID) {
+ desc.idProduct == STLINK_USB_PID_STLINK_V3_2VCP_PID ||
+ desc.idProduct == STLINK_USB_PID_STLINK_V3_NO_MSD_PID) {
slu->ep_req = 1 /* ep req */ | LIBUSB_ENDPOINT_OUT;
slu->ep_trace = 2 | LIBUSB_ENDPOINT_IN;
} else {
@@ -1343,11 +1270,22 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect,
// initialize stlink version (sl->version)
stlink_version(sl);
- if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
- // this seems to work, and is unnecessary information for the user.
- // demoted to debug -- REW
+ int32_t mode = stlink_current_mode(sl);
+ if (mode == STLINK_DEV_DFU_MODE) {
DLOG("-- exit_dfu_mode\n");
- stlink_exit_dfu_mode(sl);
+ _stlink_usb_exit_dfu_mode(sl);
+ }
+
+ if (connect == CONNECT_UNDER_RESET) {
+ // for the connect under reset only
+ // OpenOДD says (official documentation is not available) that
+ // the NRST pin must be pull down before selecting the SWD/JTAG mode
+ if (mode == STLINK_DEV_DEBUG_MODE) {
+ DLOG("-- exit_debug_mode\n");
+ _stlink_usb_exit_debug_mode(sl);
+ }
+
+ _stlink_usb_jtag_reset(sl, STLINK_DEBUG_APIV2_DRIVE_NRST_LOW);
}
sl->freq = freq;
@@ -1355,39 +1293,36 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, enum connect_type connect,
// should be done at this speed too
// set the stlink clock speed (default is 1800kHz)
DLOG("JTAG/SWD freq set to %d\n", freq);
- stlink_set_swdclk(sl, freq);
+ _stlink_usb_set_swdclk(sl, freq);
stlink_target_connect(sl, connect);
- return(sl);
+ return (sl);
on_libusb_error:
stlink_close(sl);
- return(NULL);
+ return (NULL);
on_error:
-
if (slu->libusb_ctx) { libusb_exit(slu->libusb_ctx); }
on_malloc_error:
-
if (sl != NULL) { free(sl); }
-
if (slu != NULL) { free(slu); }
- return(NULL);
+ return (NULL);
}
-static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[], enum connect_type connect, int freq) {
+static uint32_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[], enum connect_type connect, int32_t freq) {
stlink_t **_sldevs;
libusb_device *dev;
- int i = 0;
- size_t slcnt = 0;
- size_t slcur = 0;
+ int32_t i = 0;
+ uint32_t slcnt = 0;
+ uint32_t slcur = 0;
/* Count STLINKs */
while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
- int ret = libusb_get_device_descriptor(dev, &desc);
+ int32_t ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0) {
WLOG("failed to get libusb device descriptor (libusb error: %d)\n", ret);
@@ -1408,7 +1343,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[], e
if (!_sldevs) {
*sldevs = NULL;
- return(0);
+ return (0);
}
/* Open STLINKS and attach them to list */
@@ -1416,7 +1351,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[], e
while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
- int ret = libusb_get_device_descriptor(dev, &desc);
+ int32_t ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0) {
WLOG("failed to get libusb device descriptor (libusb error: %d)\n", ret);
@@ -1440,7 +1375,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[], e
break;
}
- size_t serial_len = stlink_serial(handle, &desc, serial);
+ uint32_t serial_len = stlink_serial(handle, &desc, serial);
libusb_close(handle);
@@ -1458,24 +1393,24 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[], e
*sldevs = _sldevs;
- return(slcur);
+ return (slcur);
}
-size_t stlink_probe_usb(stlink_t **stdevs[], enum connect_type connect, int freq) {
+size_t stlink_probe_usb(stlink_t **stdevs[], enum connect_type connect, int32_t freq) {
libusb_device **devs;
stlink_t **sldevs;
- size_t slcnt = 0;
- int r;
+ uint32_t slcnt = 0;
+ int32_t r;
ssize_t cnt;
r = libusb_init(NULL);
- if (r < 0) { return(0); }
+ if (r < 0) { return (0); }
cnt = libusb_get_device_list(NULL, &devs);
- if (cnt < 0) { return(0); }
+ if (cnt < 0) { return (0); }
slcnt = stlink_probe_usb_devs(devs, &sldevs, connect, freq);
libusb_free_device_list(devs, 1);
@@ -1484,13 +1419,13 @@ size_t stlink_probe_usb(stlink_t **stdevs[], enum connect_type connect, int freq
*stdevs = sldevs;
- return(slcnt);
+ return (slcnt);
}
-void stlink_probe_usb_free(stlink_t ***stdevs, size_t size) {
+void stlink_probe_usb_free(stlink_t ***stdevs, uint32_t size) {
if (stdevs == NULL || *stdevs == NULL || size == 0) { return; }
- for (size_t n = 0; n < size; n++) { stlink_close((*stdevs)[n]); }
+ for (uint32_t n = 0; n < size; n++) { stlink_close((*stdevs)[n]); }
free(*stdevs);
*stdevs = NULL;