This is an automated email from Gerrit.

Ake Rehnman ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/3952

-- gerrit

commit 040042cee1dbb966c9346db7626792cba107777c
Author: Ake Rehnman <[email protected]>
Date:   Sat Jan 21 10:42:11 2017 +0100

    jtag/drivers/stlink_usb : implemented and repaired SWIM support
    
    The SWIM support in stlink_usb was basically non existent so I have
    implemented the missing parts. The bCBWCBLength and dCBWDataTransferLength
    for STLINK-V1 protocol was not correct so that was fixed. The reason for
    adding SWIM support is to add STM8 support for OpenOCD.
    
    I have tested the driver on:
    STM8 discovery board with the built-in STLINK-V1
    STM8 discovery board with STLINK-V2 dongle
    STM32 vldiscovery board with the built-in STLINK-V1
    STM32F1xxx processor with STLINK-V2 dongle
    
    Change-Id: I4aa80a92fb0226174356adaf2f8ff949920a621f
    Signed-off-by: Ake Rehnman <[email protected]>

diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index 699c41f..8e098ad 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -1,4 +1,8 @@
 /***************************************************************************
+ *   SWIM contributions by Ake Rehnman                                     *
+ *   Copyright (C) 2017  Ake Rehnman                                       *
+ *   ake.rehnman(at)gmail.com                                              *
+ *                                                                         *
  *   Copyright (C) 2011-2012 by Mathias Kuester                            *
  *   Mathias Kuester <[email protected]>                                   *
  *                                                                         *
@@ -167,8 +171,36 @@ struct stlink_usb_handle_s {
 
 #define STLINK_DFU_EXIT                0x07
 
-#define STLINK_SWIM_ENTER              0x00
-#define STLINK_SWIM_EXIT               0x01
+/*
+       STLINK_SWIM_ENTER_SEQ
+       1.3ms low then 750Hz then 1.5kHz
+
+       STLINK_SWIM_GEN_RST
+       STM8 DM pulls reset pin low 50us
+
+       STLINK_SWIM_SPEED
+       uint8_t (0=low|1=high)
+
+       STLINK_SWIM_WRITEMEM
+       uint16_t length
+       uint32_t address
+
+       STLINK_SWIM_RESET
+       send syncronization seq (16us low, response 64 clocks low)
+*/
+#define STLINK_SWIM_ENTER                  0x00
+#define STLINK_SWIM_EXIT                   0x01
+#define STLINK_SWIM_READ_CAP               0x02
+#define STLINK_SWIM_ASSERT_RESET           0x07
+#define STLINK_SWIM_DEASSERT_RESET         0x08
+#define STLINK_SWIM_ENTER_SEQ              0x04
+#define STLINK_SWIM_GEN_RST                0x05
+#define STLINK_SWIM_SPEED                  0x03
+#define STLINK_SWIM_WRITEMEM               0x0a
+#define STLINK_SWIM_RESET                  0x06
+#define STLINK_SWIM_READMEM                0x0b
+#define STLINK_SWIM_READBUF                0x0c
+#define STLINK_SWIM_READSTATUS             0x09
 
 #define STLINK_DEBUG_ENTER_JTAG            0x00
 #define STLINK_DEBUG_GETSTATUS             0x01
@@ -342,7 +374,11 @@ static int stlink_usb_xfer_v1_get_sense(void *handle)
        return ERROR_OK;
 }
 
-/** */
+/*
+       transfers block in cmdbuf
+       <size> indicates number of bytes in the following
+       data phase.
+*/
 static int stlink_usb_xfer(void *handle, const uint8_t *buf, int size)
 {
        int err, cmdsize = STLINK_CMD_SIZE_V2;
@@ -350,8 +386,11 @@ static int stlink_usb_xfer(void *handle, const uint8_t 
*buf, int size)
 
        assert(handle != NULL);
 
-       if (h->version.stlink == 1)
+       if (h->version.stlink == 1) {
                cmdsize = STLINK_SG_SIZE;
+               /* put length in bCBWCBLength */
+               h->cmdbuf[14] = h->cmdidx-15;
+       }
 
        err = stlink_usb_xfer_rw(handle, cmdsize, buf, size);
 
@@ -373,6 +412,45 @@ static int stlink_usb_xfer(void *handle, const uint8_t 
*buf, int size)
        return ERROR_OK;
 }
 
