+/* request status from last swim request */
+static int stlink_swim_status(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ 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);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+/*
+ the purpose of this function is unknown...
+ capabilites? anyway for swim v6 it returns
+ 0001020600000000
+*/
+__attribute__((unused))
+static int stlink_swim_cap(void *handle, uint8_t *cap)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 8);
+ 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);
+ if (res != ERROR_OK)
+ return res;
+ memcpy(cap, h->databuf, 8);
+ return ERROR_OK;
+}
+
+/* debug dongle assert/deassert sreset line */
+static int stlink_swim_assert_reset(void *handle, int reset)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ if (!reset)
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ASSERT_RESET;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_DEASSERT_RESET;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/*
+ send swim enter seq
+ 1.3ms low then 750Hz then 1.5kHz
+*/
+static int stlink_swim_enter(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER_SEQ;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/* switch high/low speed swim */
+static int stlink_swim_speed(void *handle, int speed)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_SPEED;
+ if (speed)
+ h->cmdbuf[h->cmdidx++] = 1;
+ else
+ h->cmdbuf[h->cmdidx++] = 0;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/*
+ initiate srst from swim.
+ nrst is pulled low for 50us.
+*/
+static int stlink_swim_generate_rst(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_GEN_RST;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+/*
+ send resyncronize sequence
+ swim is pulled low for 16us
+ reply is 64 clks low
+*/
+static int stlink_swim_resync(void *handle)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_RESET;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+static int stlink_swim_writebytes(void *handle, uint32_t addr, uint32_t len, const uint8_t *data)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+ unsigned int i;
+ unsigned int datalen = 0;
+ int cmdsize = STLINK_CMD_SIZE_V2;
+
+ if (len > STLINK_DATA_SIZE)
+ return ERROR_FAIL;
+
+ if (h->version.stlink == 1)
+ cmdsize = STLINK_SG_SIZE;
+
+ stlink_usb_init_buffer(handle, h->tx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_WRITEMEM;
+ h_u16_to_be(h->cmdbuf+h->cmdidx, len);
+ h->cmdidx += 2;
+ h_u32_to_be(h->cmdbuf+h->cmdidx, addr);
+ h->cmdidx += 4;
+ for (i = 0; i < len; i++) {
+ if (h->cmdidx == cmdsize)
+ h->databuf[datalen++] = *(data++);
+ else
+ h->cmdbuf[h->cmdidx++] = *(data++);
+ }
+ if (h->version.stlink == 1)
+ stlink_usb_set_cbw_transfer_datalength(handle, datalen);
+
+ res = stlink_cmd_allow_retry(handle, h->databuf, datalen);
+ if (res != ERROR_OK)
+ return res;
+ return ERROR_OK;
+}
+
+static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint8_t *data)
+{
+ struct stlink_usb_handle_s *h = handle;
+ int res;
+
+ if (len > STLINK_DATA_SIZE)
+ return ERROR_FAIL;
+
+ stlink_usb_init_buffer(handle, h->rx_ep, 0);
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READMEM;
+ h_u16_to_be(h->cmdbuf+h->cmdidx, len);
+ h->cmdidx += 2;
+ h_u32_to_be(h->cmdbuf+h->cmdidx, addr);
+ h->cmdidx += 4;
+ res = stlink_cmd_allow_retry(handle, h->databuf, 0);
+ if (res != ERROR_OK)
+ return res;
+
+ 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);
+ if (res != ERROR_OK)
+ return res;
+
+ return ERROR_OK;
+}
+