Added checking the command execution status

pull/1154/head
anton 2021-05-17 00:20:54 +05:00
rodzic 22fba0249f
commit 03ad4a434d
3 zmienionych plików z 135 dodań i 118 usunięć

Wyświetl plik

@ -83,6 +83,19 @@ enum target_state {
#define STLINK_F_HAS_DPBANKSEL (1 << 8)
#define STLINK_F_HAS_RW8_512BYTES (1 << 9)
/* Error code */
#define STLINK_DEBUG_ERR_OK 0x80
#define STLINK_DEBUG_ERR_FAULT 0x81
#define STLINK_DEBUG_ERR_AP_WAIT 0x10
#define STLINK_DEBUG_ERR_AP_FAULT 0x11
#define STLINK_DEBUG_ERR_AP_ERROR 0x12
#define STLINK_DEBUG_ERR_DP_WAIT 0x14
#define STLINK_DEBUG_ERR_DP_FAULT 0x15
#define STLINK_DEBUG_ERR_DP_ERROR 0x16
#define CMD_NO_RETRY 0
#define CMD_USE_RETRY 3
#define C_BUF_LEN 32
enum stlink_flash_type {

Wyświetl plik

@ -1443,12 +1443,10 @@ void stlink_close(stlink_t *sl) {
int stlink_exit_debug_mode(stlink_t *sl) {
DLOG("*** stlink_exit_debug_mode ***\n");
if (sl->flash_type != STLINK_FLASH_TYPE_UNKNOWN) {
if (sl->flash_type != STLINK_FLASH_TYPE_UNKNOWN &&
sl->core_stat != TARGET_RESET) {
// stop debugging if the target has been identified
int ret = stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY);
if (ret == -1) {
return (ret);
}
stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY);
}
return (sl->backend->exit_debug_mode(sl));
@ -1684,7 +1682,7 @@ int stlink_load_device_params(stlink_t *sl) {
}
int stlink_jtag_reset(stlink_t *sl, int value) {
DLOG("*** stlink_jtag_reset ***\n");
DLOG("*** stlink_jtag_reset %d ***\n", value);
return (sl->backend->jtag_reset(sl, value));
}
@ -1768,6 +1766,8 @@ int stlink_reset(stlink_t *sl, enum reset_type type) {
DLOG("*** stlink_reset ***\n");
sl->core_stat = TARGET_RESET;
if (type == RESET_AUTO) {
// clear S_RESET_ST in DHCSR register for reset state detection
stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
@ -1781,9 +1781,7 @@ int stlink_reset(stlink_t *sl, enum reset_type type) {
usleep(100);
stlink_jtag_reset(sl, STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH);
}
if (sl->backend->reset(sl)) {
return (-1);
}
sl->backend->reset(sl);
usleep(10000);
}
@ -1793,8 +1791,8 @@ int stlink_reset(stlink_t *sl, enum reset_type type) {
* DDI0337E, p. 10-4, Debug Halting Control and Status Register */
dhcsr = 0;
stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) {
int res = stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0 && !res) {
// reset not done yet
// try reset through AIRCR so that NRST does not need to be connected
@ -1808,8 +1806,9 @@ int stlink_reset(stlink_t *sl, enum reset_type type) {
while (time_ms() < timeout) {
dhcsr = STLINK_REG_DHCSR_S_RESET_ST;
stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0)
if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) {
return (0);
}
}
return (-1);

Wyświetl plik

@ -84,50 +84,80 @@ 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) {
unsigned char* txbuf, size_t txsize, unsigned char* rxbuf,
size_t rxsize, bool check_error, int retry_cnt) {
// Note: txbuf and rxbuf can point to the same area
int res = 0;
int t;
int res, t, retry = 0;
int cmd = read_uint16(txbuf, (handle->protocoll == 1)?15:0);
t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, txbuf, (int)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 (rxsize != 0) {
t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, rxbuf, (int)rxsize, &res, 3000);
while (1) {
res = 0;
t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, txbuf, (int)txsize, &res, 3000);
if (t) {
printf("[!] send_recv read reply failed: %s\n", libusb_error_name(t));
return(-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 (t) {
printf("[!] send_recv read storage failed: %s\n", libusb_error_name(t));
ELOG("[!] send_recv send request failed: %s (command 0x%02X)\n", libusb_error_name(t), cmd);
return(-1);
} else if ((size_t)res != txsize) {
ELOG("[!] send_recv send request wrote %u bytes, instead of %u (command 0x%02X)\n",
(unsigned int)res, (unsigned int)txsize, cmd);
}
// The STLink doesn't seem to evaluate the sequence number.
handle->sg_transfer_idx++;
}
if (rxsize != 0) {
t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, rxbuf, (int)rxsize, &res, 3000);
return(res);
if (t) {
ELOG("[!] send_recv read reply failed: %s (command 0x%02X)\n", libusb_error_name(t), cmd);
return(-1);
}
/* Checking the command execution status stored in the first byte of the response */
if (handle->protocoll != 1 && check_error &&
rxbuf[0] != STLINK_DEBUG_ERR_OK) {
switch(rxbuf[0]) {
case STLINK_DEBUG_ERR_AP_WAIT:
case STLINK_DEBUG_ERR_DP_WAIT:
if (retry < retry_cnt) {
unsigned int delay_us = (1<<retry) * 1000;
DLOG("I/O: wait error (0x%02X) of command (0x%02X), delaying %u us and retry\n", rxbuf[0], cmd, delay_us);
usleep(delay_us);
retry++;
continue;
}
DLOG("I/O: wait error (0x%02X) of command (0x%02X)\n", rxbuf[0], cmd);
break;
case STLINK_DEBUG_ERR_FAULT: DLOG("I/O: response fault of command (0x%02X)\n", txbuf[1]); break;
case STLINK_DEBUG_ERR_AP_FAULT:
case STLINK_DEBUG_ERR_DP_FAULT: DLOG("I/O: fault status (0x%02X) of command (0x%02X)\n", rxbuf[0], cmd); break;
case STLINK_DEBUG_ERR_AP_ERROR:
case STLINK_DEBUG_ERR_DP_ERROR: DLOG("I/O: error status (0x%02X) of command (0x%02X)\n", rxbuf[0], cmd); break;
default: DLOG("I/O: error 0x%02X of command (0x%02X)\n", rxbuf[0], cmd); break;
}
return(-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 (t) {
ELOG("[!] send_recv read storage failed: %s (command 0x%02X)\n", libusb_error_name(t), cmd);
return(-1);
}
// The STLink doesn't seem to evaluate the sequence number.
handle->sg_transfer_idx++;
}
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));
return((int)send_recv(handle, terminate, txbuf, txsize, NULL, 0, false, CMD_NO_RETRY));
}
@ -149,7 +179,6 @@ 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);
}
@ -172,9 +201,8 @@ int _stlink_usb_version(stlink_t *sl) {
cmd[i++] = STLINK_GET_VERSION;
}
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, false, CMD_USE_RETRY);
if (size != (ssize_t)rep_len) {
printf("[!] send_recv STLINK_GET_VERSION\n");
return((int)size);
}
@ -193,10 +221,9 @@ int32_t _stlink_usb_target_voltage(stlink_t *sl) {
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, false, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_GET_TARGET_VOLTAGE\n");
if (size < 0) {
return(-1);
} else if (size != 8) {
printf("[!] wrong length STLINK_GET_TARGET_VOLTAGE\n");
@ -221,10 +248,9 @@ int _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
cmd[i++] = STLINK_DEBUG_COMMAND;
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, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_APIV2_READDEBUGREG\n");
if (size < 0) {
return((int)size);
}
@ -245,10 +271,9 @@ int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
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, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_APIV2_WRITEDEBUGREG\n");
if (size < 0) {
return((int)size);
}
@ -269,10 +294,10 @@ 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, true, CMD_NO_RETRY);
} 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, true, CMD_NO_RETRY);
}
if (ret < 0) { return(-1); }
@ -334,10 +359,9 @@ int _stlink_usb_current_mode(stlink_t * sl) {
int 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, false, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_GET_CURRENT_MODE\n");
if (size < 0) {
return(-1);
}
@ -362,10 +386,9 @@ 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, true, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_READCOREID\n");
if (size < 0) {
return(-1);
}
@ -408,10 +431,9 @@ int _stlink_usb_status(stlink_t * sl) {
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, false, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_GETSTATUS\n");
if (size < 0) {
return((int)size);
}
@ -450,10 +472,9 @@ int _stlink_usb_force_debug(stlink_t *sl) {
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_FORCEDEBUG;
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_FORCEDEBUG\n");
if (size < 0) {
return((int)size);
}
@ -472,10 +493,9 @@ int _stlink_usb_enter_swd_mode(stlink_t * sl) {
// 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);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_ENTER\n");
if (size < 0) {
return((int)size);
}
@ -518,10 +538,9 @@ 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);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_RESETSYS\n");
if (size < 0) {
return((int)size);
}
@ -539,10 +558,9 @@ int _stlink_usb_jtag_reset(stlink_t * sl, int value) {
cmd[i++] = STLINK_DEBUG_COMMAND;
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, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_APIV2_DRIVE_NRST\n");
if (size < 0) {
return((int)size);
}
@ -571,10 +589,9 @@ int _stlink_usb_step(stlink_t* sl) {
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_DEBUG_STEPCORE;
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_STEPCORE\n");
if (size < 0) {
return((int)size);
}
@ -607,10 +624,9 @@ int _stlink_usb_run(stlink_t* sl, enum run_type type) {
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, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_RUNCORE\n");
if (size < 0) {
return((int)size);
}
@ -655,10 +671,9 @@ 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);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_APIV2_SWD_SET_FREQ\n");
if (size < 0) {
return((int)size);
}
@ -671,10 +686,9 @@ int _stlink_usb_set_swdclk(stlink_t* sl, int clk_freq) {
cmd[i++] = STLINK_DEBUG_COMMAND;
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, true, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_APIV3_GET_COM_FREQ\n");
if (size < 0) {
return((int)size);
}
@ -702,10 +716,9 @@ 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);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, 8, true, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_APIV3_SET_COM_FREQ\n");
if (size < 0) {
return((int)size);
}
@ -747,10 +760,9 @@ int _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
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, false, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_READMEM_32BIT\n");
if (size < 0) {
return((int)size);
}
@ -776,10 +788,9 @@ 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, true, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_READALLREGS\n");
if (size < 0) {
return((int)size);
}
@ -827,10 +838,9 @@ 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, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_READREG\n");
if (size < 0) {
return((int)size);
}
@ -994,10 +1004,9 @@ 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);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, true, CMD_USE_RETRY);
if (size == -1) {
printf("[!] send_recv STLINK_DEBUG_WRITEREG\n");
if (size < 0) {
return((int)size);
}
@ -1020,10 +1029,9 @@ int _stlink_usb_enable_trace(stlink_t* sl, uint32_t frequency) {
write_uint16(&cmd[i + 0], 2 * STLINK_TRACE_BUF_LEN);
write_uint32(&cmd[i + 2], frequency);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len, true, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_only STLINK_DEBUG_APIV2_START_TRACE_RX\n");
if (size < 0) {
return((int)size);
}
@ -1044,10 +1052,9 @@ int _stlink_usb_disable_trace(stlink_t* sl) {
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, true, CMD_NO_RETRY);
if (size == -1) {
printf("[!] send_only STLINK_DEBUG_APIV2_STOP_TRACE_RX\n");
if (size < 0) {
return((int)size);
}
@ -1066,14 +1073,12 @@ int _stlink_usb_read_trace(stlink_t* sl, uint8_t* buf, size_t size) {
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, false, CMD_NO_RETRY);
if (send_size == -1) {
printf("[!] send_recv STLINK_DEBUG_APIV2_GET_TRACE_NB\n");
if (send_size < 0) {
return((int)send_size);
}
if (send_size != 2) {
printf("[!] send_recv STLINK_DEBUG_APIV2_GET_TRACE_NB %d\n", (int)send_size);
} else if (send_size != 2) {
ELOG("STLINK_DEBUG_APIV2_GET_TRACE_NB reply size %d\n", (int)send_size);
return -1;
}