stlink: check buffer size on 16 and 32 bit memory transfer 00/6600/2
authorAntonio Borneo <borneo.antonio@gmail.com>
Sun, 25 Jul 2021 15:51:49 +0000 (17:51 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Fri, 5 Nov 2021 22:40:54 +0000 (22:40 +0000)
Both HLA and ADIv5 layers limit the memory transfer within blocks
whose boundaries are aligned at 1024 or 4096 bytes.
New stlink firmware handle the ADIv5 TAR autoincrement, making
possible to send memory transfers across the boundary of 1024 or
4096 byte. OpenOCD doesn't use this feature yet.

Use the correct buffer size in the code, even if it is not used.
While there, split SWIM buffer size from JTAG/SWD case; stlink has
a dedicated command to retrieve SWIM buffer size, but currently
not implemented in OpenOCD.

Change-Id: Id46c0356ef21cead08726c044a1cd9725fd4f923
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6600
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
src/jtag/drivers/stlink_usb.c

index a523708638654a27318612d670f3c25f43cb61cd..e83e84b9578d54a119515eeb79001164f562266c 100644 (file)
@@ -79,7 +79,7 @@
 #define STLINK_V2_1_TRACE_EP  (2|ENDPOINT_IN)
 
 #define STLINK_SG_SIZE        (31)
-#define STLINK_DATA_SIZE      (4096)
+#define STLINK_DATA_SIZE      (6144)
 #define STLINK_CMD_SIZE_V2    (16)
 #define STLINK_CMD_SIZE_V1    (10)
 
  * ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
  * this limits the bulk packet size and the 8bit read/writes to max 64 bytes.
  * STLINK-V3 is a high speed USB 2.0 and the limit is 512 bytes from FW V3J6.
+ *
+ * For 16 and 32bit read/writes stlink handles USB packet split and the limit
+ * is the internal buffer size of 6144 bytes.
+ * TODO: override ADIv5 layer's tar_autoincr_block that limits the transfer
+ * to 1024 or 4096 bytes
  */
-#define STLINK_MAX_RW8         (64)
-#define STLINKV3_MAX_RW8       (512)
+#define STLINK_MAX_RW8          (64)
+#define STLINKV3_MAX_RW8        (512)
+#define STLINK_MAX_RW16_32      STLINK_DATA_SIZE
+#define STLINK_SWIM_DATA_SIZE   STLINK_DATA_SIZE
 
 /* "WAIT" responses will be retried (with exponential backoff) at
  * most this many times before failing to caller.
@@ -1807,7 +1814,7 @@ static int stlink_swim_writebytes(void *handle, uint32_t addr, uint32_t len, con
        unsigned int datalen = 0;
        int cmdsize = STLINK_CMD_SIZE_V2;
 
-       if (len > STLINK_DATA_SIZE)
+       if (len > STLINK_SWIM_DATA_SIZE)
                return ERROR_FAIL;
 
        if (h->version.stlink == 1)
@@ -1840,7 +1847,7 @@ static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint
        struct stlink_usb_handle_s *h = handle;
        int res;
 
-       if (len > STLINK_DATA_SIZE)
+       if (len > STLINK_SWIM_DATA_SIZE)
                return ERROR_FAIL;
 
        stlink_usb_init_buffer(handle, h->rx_ep, 0);
@@ -2411,6 +2418,11 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len,
        if (!(h->version.flags & STLINK_F_HAS_MEM_16BIT))
                return ERROR_COMMAND_NOTFOUND;
 
+       if (len > STLINK_MAX_RW16_32) {
+               LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32);
+               return ERROR_FAIL;
+       }
+
        /* data must be a multiple of 2 and half-word aligned */
        if (len % 2 || addr % 2) {
                LOG_DEBUG("Invalid data alignment");
@@ -2448,6 +2460,11 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len,
        if (!(h->version.flags & STLINK_F_HAS_MEM_16BIT))
                return ERROR_COMMAND_NOTFOUND;
 
+       if (len > STLINK_MAX_RW16_32) {
+               LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32);
+               return ERROR_FAIL;
+       }
+
        /* data must be a multiple of 2 and half-word aligned */
        if (len % 2 || addr % 2) {
                LOG_DEBUG("Invalid data alignment");
@@ -2480,6 +2497,11 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
 
        assert(handle);
 
+       if (len > STLINK_MAX_RW16_32) {
+               LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32);
+               return ERROR_FAIL;
+       }
+
        /* data must be a multiple of 4 and word aligned */
        if (len % 4 || addr % 4) {
                LOG_DEBUG("Invalid data alignment");
@@ -2514,6 +2536,11 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
 
        assert(handle);
 
+       if (len > STLINK_MAX_RW16_32) {
+               LOG_DEBUG("max buffer (%d) length exceeded", STLINK_MAX_RW16_32);
+               return ERROR_FAIL;
+       }
+
        /* data must be a multiple of 4 and word aligned */
        if (len % 4 || addr % 4) {
                LOG_DEBUG("Invalid data alignment");
@@ -3482,7 +3509,7 @@ static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode
                        goto error_open;
                }
                *fd = h;
-               h->max_mem_packet = STLINK_DATA_SIZE;
+               h->max_mem_packet = STLINK_SWIM_DATA_SIZE;
                return ERROR_OK;
        }
 
@@ -4090,7 +4117,7 @@ static int stlink_swim_op_read_mem(uint32_t addr, uint32_t size,
        count *= size;
 
        while (count) {
-               bytes_remaining = (count > STLINK_DATA_SIZE) ? STLINK_DATA_SIZE : count;
+               bytes_remaining = (count > STLINK_SWIM_DATA_SIZE) ? STLINK_SWIM_DATA_SIZE : count;
                retval = stlink_swim_readbytes(stlink_dap_handle, addr, bytes_remaining, buffer);
                if (retval != ERROR_OK)
                        return retval;
@@ -4113,7 +4140,7 @@ static int stlink_swim_op_write_mem(uint32_t addr, uint32_t size,
        count *= size;
 
        while (count) {
-               bytes_remaining = (count > STLINK_DATA_SIZE) ? STLINK_DATA_SIZE : count;
+               bytes_remaining = (count > STLINK_SWIM_DATA_SIZE) ? STLINK_SWIM_DATA_SIZE : count;
                retval = stlink_swim_writebytes(stlink_dap_handle, addr, bytes_remaining, buffer);
                if (retval != ERROR_OK)
                        return retval;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)