+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
printf("device: 0x%04x, 0x%04x\n", desc.idVendor, desc.idProduct);
- if (desc.idVendor != 0x0483)
+ if (desc.idVendor != USB_ST_VID)
return 0;
- if (desc.idProduct != 0x3748)
+ if (desc.idProduct != USB_STLINK_32L_PID)
return 0;
return 1;
}
-void _stlink_usb_version(stlink_t * sl) {
+void _stlink_usb_version(stlink_t *sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const buf = sl->q_buf;
ssize_t size;
buf[0] = STLINK_GET_VERSION;
buf[1] = 0x80;
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
#if 1 /* DEBUG */
{
- unsigned int i;
+ ssize_t i;
for (i = 0; i < size; ++i) printf("%02x", buf[i]);
printf("\n");
}
}
void _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
- DD(sl, "oops! no write32 support yet, wanted to write %d bytes to %#x\n",
- len, addr);
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ unsigned char *cmd_buf = sl->c_buf;
+
+ memset(cmd_buf, 0, STLINK_CMD_SIZE);
+ cmd_buf[0] = STLINK_DEBUG_COMMAND;
+ cmd_buf[1] = STLINK_DEBUG_WRITEMEM_32BIT;
+ write_uint32(cmd_buf + 2, addr);
+ write_uint16(cmd_buf + 6, len);
+ send_only(slu, cmd_buf, STLINK_CMD_SIZE);
+
+ assert((len & 3) == 0);
+ stlink_print_data(sl);
+ send_only(slu, buf, len);
+
}
void _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
- DD(sl, "oops! no write8 support yet, wanted to write %d bytes to %#x\n",
- len, addr);
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ unsigned char *cmd_buf = sl->c_buf;
+
+ memset(cmd_buf, 0, STLINK_CMD_SIZE);
+ cmd_buf[0] = STLINK_DEBUG_COMMAND;
+ cmd_buf[1] = STLINK_DEBUG_WRITEMEM_8BIT;
+ write_uint32(cmd_buf + 2, addr);
+ write_uint16(cmd_buf + 6, len);
+ send_only(slu, cmd_buf, STLINK_CMD_SIZE);
+
+ stlink_print_data(sl);
+ send_only(slu, buf, len);
}
int _stlink_usb_current_mode(stlink_t * sl) {
- int mode = -1;
-
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const buf = sl->q_buf;
ssize_t size;
-
memset(buf, 0, sizeof (sl->q_buf));
-
buf[0] = STLINK_GET_CURRENT_MODE;
-
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return -1;
}
-
- /* mode = (int)read_uint16(buf, 0); */
- mode = (int) buf[0];
- DD(sl, "mode == 0x%x\n", mode);
- return mode;
+ return sl->q_buf[0];
}
void _stlink_usb_core_id(stlink_t * sl) {
buf[0] = STLINK_DEBUG_COMMAND;
buf[1] = STLINK_DEBUG_READCOREID;
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
buf[0] = STLINK_DEBUG_COMMAND;
buf[1] = STLINK_DEBUG_GETSTATUS;
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
}
-void _stlink_enter_swd_mode(stlink_t * sl) {
+void _stlink_usb_force_debug(stlink_t *sl) {
+ struct stlink_libusb *slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ ssize_t size;
+
+ memset(buf, 0, sizeof (sl->q_buf));
+
+ buf[0] = STLINK_DEBUG_COMMAND;
+ buf[1] = STLINK_DEBUG_FORCEDEBUG;
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+ if (size == -1) {
+ printf("[!] send_recv\n");
+ return;
+ }
+}
+
+
+void _stlink_usb_enter_swd_mode(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const buf = sl->q_buf;
ssize_t size;
memset(buf, 0, sizeof (sl->q_buf));
buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = 0x30; /* needed byte */
- buf[2] = STLINK_DEBUG_ENTER_JTAG;
+ buf[1] = STLINK_SWD_ENTER;
+ buf[2] = STLINK_DEBUG_ENTER_SWD;
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
}
-
}
void _stlink_usb_exit_dfu_mode(stlink_t* sl) {
}
}
+/**
+ * TODO - not convinced this does anything...
+ * @param sl
+ */
void _stlink_usb_reset(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const buf = sl->q_buf;
buf[0] = STLINK_DEBUG_COMMAND;
buf[1] = STLINK_DEBUG_RESETSYS;
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
buf[0] = STLINK_DEBUG_COMMAND;
buf[1] = STLINK_DEBUG_STEPCORE;
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
}
}
+/**
+ * This seems to do a good job of restarting things from the beginning?
+ * @param sl
+ */
void _stlink_usb_run(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const buf = sl->q_buf;
buf[0] = STLINK_DEBUG_COMMAND;
buf[1] = STLINK_DEBUG_RUNCORE;
- size = send_recv(slu, buf, 16, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
buf[0] = STLINK_DEBUG_COMMAND;
buf[1] = STLINK_DEBUG_READMEM_32BIT;
write_uint32(buf + 2, addr);
- write_uint16(buf + 6, len);
-#if 0
- /* windows usb logs show only one byte is used for length ... */
+
+ /* need to add +1 to len, otherwise get residue errors */
+ len += 1;
buf[6] = (uint8_t) len;
-#endif
+ buf[7] = (uint8_t) (len >> 8);
- size = send_recv(slu, buf, 0x10, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
if (size == -1) {
printf("[!] send_recv\n");
return;
stlink_print_data(sl);
}
-void _stlink_usb_read_all_regs(stlink_t *sl) {
- DD(sl, "oops! read_all_regs not implemented for USB!\n");
+
+#if 1 /* stlinkv1 */
+
+void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd_buf = sl->c_buf;
+ ssize_t size;
+ int i;
+
+ memset(cmd_buf, 0, STLINK_CMD_SIZE);
+ cmd_buf[0] = STLINK_DEBUG_COMMAND;
+ cmd_buf[1] = STLINK_DEBUG_READALLREGS;
+ size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 84);
+ if (size == -1) {
+ printf("[!] send_recv\n");
+ return;
+ }
+ sl->q_len = (size_t) size;
+ stlink_print_data(sl);
+ for(i=0; i<16; i++)
+ regp->r[i]= read_uint32(sl->q_buf, i*4);
+ regp->xpsr = read_uint32(sl->q_buf, 64);
+ regp->main_sp = read_uint32(sl->q_buf, 68);
+ regp->process_sp = read_uint32(sl->q_buf, 72);
+ regp->rw = read_uint32(sl->q_buf, 76);
+ regp->rw2 = read_uint32(sl->q_buf, 80);
+ if (sl->verbose < 2)
+ return;
+
+ DD(sl, "xpsr = 0x%08x\n", read_uint32(sl->q_buf, 64));
+ DD(sl, "main_sp = 0x%08x\n", read_uint32(sl->q_buf, 68));
+ DD(sl, "process_sp = 0x%08x\n", read_uint32(sl->q_buf, 72));
+ DD(sl, "rw = 0x%08x\n", read_uint32(sl->q_buf, 76));
+ DD(sl, "rw2 = 0x%08x\n", read_uint32(sl->q_buf, 80));
}
+#else /* stlinkv2 */
+
+static void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd_buf = sl->c_buf;
+ ssize_t size;
+ int i;
+
+#define STLINK_JTAG_COMMAND 0xf2
+#define STLINK_JTAG_READALLREGS2 0x3a
+ memset(cmd_buf, 0, STLINK_CMD_SIZE);
+ cmd_buf[0] = STLINK_JTAG_COMMAND;
+ cmd_buf[1] = STLINK_JTAG_READALLREGS2;
+ size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 84);
+
+ if (size == -1) {
+ printf("[!] send_recv\n");
+ return;
+ }
+
+ sl->q_len = (size_t) size;
+
+ for(i=0; i<16; i++)
+ regp->r[i]= read_uint32(sl->q_buf, i*4);
+
+ regp->xpsr = read_uint32(sl->q_buf, 64);
+ regp->main_sp = read_uint32(sl->q_buf, 68);
+ regp->process_sp = read_uint32(sl->q_buf, 72);
+ regp->rw = read_uint32(sl->q_buf, 76);
+ regp->rw2 = read_uint32(sl->q_buf, 80);
+}
+
+#endif /* stlinkv1 */
+
void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
- DD(sl, "oops! read_reg not implemented for USB! Wanted to read reg %d\n",
- r_idx);
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd_buf = sl->c_buf;
+ ssize_t size;
+ uint32_t r;
+
+ memset(cmd_buf, 0, STLINK_CMD_SIZE);
+ cmd_buf[0] = STLINK_DEBUG_COMMAND;
+ cmd_buf[1] = STLINK_DEBUG_READREG;
+ cmd_buf[2] = (uint8_t) r_idx;
+ size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 4);
+ if (size == -1) {
+ printf("[!] send_recv\n");
+ return;
+ }
+ sl->q_len = (size_t) size;
+ stlink_print_data(sl);
+ r = read_uint32(sl->q_buf, 0);
+ DD(sl, "r_idx (%2d) = 0x%08x\n", r_idx, r);
+
+ switch (r_idx) {
+ case 16:
+ regp->xpsr = r;
+ break;
+ case 17:
+ regp->main_sp = r;
+ break;
+ case 18:
+ regp->process_sp = r;
+ break;
+ case 19:
+ regp->rw = r; //XXX ?(primask, basemask etc.)
+ break;
+ case 20:
+ regp->rw2 = r; //XXX ?(primask, basemask etc.)
+ break;
+ default:
+ regp->r[r_idx] = r;
+ }
}
+
+#if 1 /* stlinkv1 */
+
void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
- DD(sl, "oops! write_reg not implemented for USB! Wanted to write %#x to %d\n",
- reg, idx);
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ unsigned char *cmd_buf = sl->c_buf;
+ ssize_t size;
+
+ memset(cmd_buf, 0, STLINK_CMD_SIZE);
+ cmd_buf[0] = STLINK_DEBUG_COMMAND;
+ cmd_buf[1] = STLINK_DEBUG_WRITEREG;
+ cmd_buf[2] = idx;
+ write_uint32(cmd_buf + 3, reg);
+ size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 2);
+ if (size == -1) {
+ printf("[!] send_recv\n");
+ return;
+ }
+ sl->q_len = (size_t) size;
+ stlink_print_data(sl);
+}
+
+#else /* stlinkv2 */
+
+void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const buf = sl->q_buf;
+ unsigned char *cmd_buf = sl->c_buf;
+ ssize_t size;
+
+#define STLINK_JTAG_WRITEREG2 0x34
+ memset(cmd_buf, 0, STLINK_CMD_SIZE);
+ cmd_buf[0] = STLINK_JTAG_COMMAND;
+ cmd_buf[1] = STLINK_JTAG_WRITEREG2;
+ cmd_buf[2] = idx;
+ write_uint32(cmd_buf + 3, reg);
+ size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 2);
+ if (size == -1) {
+ printf("[!] send_recv\n");
+ return;
+ }
+ sl->q_len = (size_t) size;
+ stlink_print_data(sl);
}
+#endif /* stlinkv1 */
stlink_backend_t _stlink_usb_backend = {
_stlink_usb_close,
_stlink_usb_exit_debug_mode,
- _stlink_enter_swd_mode,
- NULL,
+ _stlink_usb_enter_swd_mode,
+ NULL, // no enter_jtag_mode here...
_stlink_usb_exit_dfu_mode,
_stlink_usb_core_id,
_stlink_usb_reset,
_stlink_usb_read_reg,
_stlink_usb_write_reg,
_stlink_usb_step,
- _stlink_usb_current_mode
+ _stlink_usb_current_mode,
+ _stlink_usb_force_debug
};
stlink_t* sl = NULL;
struct stlink_libusb* slu = NULL;
+ /* unused */
+ dev_name = dev_name;
+
sl = malloc(sizeof (stlink_t));
slu = malloc(sizeof (struct stlink_libusb));
if (sl == NULL) goto on_error;
sl->backend = &_stlink_usb_backend;
sl->backend_data = slu;
+
+ /* flash memory settings */
+ sl->flash_base = STM32_FLASH_BASE;
+ sl->flash_size = STM32_FLASH_SIZE;
+ sl->flash_pgsz = STM32_FLASH_PGSZ;
+
+ /* system memory */
+ sl->sys_base = STM32_SYSTEM_BASE;
+ sl->sys_size = STM32_SYSTEM_SIZE;
+
+ /* sram memory settings */
+ sl->sram_base = STM32_SRAM_BASE;
+ sl->sram_size = STM32L_SRAM_SIZE;
+
/* success */
return sl;
if (sl != NULL) free(sl);
if (slu != NULL) free(slu);
return 0;
-}
\ No newline at end of file
+}
+