+/*
+       send cbw with wait for completion
+       handle - handle
+       buf - buffer used in data phase
+       size - number of bytes in data phase
+ */
+static int stlink_usb_xfer_busyw(void *handle, const uint8_t *buf, int size)
+{
+       struct stlink_usb_handle_s *h = handle;
+       int err;
+       int timeout = 1000;
+
+       assert(handle != NULL);
+
+       err = stlink_usb_xfer(handle, buf, size);
+
+       if (err != ERROR_OK)
+               return err;
+
+       do {
+               stlink_usb_init_buffer(handle, h->rx_ep, 4);
+               h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+               h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READSTATUS;
+               err = stlink_usb_xfer(handle, buf, 4);
+
+               if (err != ERROR_OK)
+                       return err;
+               /* 0x01 indicates busy */
+               if (buf[0] == 0x01)
+                       usleep(1000);
+               else
+                       break;
+       } while (timeout--);
+
+       if (buf[0] != 0)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
 
 /**
     Converts an STLINK status code held in the first byte of a response
@@ -388,6 +466,9 @@ static int stlink_usb_error_check(void *handle)
        if (h->jtag_api == STLINK_JTAG_API_V1)
                h->databuf[0] = STLINK_DEBUG_ERR_OK;
 
+       if (h->transport == HL_TRANSPORT_SWIM)
+               h->databuf[0] = STLINK_DEBUG_ERR_OK;
+
        switch (h->databuf[0]) {
                case STLINK_DEBUG_ERR_OK:
                        return ERROR_OK;
@@ -487,7 +568,17 @@ static int stlink_usb_read_trace(void *handle, const 
uint8_t *buf, int size)
        return ERROR_OK;
 }
 
-/** */
+/*
+       this function writes transfer length in
+       the right place in the cb
+*/
+static void stlink_usb_set_cbw_transfer_datalength(void *handle, uint32_t size)
+{
+       struct stlink_usb_handle_s *h = handle;
+
+       buf_set_u32(h->cmdbuf+8, 0, 32, size);
+}
+
 static void stlink_usb_xfer_v1_create_cmd(void *handle, uint8_t direction, 
uint32_t size)
 {
        struct stlink_usb_handle_s *h = handle;
@@ -496,12 +587,16 @@ static void stlink_usb_xfer_v1_create_cmd(void *handle, 
uint8_t direction, uint3
        strcpy((char *)h->cmdbuf, "USBC");
        h->cmdidx += 4;
        /* csw tag not used */
+       buf_set_u32(h->cmdbuf+h->cmdidx, 0, 32, 0);
        h->cmdidx += 4;
+       /* cbw data transfer length (in the following data phase in or out) */
        buf_set_u32(h->cmdbuf+h->cmdidx, 0, 32, size);
        h->cmdidx += 4;
+       /* cbw flags */
        h->cmdbuf[h->cmdidx++] = (direction == h->rx_ep ? ENDPOINT_IN : 
ENDPOINT_OUT);
        h->cmdbuf[h->cmdidx++] = 0; /* lun */
-       h->cmdbuf[h->cmdidx++] = STLINK_CMD_SIZE_V1;
+       /* cdb clength (is filled in at xfer) */
+       h->cmdbuf[h->cmdidx++] = 0;
 }
 
 /** */
@@ -681,6 +776,8 @@ static int stlink_usb_mode_enter(void *handle, enum 
stlink_mode type)
                case STLINK_MODE_DEBUG_SWIM:
                        h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
                        h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER;
+                       /* no answer for this function... */
+                       rx_size = 0;
                        break;
                case STLINK_MODE_DFU:
                case STLINK_MODE_MASS:
@@ -845,6 +942,182 @@ static int stlink_usb_init_mode(void *handle, bool 
connect_under_reset)
        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_usb_xfer_busyw(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_usb_xfer_busyw(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_usb_xfer_busyw(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_usb_xfer_busyw(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_usb_xfer_busyw(handle, h->databuf, 0);
+       if (res != ERROR_OK)
+               return res;
+       return ERROR_OK;
+}
+
+static int stlink_swim_writebytes(void *handle, uint32_t addr, const uint8_t 
*data, uint32_t len)
+{
+       struct stlink_usb_handle_s *h = handle;
+       int res;
+       unsigned int i;
+       unsigned int datalen = 0;
+       int cmdsize = STLINK_CMD_SIZE_V2;
+
+       if (len > 4096)
+               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_usb_xfer_busyw(handle, h->databuf, datalen);
+       if (res != ERROR_OK)
+               return res;
+       return ERROR_OK;
+}
+
+static int stlink_swim_readbytes(void *handle, uint32_t addr, uint8_t *data, 
uint32_t len)
+{
+       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_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_usb_xfer_busyw(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;
+}
+
 /** */
 static int stlink_usb_idcode(void *handle, uint32_t *idcode)
 {
@@ -853,6 +1126,12 @@ static int stlink_usb_idcode(void *handle, uint32_t 
*idcode)
 
        assert(handle != NULL);
 
+       /* there is no swim read core id cmd */
+       if (h->transport == HL_TRANSPORT_SWIM) {
+               *idcode = 0;
+               return ERROR_OK;
+       }
+
        stlink_usb_init_buffer(handle, h->rx_ep, 4);
 
        h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
@@ -971,6 +1250,18 @@ static enum target_state stlink_usb_state(void *handle)
 
        assert(handle != NULL);
 
+       if (h->transport == HL_TRANSPORT_SWIM) {
+               res = stlink_usb_mode_enter(handle, 
stlink_get_mode(h->transport));
+               if (res != ERROR_OK)
+                       return TARGET_UNKNOWN;
+
+               res = stlink_swim_resync(handle);
+               if (res != ERROR_OK)
+                       return TARGET_UNKNOWN;
+
+               return ERROR_OK;
+       }
+
        if (h->reconnect_pending) {
                LOG_INFO("Previous state query failed, trying to reconnect");
                res = stlink_usb_mode_enter(handle, 
stlink_get_mode(h->transport));
@@ -1014,6 +1305,9 @@ static int stlink_usb_assert_srst(void *handle, int srst)
 
        assert(handle != NULL);
 
+       if (h->transport == HL_TRANSPORT_SWIM)
+               return stlink_swim_assert_reset(handle, srst);
+
        if (h->version.stlink == 1)
                return ERROR_COMMAND_NOTFOUND;
 
@@ -1088,6 +1382,9 @@ static int stlink_usb_reset(void *handle)
 
        assert(handle != NULL);
 
+       if (h->transport == HL_TRANSPORT_SWIM)
+               return stlink_swim_generate_rst(handle);
+
        stlink_usb_init_buffer(handle, h->rx_ep, 2);
 
        h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
@@ -1294,6 +1591,12 @@ static int stlink_usb_read_mem8(void *handle, uint32_t 
addr, uint16_t len,
 
        stlink_usb_init_buffer(handle, h->rx_ep, read_len);
 
+       if (h->transport == HL_TRANSPORT_SWIM) {
+               /* read mem at addr */
+               res = stlink_swim_readbytes(handle, addr, buffer, len);
+               return res;
+       }
+
        h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
        h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_8BIT;
        h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
@@ -1332,6 +1635,12 @@ static int stlink_usb_write_mem8(void *handle, uint32_t 
addr, uint16_t len,
 
        stlink_usb_init_buffer(handle, h->tx_ep, len);
 
+       if (h->transport == HL_TRANSPORT_SWIM) {
+               /* read mem at addr */
+               res = stlink_swim_writebytes(handle, addr, buffer, len);
+               return res;
+       }
+
        h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
        h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_8BIT;
        h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
@@ -1440,6 +1749,11 @@ static int stlink_usb_read_mem(void *handle, uint32_t 
addr, uint32_t size,
                if (count < bytes_remaining)
                        bytes_remaining = count;
 
+               if (h->transport == HL_TRANSPORT_SWIM) {
+                       retval = stlink_usb_read_mem8(handle, addr, 
bytes_remaining, buffer);
+                       if (retval != ERROR_OK)
+                               return retval;
+               } else
                /* the stlink only supports 8/32bit memory read/writes
                 * honour 32bit, all others will be handled as 8bit access */
                if (size == 4) {
@@ -1510,6 +1824,14 @@ static int stlink_usb_write_mem(void *handle, uint32_t 
addr, uint32_t size,
                if (count < bytes_remaining)
                        bytes_remaining = count;
 
+               if (h->transport == HL_TRANSPORT_SWIM) {
+                       if (bytes_remaining > STLINK_MAX_RW8)
+                               bytes_remaining = STLINK_MAX_RW8;
+                       retval = stlink_usb_write_mem8(handle, addr, 
bytes_remaining, buffer);
+                       if (retval != ERROR_OK)
+                               return retval;
+               } else
+
                /* the stlink only supports 8/32bit memory read/writes
                 * honour 32bit, all others will be handled as 8bit access */
                if (size == 4) {
@@ -1574,6 +1896,20 @@ static int stlink_speed(void *handle, int khz, bool 
query)
        int speed_diff = INT_MAX;
        struct stlink_usb_handle_s *h = handle;
 
+       if (h && (h->transport == HL_TRANSPORT_SWIM)) {
+               /*
+                       we dont care what the khz rate is
+                       we only have low and high speed...
+                       before changing speed the SWIM_CSR HS bit
+                       must be updated
+                */
+               if (khz == 0)
+                       stlink_swim_speed(handle, 0);
+               else
+                       stlink_swim_speed(handle, 1);
+               return khz;
+       }
+
        /* only supported by stlink/v2 and for firmware >= 22 */
        if (h && (h->version.stlink == 1 || h->version.jtag < 22))
                return khz;
@@ -1780,6 +2116,17 @@ static int stlink_usb_open(struct hl_interface_param_s 
*param, void **fd)
                goto error_open;
        }
 
+       if (h->transport == HL_TRANSPORT_SWIM) {
+               err = stlink_swim_enter(h);
+               if (err != ERROR_OK) {
+                       LOG_ERROR("stlink_swim_enter_failed (unable to connect 
to the target)");
+                       goto error_open;
+               }
+               *fd = h;
+               h->max_mem_packet = (1 << 10);
+               return ERROR_OK;
+       }
+
        /* clock speed only supported by stlink/v2 and for firmware >= 22 */
        if (h->version.stlink >= 2 && h->version.jtag >= 22) {
                LOG_DEBUG("Supported clock speeds are:");

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to