#include <jtag/stlink/stlink_interface.h>
#include <target/target.h>
+#include <target/cortex_m.h>
+
#include "libusb_common.h"
#define ENDPOINT_IN 0x80
#define STLINK_DEBUG_APIV2_RESETSYS 0x32
#define STLINK_DEBUG_APIV2_READREG 0x33
#define STLINK_DEBUG_APIV2_WRITEREG 0x34
+#define STLINK_DEBUG_APIV2_WRITEDEBUGREG 0x35
+#define STLINK_DEBUG_APIV2_READDEBUGREG 0x36
#define STLINK_DEBUG_APIV2_READALLREGS 0x3A
-
+#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS 0x3B
#define STLINK_DEBUG_APIV2_DRIVE_NRST 0x3C
#define STLINK_DEBUG_APIV2_DRIVE_NRST_LOW 0x00
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 %04X PID %04X",
+ 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,
if (res != ERROR_OK)
return res;
- LOG_DEBUG("MODE: %02X", mode);
+ LOG_DEBUG("MODE: 0x%02X", mode);
/* try to exit current mode */
switch (mode) {
if (res != ERROR_OK)
return res;
- LOG_DEBUG("MODE: %02X", mode);
+ LOG_DEBUG("MODE: 0x%02X", mode);
/* set selected mode */
switch (h->transport) {
if (res != ERROR_OK)
return res;
- LOG_DEBUG("MODE: %02X", mode);
+ LOG_DEBUG("MODE: 0x%02X", mode);
return ERROR_OK;
}
*idcode = le_to_h_u32(h->databuf);
- LOG_DEBUG("IDCODE: %08X", *idcode);
+ 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_debug_reg(void *handle, uint32_t addr, 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_WRITEDEBUGREG;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEDEBUGREG;
+ h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
+ h->cmdidx += 4;
+ 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 enum target_state stlink_usb_v2_get_status(void *handle)
+{
+ int result;
+ uint32_t status;
+
+ result = stlink_usb_v2_read_debug_reg(handle, DCB_DHCSR, &status);
+ if (result != ERROR_OK)
+ return TARGET_UNKNOWN;
+
+ if (status & S_HALT)
+ return TARGET_HALTED;
+
+ return TARGET_RUNNING;
+}
+
/** */
static enum target_state stlink_usb_state(void *handle)
{
h = (struct stlink_usb_handle_s *)handle;
if (h->jtag_api == STLINK_JTAG_API_V2)
- return TARGET_UNKNOWN;
+ return stlink_usb_v2_get_status(handle);
stlink_usb_init_buffer(handle, STLINK_RX_EP, 2);
if (res != ERROR_OK)
return res;
- LOG_DEBUG("RESET: %08X", h->databuf[0]);
+ LOG_DEBUG("RESET: 0x%08X", h->databuf[0]);
- return ERROR_OK;
+ return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
}
/** */
h = (struct stlink_usb_handle_s *)handle;
if (h->jtag_api == STLINK_JTAG_API_V2)
- return ERROR_FAIL;
+ return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_DEBUGEN);
stlink_usb_init_buffer(handle, STLINK_RX_EP, 2);
if (res != ERROR_OK)
return res;
- return ERROR_OK;
+ return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
}
/** */
h = (struct stlink_usb_handle_s *)handle;
if (h->jtag_api == STLINK_JTAG_API_V2)
- return ERROR_FAIL;
+ return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN);
stlink_usb_init_buffer(handle, STLINK_RX_EP, 2);
if (res != ERROR_OK)
return res;
- return ERROR_OK;
+ return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
}
/** */
h = (struct stlink_usb_handle_s *)handle;
if (h->jtag_api == STLINK_JTAG_API_V2)
- return ERROR_FAIL;
+ return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_STEP|C_DEBUGEN);
stlink_usb_init_buffer(handle, STLINK_RX_EP, 2);
if (res != ERROR_OK)
return res;
- return ERROR_OK;
+ return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
}
/** */
h = (struct stlink_usb_handle_s *)handle;
- stlink_usb_init_buffer(handle, STLINK_RX_EP, 4);
+ 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_APIV2_READREG;
h->cmdbuf[h->cmdidx++] = num;
- res = stlink_usb_xfer(handle, h->databuf, 4);
+ res = stlink_usb_xfer(handle, h->databuf, h->jtag_api == STLINK_JTAG_API_V1 ? 4 : 8);
if (res != ERROR_OK)
return res;
- *val = le_to_h_u32(h->databuf);
+ 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;
}
if (res != ERROR_OK)
return res;
- return ERROR_OK;
+ return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
+}
+
+static int stlink_usb_get_rw_status(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_V1)
+ return ERROR_OK;
+
+ stlink_usb_init_buffer(handle, STLINK_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;
}
/** */
memcpy(buffer, h->databuf, len);
- return ERROR_OK;
+ return stlink_usb_get_rw_status(handle);
}
/** */
h_u16_to_le(h->cmdbuf+h->cmdidx, len);
h->cmdidx += 2;
- res = stlink_usb_xfer(handle, (uint8_t *) buffer, len);
+ res = stlink_usb_xfer(handle, buffer, len);
if (res != ERROR_OK)
return res;
- return ERROR_OK;
+ return stlink_usb_get_rw_status(handle);
}
/** */
static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
- uint32_t *buffer)
+ uint8_t *buffer)
{
int res;
struct stlink_usb_handle_s *h;
memcpy(buffer, h->databuf, len);
- return ERROR_OK;
+ return stlink_usb_get_rw_status(handle);
}
/** */
static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
- const uint32_t *buffer)
+ const uint8_t *buffer)
{
int res;
struct stlink_usb_handle_s *h;
h_u16_to_le(h->cmdbuf+h->cmdidx, len);
h->cmdidx += 2;
- res = stlink_usb_xfer(handle, (uint8_t *) buffer, len);
+ res = stlink_usb_xfer(handle, buffer, len);
if (res != ERROR_OK)
return res;
- return ERROR_OK;
+ return stlink_usb_get_rw_status(handle);
}
/** */
const uint16_t vids[] = { param->vid, 0 };
const uint16_t pids[] = { param->pid, 0 };
- LOG_DEBUG("transport: %d vid: %04x pid: %04x", param->transport,
+ LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport,
param->vid, param->pid);
if (jtag_libusb_open(vids, pids, &h->fd) != ERROR_OK) {
/* compare usb vid/pid */
if ((param->vid != h->vid) || (param->pid != h->pid))
- LOG_INFO("vid/pid are not identical: %04X/%04X %04X/%04X",
+ LOG_INFO("vid/pid are not identical: 0x%04X/0x%04X 0x%04X/0x%04X",
param->vid, param->pid,
h->vid, h->pid);
return err;
}
- /* set the used jtag api */
- h->jtag_api = STLINK_JTAG_API_V1;
+ /* set the used jtag api, this will default to the newest supported version */
+ h->jtag_api = h->version.jtag_api_max;
/* initialize the debug hardware */
err = stlink_usb_init_mode(h);