static int stlink_usb_halt(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->jtag_api == STLINK_JTAG_API_V2) { res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); if (res == ERROR_OK && h->trace.enabled) stlink_usb_trace_disable(handle); return res; } stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_FORCEDEBUG; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }
static int stlink_usb_run(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->jtag_api == STLINK_JTAG_API_V2) { res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_DEBUGEN); /* Try to start tracing, if requested */ if (res == ERROR_OK && h->trace.source_hz && !h->trace.enabled) { if (stlink_usb_trace_enable(handle) == ERROR_OK) LOG_DEBUG("Tracing: enabled\n"); else LOG_ERROR("Tracing: enable failed\n"); } return res; } stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_RUNCORE; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }
static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, uint8_t *buffer) { int res; uint16_t read_len = len; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, read_len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_8BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; /* we need to fix read length for single bytes */ if (read_len == 1) read_len++; res = stlink_usb_xfer(handle, h->databuf, read_len); if (res != ERROR_OK) return res; memcpy(buffer, h->databuf, len); return stlink_usb_get_rw_status(handle); }
static int stlink_usb_write_reg(void *handle, int num, uint32_t val) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEREG; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEREG; h->cmdbuf[h->cmdidx++] = num; h_u32_to_le(h->cmdbuf+h->cmdidx, val); h->cmdidx += 4; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }
static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* data must be a multiple of 4 and word aligned */ if (len % 4 || addr % 4) { LOG_DEBUG("Invalid data alignment"); return ERROR_TARGET_UNALIGNED_ACCESS; } stlink_usb_init_buffer(handle, h->tx_ep, len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_32BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; res = stlink_usb_xfer(handle, buffer, len); if (res != ERROR_OK) return res; return stlink_usb_get_rw_status(handle); }
static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* max 8bit read/write is 64bytes */ if (len > STLINK_MAX_RW8) { LOG_DEBUG("max buffer length exceeded"); return ERROR_FAIL; } stlink_usb_init_buffer(handle, h->tx_ep, len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_8BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; res = stlink_usb_xfer(handle, buffer, len); if (res != ERROR_OK) return res; return stlink_usb_get_rw_status(handle); }
static int stlink_usb_check_voltage(void *handle, float *target_voltage) { struct stlink_usb_handle_s *h = handle; uint32_t adc_results[2]; /* only supported by stlink/v2 and for firmware >= 13 */ if (h->version.stlink == 1 || h->version.jtag < 13) return ERROR_COMMAND_NOTFOUND; stlink_usb_init_buffer(handle, h->rx_ep, 8); h->cmdbuf[h->cmdidx++] = STLINK_GET_TARGET_VOLTAGE; int result = stlink_usb_xfer(handle, h->databuf, 8); if (result != ERROR_OK) return result; /* convert result */ adc_results[0] = le_to_h_u32(h->databuf); adc_results[1] = le_to_h_u32(h->databuf + 4); *target_voltage = 0; if (adc_results[0]) *target_voltage = 2 * ((float)adc_results[1]) * (float)(1.2 / adc_results[0]); LOG_INFO("Target voltage: %f", (double)*target_voltage); return ERROR_OK; }
static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, h->jtag_api == STLINK_JTAG_API_V1 ? 4 : 8); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READREG; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READREG; h->cmdbuf[h->cmdidx++] = num; res = stlink_usb_xfer(handle, h->databuf, h->jtag_api == STLINK_JTAG_API_V1 ? 4 : 8); if (res != ERROR_OK) return res; if (h->jtag_api == STLINK_JTAG_API_V1) *val = le_to_h_u32(h->databuf); else { *val = le_to_h_u32(h->databuf + 4); return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; } return ERROR_OK; }
static int stlink_usb_reset(void *handle) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_RESETSYS; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_RESETSYS; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; LOG_DEBUG("RESET: 0x%08X", h->databuf[0]); /* the following is not a error under swd (using hardware srst), so return success */ if (h->databuf[0] == STLINK_SWD_AP_WAIT || h->databuf[0] == STLINK_SWD_DP_WAIT) return ERROR_OK; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }
static int stlink_usb_xfer_v1_get_sense(void *handle) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, 16); h->cmdbuf[h->cmdidx++] = REQUEST_SENSE; h->cmdbuf[h->cmdidx++] = 0; h->cmdbuf[h->cmdidx++] = 0; h->cmdbuf[h->cmdidx++] = 0; h->cmdbuf[h->cmdidx++] = REQUEST_SENSE_LENGTH; res = stlink_usb_xfer_rw(handle, REQUEST_SENSE_LENGTH, h->databuf, 16); if (res != ERROR_OK) return res; if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; }
static enum target_state stlink_usb_state(void *handle) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; if (h->jtag_api == STLINK_JTAG_API_V2) return stlink_usb_v2_get_status(handle); stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_GETSTATUS; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return TARGET_UNKNOWN; if (h->databuf[0] == STLINK_CORE_RUNNING) return TARGET_RUNNING; if (h->databuf[0] == STLINK_CORE_HALTED) return TARGET_HALTED; return TARGET_UNKNOWN; }
static int stlink_usb_idcode(void *handle, uint32_t *idcode) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, 4); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID; res = stlink_usb_xfer(handle, h->databuf, 4); if (res != ERROR_OK) return res; *idcode = le_to_h_u32(h->databuf); LOG_DEBUG("IDCODE: 0x%08X", *idcode); return ERROR_OK; }
static int stlink_usb_v2_read_debug_reg(void *handle, uint32_t addr, uint32_t *val) { struct stlink_usb_handle_s *h; int res; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, 8); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READDEBUGREG; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; res = stlink_usb_xfer(handle, h->databuf, 8); if (res != ERROR_OK) return res; *val = le_to_h_u32(h->databuf + 4); return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }
static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; len *= 4; stlink_usb_init_buffer(handle, STLINK_TX_EP, len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_32BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; res = stlink_usb_xfer(handle, buffer, len); if (res != ERROR_OK) return res; return stlink_usb_get_rw_status(handle); }
static int stlink_usb_step(void *handle) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; if (h->jtag_api == STLINK_JTAG_API_V2) { /* TODO: this emulates the v1 api, it should really use a similar auto mask isr * that the cortex-m3 currently does. */ stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_MASKINTS|C_DEBUGEN); stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_STEP|C_MASKINTS|C_DEBUGEN); return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); } stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_STEPCORE; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }
static int stlink_usb_assert_srst(void *handle, int srst) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; if (h->jtag_api == STLINK_JTAG_API_V1) return ERROR_COMMAND_NOTFOUND; stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_DRIVE_NRST; h->cmdbuf[h->cmdidx++] = srst; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }
static void stlink_usb_trace_read(void *handle) { struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->trace.enabled && h->version.jtag >= STLINK_TRACE_MIN_VERSION) { int res; stlink_usb_init_buffer(handle, h->rx_ep, 10); 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); if (res == ERROR_OK) { uint8_t buf[STLINK_TRACE_SIZE]; size_t size = le_to_h_u16(h->databuf); if (size > 0) { size = size < sizeof(buf) ? size : sizeof(buf) - 1; res = stlink_usb_read_trace(handle, buf, size); if (res == ERROR_OK) { if (h->trace.output_f) { /* Log retrieved trace output */ if (fwrite(buf, 1, size, h->trace.output_f) > 0) fflush(h->trace.output_f); } } } } } }
static int stlink_usb_mode_leave(void *handle, enum stlink_mode type) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, STLINK_NULL_EP, 0); switch (type) { case STLINK_MODE_DEBUG_JTAG: case STLINK_MODE_DEBUG_SWD: h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_EXIT; break; case STLINK_MODE_DEBUG_SWIM: h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_SWIM_EXIT; break; case STLINK_MODE_DFU: h->cmdbuf[h->cmdidx++] = STLINK_DFU_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DFU_EXIT; break; case STLINK_MODE_MASS: default: return ERROR_FAIL; } res = stlink_usb_xfer(handle, 0, 0); if (res != ERROR_OK) return res; return ERROR_OK; }
static int stlink_usb_mode_enter(void *handle, enum stlink_mode type) { int res; int rx_size = 0; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; /* on api V2 we are able the read the latest command * status * TODO: we need the test on api V1 too */ if (h->jtag_api == STLINK_JTAG_API_V2) rx_size = 2; stlink_usb_init_buffer(handle, STLINK_RX_EP, rx_size); switch (type) { case STLINK_MODE_DEBUG_JTAG: h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_JTAG; break; case STLINK_MODE_DEBUG_SWD: h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_SWD; break; case STLINK_MODE_DEBUG_SWIM: h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER; break; case STLINK_MODE_DFU: case STLINK_MODE_MASS: default: return ERROR_FAIL; } res = stlink_usb_xfer(handle, h->databuf, rx_size); if (res != ERROR_OK) return res; res = stlink_usb_error_check(h); return res; }
static int stlink_usb_trace_enable(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->version.jtag >= STLINK_TRACE_MIN_VERSION) { uint32_t trace_hz; res = stlink_configure_target_trace_port(handle); if (res != ERROR_OK) LOG_ERROR("Unable to configure tracing on target\n"); trace_hz = h->trace.prescale > 0 ? h->trace.source_hz / (h->trace.prescale + 1) : h->trace.source_hz; stlink_usb_init_buffer(handle, h->rx_ep, 10); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_START_TRACE_RX; h_u16_to_le(h->cmdbuf+h->cmdidx, (uint16_t)STLINK_TRACE_SIZE); h->cmdidx += 2; h_u32_to_le(h->cmdbuf+h->cmdidx, trace_hz); h->cmdidx += 4; res = stlink_usb_xfer(handle, h->databuf, 2); if (res == ERROR_OK) { h->trace.enabled = true; LOG_DEBUG("Tracing: recording at %" PRIu32 "Hz\n", trace_hz); /* We need the trace read function to be called at a * high-enough frequency to ensure reasonable * "timeliness" in processing ITM/DWT data. * TODO: An alternative could be using the asynchronous * features of the libusb-1.0 API to queue up one or more * reads in advance and requeue them once they are * completed. */ target_register_timer_callback(stlink_usb_trace_read_callback, 1, 1, handle); } } else { LOG_ERROR("Tracing is not supported by this version."); res = ERROR_FAIL; } return res; }
static int stlink_usb_version(void *handle) { int res; uint16_t v; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; stlink_usb_init_buffer(handle, STLINK_RX_EP, 6); h->cmdbuf[h->cmdidx++] = STLINK_GET_VERSION; res = stlink_usb_xfer(handle, h->databuf, 6); if (res != ERROR_OK) return res; v = (h->databuf[0] << 8) | h->databuf[1]; h->version.stlink = (v >> 12) & 0x0f; h->version.jtag = (v >> 6) & 0x3f; h->version.swim = v & 0x3f; h->vid = buf_get_u32(h->databuf, 16, 16); h->pid = buf_get_u32(h->databuf, 32, 16); /* set the supported jtag api version * API V2 is supported since JTAG V11 */ if (h->version.jtag >= 11) h->version.jtag_api_max = STLINK_JTAG_API_V2; else h->version.jtag_api_max = STLINK_JTAG_API_V1; LOG_DEBUG("STLINK v%d JTAG v%d API v%d SWIM v%d VID 0x%04X PID 0x%04X", h->version.stlink, h->version.jtag, (h->version.jtag_api_max == STLINK_JTAG_API_V1) ? 1 : 2, h->version.swim, h->vid, h->pid); return ERROR_OK; }
static enum target_state stlink_usb_state(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->reconnect_pending) { LOG_INFO("Previous state query failed, trying to reconnect"); res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport)); if (res != ERROR_OK) return TARGET_UNKNOWN; h->reconnect_pending = false; } if (h->jtag_api == STLINK_JTAG_API_V2) { res = stlink_usb_v2_get_status(handle); if (res == TARGET_UNKNOWN) h->reconnect_pending = true; return res; } stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_GETSTATUS; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return TARGET_UNKNOWN; if (h->databuf[0] == STLINK_CORE_RUNNING) return TARGET_RUNNING; if (h->databuf[0] == STLINK_CORE_HALTED) return TARGET_HALTED; h->reconnect_pending = true; return TARGET_UNKNOWN; }
static int stlink_usb_current_mode(void *handle, uint8_t *mode) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_GET_CURRENT_MODE; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; *mode = h->databuf[0]; return ERROR_OK; }
static void stlink_usb_trace_disable(void *handle) { int res = ERROR_OK; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); assert(h->version.jtag >= STLINK_TRACE_MIN_VERSION); LOG_DEBUG("Tracing: disable\n"); 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); if (res == ERROR_OK) { h->trace.enabled = false; target_unregister_timer_callback(stlink_usb_trace_read_callback, handle); } }
static int stlink_usb_read_regs(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); stlink_usb_init_buffer(handle, h->rx_ep, 84); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READALLREGS; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READALLREGS; res = stlink_usb_xfer(handle, h->databuf, 84); if (res != ERROR_OK) return res; return ERROR_OK; }
static int stlink_usb_get_rw_status(void *handle) { int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); if (h->jtag_api == STLINK_JTAG_API_V1) return ERROR_OK; stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : res; }
static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, uint8_t *buffer) { int res; uint16_t read_len = len; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); /* max 8bit read/write is 64bytes */ if (len > STLINK_MAX_RW8) { LOG_DEBUG("max buffer length exceeded"); return ERROR_FAIL; } stlink_usb_init_buffer(handle, h->rx_ep, read_len); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_8BIT; h_u32_to_le(h->cmdbuf+h->cmdidx, addr); h->cmdidx += 4; h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; /* we need to fix read length for single bytes */ if (read_len == 1) read_len++; res = stlink_usb_xfer(handle, h->databuf, read_len); if (res != ERROR_OK) return res; memcpy(buffer, h->databuf, len); return stlink_usb_get_rw_status(handle); }
static int stlink_usb_halt(void *handle) { int res; struct stlink_usb_handle_s *h; assert(handle != NULL); h = (struct stlink_usb_handle_s *)handle; if (h->jtag_api == STLINK_JTAG_API_V2) return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_FORCEDEBUG; res = stlink_usb_xfer(handle, h->databuf, 2); if (res != ERROR_OK) return res; return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; }