#define STLINK_SWIM_READMEM 0x0b
#define STLINK_SWIM_READBUF 0x0c
-#define STLINK_DEBUG_ENTER_JTAG 0x00
#define STLINK_DEBUG_GETSTATUS 0x01
#define STLINK_DEBUG_FORCEDEBUG 0x02
#define STLINK_DEBUG_APIV1_RESETSYS 0x03
#define STLINK_DEBUG_APIV1_WRITEDEBUGREG 0x0f
#define STLINK_DEBUG_APIV1_SETWATCHPOINT 0x10
-#define STLINK_DEBUG_ENTER_JTAG 0x00
-#define STLINK_DEBUG_ENTER_SWD 0xa3
+#define STLINK_DEBUG_ENTER_JTAG_RESET 0x00
+#define STLINK_DEBUG_ENTER_SWD_NO_RESET 0xa3
+#define STLINK_DEBUG_ENTER_JTAG_NO_RESET 0xa4
#define STLINK_DEBUG_APIV1_ENTER 0x20
#define STLINK_DEBUG_EXIT 0x21
#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS 0x3B
#define STLINK_DEBUG_APIV2_DRIVE_NRST 0x3C
+#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS2 0x3E
+
#define STLINK_DEBUG_APIV2_START_TRACE_RX 0x40
#define STLINK_DEBUG_APIV2_STOP_TRACE_RX 0x41
#define STLINK_DEBUG_APIV2_GET_TRACE_NB 0x42
#define STLINK_F_HAS_SWD_SET_FREQ (1UL << 1)
#define STLINK_F_HAS_JTAG_SET_FREQ (1UL << 2)
#define STLINK_F_HAS_MEM_16BIT (1UL << 3)
+#define STLINK_F_HAS_GETLASTRWSTATUS2 (1UL << 4)
/* aliases */
#define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE
{
int res;
uint32_t flags;
- uint16_t v;
+ uint16_t version;
+ uint8_t v, x, y, jtag, swim, msd;
+ char v_str[4 * (1 + 3) + 1]; /* VvJjMmSs */
+ char *p;
struct stlink_usb_handle_s *h = handle;
assert(handle != NULL);
if (res != ERROR_OK)
return res;
- v = (h->databuf[0] << 8) | h->databuf[1];
+ version = be_to_h_u16(h->databuf);
+ v = (version >> 12) & 0x0f;
+ x = (version >> 6) & 0x3f;
+ y = version & 0x3f;
+
+ h->vid = le_to_h_u16(h->databuf + 2);
+ h->pid = le_to_h_u16(h->databuf + 4);
+
+ switch (h->pid) {
+ case STLINK_V2_1_PID:
+ case STLINK_V2_1_NO_MSD_PID:
+ /* JxMy : STM32 V2.1 - JTAG/SWD only */
+ jtag = x;
+ msd = y;
+ swim = 0;
+ break;
+ default:
+ jtag = x;
+ swim = y;
+ msd = 0;
+ break;
+ }
- 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);
+ h->version.stlink = v;
+ h->version.jtag = jtag;
+ h->version.swim = swim;
flags = 0;
switch (h->version.stlink) {
if (h->version.jtag >= 13)
flags |= STLINK_F_HAS_TRACE;
+ /* preferred API to get last R/W status from J15 */
+ if (h->version.jtag >= 15)
+ flags |= STLINK_F_HAS_GETLASTRWSTATUS2;
+
/* API to set SWD frequency from J22 */
if (h->version.jtag >= 22)
flags |= STLINK_F_HAS_SWD_SET_FREQ;
}
h->version.flags = flags;
- LOG_INFO("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 == STLINK_JTAG_API_V1) ? 1 : 2,
- h->version.swim,
+ p = v_str;
+ p += sprintf(p, "V%d", v);
+ if (jtag || !msd)
+ p += sprintf(p, "J%d", jtag);
+ if (msd)
+ p += sprintf(p, "M%d", msd);
+ if (swim || !msd)
+ p += sprintf(p, "S%d", swim);
+
+ LOG_INFO("STLINK %s (API v%d) VID:PID %04X:%04X",
+ v_str,
+ h->version.jtag_api,
h->vid,
h->pid);
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;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_JTAG_NO_RESET;
break;
case STLINK_MODE_DEBUG_SWD:
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
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;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_SWD_NO_RESET;
break;
case STLINK_MODE_DEBUG_SWIM:
h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
stlink_usb_init_buffer(handle, h->rx_ep, 2);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS;
+ if (h->version.flags & STLINK_F_HAS_GETLASTRWSTATUS2) {
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS2;
- res = stlink_usb_xfer(handle, h->databuf, 2);
+ res = stlink_usb_xfer(handle, h->databuf, 12);
+ } else {
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS;
+
+ res = stlink_usb_xfer(handle, h->databuf, 2);
+ }
if (res != ERROR_OK)
return res;