stlink: collapse consecutive mem AP r/w in a single command 04/6604/2
authorAntonio Borneo <borneo.antonio@gmail.com>
Sun, 25 Jul 2021 15:31:53 +0000 (17:31 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Fri, 5 Nov 2021 22:41:53 +0000 (22:41 +0000)
Detect a sequence of memory AP operations that can be issued as a
single stlink command.
This improves the data throughput during memory transfer.

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

index 1cd68c50ba6544314387c40b8d866ee4629f8342..818fccd333b7e1004aef7faebff77373060533d3 100644 (file)
@@ -4132,6 +4132,95 @@ static int stlink_dap_op_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
        return ERROR_OK;
 }
 
+static int stlink_usb_buf_rw_segment(void *handle, const struct dap_queue *q, unsigned int count)
+{
+       uint32_t bufsize = count * CMD_MEM_AP_2_SIZE(q[0].cmd);
+       uint8_t buf[bufsize];
+       uint8_t ap_num = q[0].mem_ap.ap->ap_num;
+       uint32_t addr = q[0].mem_ap.addr;
+       uint32_t csw = q[0].mem_ap.csw;
+
+       int retval = stlink_dap_open_ap(ap_num);
+       if (retval != ERROR_OK)
+               return retval;
+
+       switch (q[0].cmd) {
+       case CMD_MEM_AP_WRITE8:
+               for (unsigned int i = 0; i < count; i++)
+                       buf[i] = q[i].mem_ap.data >> 8 * (q[i].mem_ap.addr & 3);
+               return stlink_usb_write_mem8(stlink_dap_handle, ap_num, csw, addr, bufsize, buf);
+
+       case CMD_MEM_AP_WRITE16:
+               for (unsigned int i = 0; i < count; i++)
+                       h_u16_to_le(&buf[2 * i], q[i].mem_ap.data >> 8 * (q[i].mem_ap.addr & 2));
+               return stlink_usb_write_mem16(stlink_dap_handle, ap_num, csw, addr, bufsize, buf);
+
+       case CMD_MEM_AP_WRITE32:
+               for (unsigned int i = 0; i < count; i++)
+                       h_u32_to_le(&buf[4 * i], q[i].mem_ap.data);
+               return stlink_usb_write_mem32(stlink_dap_handle, ap_num, csw, addr, bufsize, buf);
+
+       case CMD_MEM_AP_READ8:
+               retval = stlink_usb_read_mem8(stlink_dap_handle, ap_num, csw, addr, bufsize, buf);
+               if (retval == ERROR_OK)
+                       for (unsigned int i = 0; i < count; i++)
+                               *q[i].mem_ap.p_data = buf[i] << 8 * (q[i].mem_ap.addr & 3);
+               return retval;
+
+       case CMD_MEM_AP_READ16:
+               retval = stlink_usb_read_mem16(stlink_dap_handle, ap_num, csw, addr, bufsize, buf);
+               if (retval == ERROR_OK)
+                       for (unsigned int i = 0; i < count; i++)
+                               *q[i].mem_ap.p_data = le_to_h_u16(&buf[2 * i]) << 8 * (q[i].mem_ap.addr & 2);
+               return retval;
+
+       case CMD_MEM_AP_READ32:
+               retval = stlink_usb_read_mem32(stlink_dap_handle, ap_num, csw, addr, bufsize, buf);
+               if (retval == ERROR_OK)
+                       for (unsigned int i = 0; i < count; i++)
+                               *q[i].mem_ap.p_data = le_to_h_u32(&buf[4 * i]);
+               return retval;
+
+       default:
+               return ERROR_FAIL;
+       };
+}
+
+static int stlink_usb_count_buf_rw_queue(const struct dap_queue *q, unsigned int len)
+{
+       uint32_t incr = CMD_MEM_AP_2_SIZE(q[0].cmd);
+       unsigned int len_max;
+
+       if (incr == 1)
+               len_max = stlink_usb_block(stlink_dap_handle);
+       else
+               len_max = STLINK_MAX_RW16_32 / incr;
+
+       if (len > len_max)
+               len = len_max;
+
+       for (unsigned int i = 1; i < len; i++)
+               if (q[i].cmd != q[0].cmd ||
+                       q[i].mem_ap.ap != q[0].mem_ap.ap ||
+                       q[i].mem_ap.csw != q[0].mem_ap.csw ||
+                       q[i].mem_ap.addr != q[i - 1].mem_ap.addr + incr)
+                       return i;
+
+       return len;
+}
+
+static int stlink_usb_mem_rw_queue(void *handle, const struct dap_queue *q, unsigned int len, unsigned int *skip)
+{
+       unsigned int count = stlink_usb_count_buf_rw_queue(q, len);
+
+       int retval = stlink_usb_buf_rw_segment(handle, q, count);
+       if (retval != ERROR_OK)
+               return retval;
+
+       *skip = count;
+       return ERROR_OK;
+}
+
 static void stlink_dap_run_internal(struct adiv5_dap *dap)
 {
        int retval = stlink_dap_check_reconnect(dap);
@@ -4143,9 +4232,10 @@ static void stlink_dap_run_internal(struct adiv5_dap *dap)
 
        unsigned int i = stlink_dap_handle->queue_index;
        struct dap_queue *q = &stlink_dap_handle->queue[0];
-       uint8_t buf[4];
 
        while (i && stlink_dap_get_error() == ERROR_OK) {
+               unsigned int skip = 1;
+
                switch (q->cmd) {
                case CMD_DP_READ:
                        retval = stlink_dap_dp_read(q->dp_r.dap, q->dp_r.reg, q->dp_r.p_data);
@@ -4164,50 +4254,12 @@ static void stlink_dap_run_internal(struct adiv5_dap *dap)
                        break;
 
                case CMD_MEM_AP_READ8:
-                       retval = stlink_dap_open_ap(q->mem_ap.ap->ap_num);
-                       if (retval == ERROR_OK)
-                               retval = stlink_usb_read_mem8(stlink_dap_handle, q->mem_ap.ap->ap_num, q->mem_ap.csw, q->mem_ap.addr,
-                                                                                         1, buf);
-                       if (retval == ERROR_OK)
-                               *q->mem_ap.p_data = *buf << 8 * (q->mem_ap.addr & 3);
-                       break;
                case CMD_MEM_AP_READ16:
-                       retval = stlink_dap_open_ap(q->mem_ap.ap->ap_num);
-                       if (retval == ERROR_OK)
-                               retval = stlink_usb_read_mem16(stlink_dap_handle, q->mem_ap.ap->ap_num, q->mem_ap.csw, q->mem_ap.addr,
-                                                                                          2, buf);
-                       if (retval == ERROR_OK)
-                               *q->mem_ap.p_data = le_to_h_u16(buf) << 8 * (q->mem_ap.addr & 2);
-                       break;
                case CMD_MEM_AP_READ32:
-                       retval = stlink_dap_open_ap(q->mem_ap.ap->ap_num);
-                       if (retval == ERROR_OK)
-                               retval = stlink_usb_read_mem32(stlink_dap_handle, q->mem_ap.ap->ap_num, q->mem_ap.csw, q->mem_ap.addr,
-                                                                                          4, buf);
-                       if (retval == ERROR_OK)
-                               *q->mem_ap.p_data = le_to_h_u32(buf);
-                       break;
-
                case CMD_MEM_AP_WRITE8:
-                       *buf = q->mem_ap.data >> 8 * (q->mem_ap.addr & 3);
-                       retval = stlink_dap_open_ap(q->mem_ap.ap->ap_num);
-                       if (retval == ERROR_OK)
-                               retval = stlink_usb_write_mem8(stlink_dap_handle, q->mem_ap.ap->ap_num, q->mem_ap.csw, q->mem_ap.addr,
-                                                                                          1, buf);
-                       break;
                case CMD_MEM_AP_WRITE16:
-                       h_u16_to_le(buf, q->mem_ap.data >> 8 * (q->mem_ap.addr & 2));
-                       retval = stlink_dap_open_ap(q->mem_ap.ap->ap_num);
-                       if (retval == ERROR_OK)
-                               retval = stlink_usb_write_mem16(stlink_dap_handle, q->mem_ap.ap->ap_num, q->mem_ap.csw, q->mem_ap.addr,
-                                                                                               2, buf);
-                       break;
                case CMD_MEM_AP_WRITE32:
-                       h_u32_to_le(buf, q->mem_ap.data);
-                       retval = stlink_dap_open_ap(q->mem_ap.ap->ap_num);
-                       if (retval == ERROR_OK)
-                               retval = stlink_usb_write_mem32(stlink_dap_handle, q->mem_ap.ap->ap_num, q->mem_ap.csw, q->mem_ap.addr,
-                                                                                               4, buf);
+                       retval = stlink_usb_mem_rw_queue(stlink_dap_handle, q, i, &skip);
                        break;
 
                default:
@@ -4216,8 +4268,8 @@ static void stlink_dap_run_internal(struct adiv5_dap *dap)
                        break;
                }
                stlink_dap_record_error(retval);
-               q++;
-               i--;
+               q += skip;
+               i -= skip;
        }
 
        stlink_dap_handle->queue_index = 0;

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)