]> git.sur5r.net Git - openocd/blobdiff - src/jtag/drivers/stlink_usb.c
stlink: fix stlink api2 single step
[openocd] / src / jtag / drivers / stlink_usb.c
index 98eeb09029d8de9584097a3ab60935d34c4704d6..708b24b41c8fc00056453dc42dc5e6209b1e1847 100644 (file)
@@ -32,6 +32,8 @@
 #include <jtag/stlink/stlink_interface.h>
 #include <target/target.h>
 
+#include <target/cortex_m.h>
+
 #include "libusb_common.h"
 
 #define ENDPOINT_IN    0x80
@@ -46,7 +48,7 @@
 #define STLINK_CMD_SIZE_V1     (10)
 
 enum stlink_jtag_api_version {
-       STLINK_JTAG_API_V1 = 0,
+       STLINK_JTAG_API_V1 = 1,
        STLINK_JTAG_API_V2,
 };
 
@@ -142,9 +144,11 @@ struct stlink_usb_handle_s {
 #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
@@ -396,15 +400,14 @@ static int stlink_usb_version(void *handle)
        h->pid = buf_get_u32(h->databuf, 32, 16);
 
        /* set the supported jtag api version
-        * V1 doesn't support API V2 at all
-        * V2 support API V2 since JTAG V13
+        * API V2 is supported since JTAG V11
         */
-       if ((h->version.stlink == 2) && (h->version.jtag > 12))
+       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 %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,
@@ -552,7 +555,7 @@ static int stlink_usb_init_mode(void *handle)
        if (res != ERROR_OK)
                return res;
 
-       LOG_DEBUG("MODE: %02X", mode);
+       LOG_DEBUG("MODE: 0x%02X", mode);
 
        /* try to exit current mode */
        switch (mode) {
@@ -584,7 +587,7 @@ static int stlink_usb_init_mode(void *handle)
        if (res != ERROR_OK)
                return res;
 
-       LOG_DEBUG("MODE: %02X", mode);
+       LOG_DEBUG("MODE: 0x%02X", mode);
 
        /* set selected mode */
        switch (h->transport) {
@@ -617,7 +620,7 @@ static int stlink_usb_init_mode(void *handle)
        if (res != ERROR_OK)
                return res;
 
-       LOG_DEBUG("MODE: %02X", mode);
+       LOG_DEBUG("MODE: 0x%02X", mode);
 
        return ERROR_OK;
 }
@@ -644,11 +647,83 @@ static int stlink_usb_idcode(void *handle, uint32_t *idcode)
 
        *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;
+       else if (status & S_RESET_ST)
+               return TARGET_RESET;
+
+       return TARGET_RUNNING;
+}
+
 /** */
 static enum target_state stlink_usb_state(void *handle)
 {
@@ -660,7 +735,7 @@ 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);
 
@@ -704,9 +779,35 @@ static int stlink_usb_reset(void *handle)
        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;
+}
+
+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;
 }
 
 /** */
@@ -720,7 +821,7 @@ static int stlink_usb_run(void *handle)
        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);
 
@@ -732,7 +833,7 @@ static int stlink_usb_run(void *handle)
        if (res != ERROR_OK)
                return res;
 
-       return ERROR_OK;
+       return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
 }
 
 /** */
@@ -746,7 +847,7 @@ static int stlink_usb_halt(void *handle)
        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);
 
@@ -758,7 +859,7 @@ static int stlink_usb_halt(void *handle)
        if (res != ERROR_OK)
                return res;
 
-       return ERROR_OK;
+       return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
 }
 
 /** */
@@ -771,8 +872,13 @@ static int stlink_usb_step(void *handle)
 
        h = (struct stlink_usb_handle_s *)handle;
 
-       if (h->jtag_api == STLINK_JTAG_API_V2)
-               return ERROR_FAIL;
+       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);
 
@@ -784,7 +890,7 @@ static int stlink_usb_step(void *handle)
        if (res != ERROR_OK)
                return res;
 
-       return ERROR_OK;
+       return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL;
 }
 
 /** */
@@ -823,7 +929,7 @@ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val)
 
        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)
@@ -832,12 +938,17 @@ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val)
                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;
 }
@@ -868,7 +979,32 @@ static int stlink_usb_write_reg(void *handle, int num, uint32_t val)
        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;
 }
 
 /** */
@@ -903,7 +1039,7 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len,
 
        memcpy(buffer, h->databuf, len);
 
-       return ERROR_OK;
+       return stlink_usb_get_rw_status(handle);
 }
 
 /** */
@@ -926,17 +1062,17 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len,
        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;
@@ -963,12 +1099,12 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
 
        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;
@@ -988,12 +1124,12 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
        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);
 }
 
 /** */
@@ -1001,6 +1137,7 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd)
 {
        int err;
        struct stlink_usb_handle_s *h;
+       enum stlink_jtag_api_version api;
 
        LOG_DEBUG("stlink_usb_open");
 
@@ -1016,7 +1153,7 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd)
        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) {
@@ -1053,7 +1190,7 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd)
 
        /* 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);
 
@@ -1082,8 +1219,17 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd)
                return err;
        }
 
-       /* set the used jtag api */
-       h->jtag_api = STLINK_JTAG_API_V1;
+       api = h->version.jtag_api_max;
+
+       /* check that user has not requested certain api version
+        * and if they have check it is supported */
+       if ((param->api != 0) && (param->api <= h->version.jtag_api_max)) {
+               api = param->api;
+               LOG_INFO("using stlink api v%d", api);
+       }
+
+       /* set the used jtag api, this will default to the newest supported version */
+       h->jtag_api = api;
 
        /* initialize the debug hardware */
        err = stlink_usb_init_mode(h);
@@ -1119,6 +1265,8 @@ struct stlink_layout_api_s stlink_usb_layout_api = {
        /** */
        .reset = stlink_usb_reset,
        /** */
+       .assert_srst = stlink_usb_assert_srst,
+       /** */
        .run = stlink_usb_run,
        /** */
        .halt = stlink_usb_halt,
@@ -1138,4 +1286,6 @@ struct stlink_layout_api_s stlink_usb_layout_api = {
        .read_mem32 = stlink_usb_read_mem32,
        /** */
        .write_mem32 = stlink_usb_write_mem32,
+       /** */
+       .write_debug_reg = stlink_usb_write_debug_reg
 };