target/adiv5: probe MEM-AP supported transfer sizes including large data 76/7576/4
authorTomas Vanek <vanekt@fbl.cz>
Sun, 2 Apr 2023 15:23:46 +0000 (17:23 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 6 Jan 2024 13:56:43 +0000 (13:56 +0000)
Based on Daniel Goehring's [1] and Peter Collingbourne's [2] work.

Probe for support of 8, 16 bit and if the large data extension is available
also probe for 64, 128 and 256 bit operations.
Probe for the ability of packing 8 and 16 bit data
(formerly probed in mem_ap_init()). The probe is integrated to
mem_ap_read/write() routines and takes place just before the first memory
access of the specific size.

Add 64, 128 and 256 bit MEM-AP read/writes.

Introduce specific error codes for unsupported transfer size
and for unsupported packing.

Change-Id: I180c4ef17d2fc3189e8e2f14bafd22d857f29608
Link: 7191: target/adiv5: add MEM-AP 64-bit access support | https://review.openocd.org/c/openocd/+/7191
Link: 7436: arm_adi_v5: Support reads wider than 32 bits | https://review.openocd.org/c/openocd/+/7436
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/7576
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
src/target/arm_adi_v5.c
src/target/arm_adi_v5.h
src/target/target.h

index 0f1e648a9e103acbb75f1f833095758f090f1086..ff12658c83d6c89cbf2f4c1418bdace22d0ade4e 100644 (file)
@@ -50,7 +50,8 @@
 /*
  * Relevant specifications from ARM include:
  *
- * ARM(tm) Debug Interface v5 Architecture Specification    ARM IHI 0031E
+ * ARM(tm) Debug Interface v5 Architecture Specification    ARM IHI 0031F
+ * ARM(tm) Debug Interface v6 Architecture Specification    ARM IHI 0074C
  * CoreSight(tm) v1.0 Architecture Specification            ARM IHI 0029B
  *
  * CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D
@@ -164,6 +165,12 @@ static uint32_t mem_ap_get_tar_increment(struct adiv5_ap *ap)
                        return 2;
                case CSW_32BIT:
                        return 4;
+               case CSW_64BIT:
+                       return 8;
+               case CSW_128BIT:
+                       return 16;
+               case CSW_256BIT:
+                       return 32;
                default:
                        return 0;
                }
@@ -319,12 +326,145 @@ int mem_ap_write_atomic_u32(struct adiv5_ap *ap, target_addr_t address,
        return dap_run(ap->dap);
 }
 
+/**
+ * Queue transactions setting up transfer parameters for the
+ * currently selected MEM-AP. If transfer size or packing
+ * has not been probed, run the queue, read back CSW and check if the requested
+ * transfer mode is supported.
+ *
+ * @param ap The MEM-AP.
+ * @param size Transfer width in bytes. Corresponding CSW.Size will be set.
+ * @param address Transfer address, MEM-AP TAR will be set to this value.
+ * @param addrinc TAR will be autoincremented.
+ * @param pack Try to setup packed transfer.
+ * @param this_size Points to a variable set to the size of single transfer
+ *             or to 4 when transferring packed bytes or halfwords
+ *
+ * @return ERROR_OK if the transaction was properly queued, else a fault code.
+ */
+static int mem_ap_setup_transfer_verify_size_packing(struct adiv5_ap *ap,
+       unsigned int size, target_addr_t address,
+       bool addrinc, bool pack, unsigned int *this_size)
+{
+       int retval;
+       uint32_t csw_size;
+
+       switch (size) {
+       case 1:
+               csw_size = CSW_8BIT;
+               break;
+       case 2:
+               csw_size = CSW_16BIT;
+               break;
+       case 4:
+               csw_size = CSW_32BIT;
+               break;
+       case 8:
+               csw_size = CSW_64BIT;
+               break;
+       case 16:
+               csw_size = CSW_128BIT;
+               break;
+       case 32:
+               csw_size = CSW_256BIT;
+               break;
+       default:
+               LOG_ERROR("Size %u not supported", size);
+               return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+       }
+
+       if (!addrinc || size >= 4
+                       || (ap->packed_transfers_probed && !ap->packed_transfers_supported)
+                       || max_tar_block_size(ap->tar_autoincr_block, address) < 4)
+               pack = false;
+
+       uint32_t csw_addrinc = pack ? CSW_ADDRINC_PACKED :
+                addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
+       retval = mem_ap_setup_csw(ap, csw_size | csw_addrinc);
+       if (retval != ERROR_OK)
+               return retval;
+
+       bool do_probe = !(ap->csw_size_probed_mask & size)
+                || (pack && !ap->packed_transfers_probed);
+       if (do_probe) {
+               uint32_t csw_readback;
+               retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW(ap->dap), &csw_readback);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = dap_run(ap->dap);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               bool size_supported = ((csw_readback & CSW_SIZE_MASK) == csw_size);
+               LOG_DEBUG("AP#0x%" PRIx64 " probed size %u: %s", ap->ap_num, size,
+                       size_supported ? "supported" : "not supported");
+               ap->csw_size_probed_mask |= size;
+               if (size_supported) {
+                       ap->csw_size_supported_mask |= size;
+                       if (pack && !ap->packed_transfers_probed) {
+                               ap->packed_transfers_probed = true;
+                               ap->packed_transfers_supported =
+                                       ((csw_readback & CSW_ADDRINC_MASK) == csw_addrinc);
+                               LOG_DEBUG("probed packing: %s",
+                                       ap->packed_transfers_supported ? "supported" : "not supported");
+                       }
+               }
+       }
+
+       if (!(ap->csw_size_supported_mask & size)) {
+               LOG_ERROR("Size %u not supported", size);
+               return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+       }
+
+       if (pack && !ap->packed_transfers_supported)
+               return ERROR_TARGET_PACKING_NOT_SUPPORTED;
+
+       *this_size = pack ? 4 : size;
+
+       return mem_ap_setup_tar(ap, address);
+}
+
+/**
+ * Queue transactions setting up transfer parameters for the
+ * currently selected MEM-AP. If transfer size or packing
+ * has not been probed, run the queue, read back CSW and check if the requested
+ * transfer mode is supported.
+ * If packing is not supported fallback and prepare CSW for unpacked transfer.
+ *
+ * @param ap The MEM-AP.
+ * @param size Transfer width in bytes. Corresponding CSW.Size will be set.
+ * @param address Transfer address, MEM-AP TAR will be set to this value.
+ * @param addrinc TAR will be autoincremented.
+ * @param pack Try to setup packed transfer.
+ * @param this_size Points to a variable set to the size of single transfer
+ *             or to 4 when transferring packed bytes or halfwords
+ *
+ * @return ERROR_OK if the transaction was properly queued, else a fault code.
+ */
+static int mem_ap_setup_transfer_verify_size_packing_fallback(struct adiv5_ap *ap,
+       unsigned int size, target_addr_t address,
+       bool addrinc, bool pack, unsigned int *this_size)
+{
+       int retval = mem_ap_setup_transfer_verify_size_packing(ap,
+                                       size, address,
+                                       addrinc, pack, this_size);
+       if (retval == ERROR_TARGET_PACKING_NOT_SUPPORTED) {
+               /* Retry without packing */
+               retval = mem_ap_setup_transfer_verify_size_packing(ap,
+                                       size, address,
+                                       addrinc, false, this_size);
+       }
+       return retval;
+}
+
 /**
  * Synchronous write of a block of memory, using a specific access size.
  *
  * @param ap The MEM-AP to access.
  * @param buffer The data buffer to write. No particular alignment is assumed.
- * @param size Which access size to use, in bytes. 1, 2 or 4.
+ * @param size Which access size to use, in bytes. 1, 2, or 4.
+ *     If large data extension is available also accepts sizes 8, 16, 32.
  * @param count The number of writes to do (in size units, not bytes).
  * @param address Address to be written; it must be writable by the currently selected MEM-AP.
  * @param addrinc Whether the target address should be increased for each write or not. This
@@ -336,8 +476,6 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
 {
        struct adiv5_dap *dap = ap->dap;
        size_t nbytes = size * count;
-       const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
-       uint32_t csw_size;
        int retval = ERROR_OK;
 
        /* TI BE-32 Quirks mode:
@@ -352,93 +490,85 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
         * To make writes of size < 4 work as expected, we xor a value with the address before
         * setting the TAP, and we set the TAP after every transfer rather then relying on
         * address increment. */
-
-       target_addr_t ti_be_lane_xor = dap->ti_be_32_quirks ? 3 : 0;
-       target_addr_t ti_be_addr_xor;
-       if (size == 4) {
-               csw_size = CSW_32BIT;
-               ti_be_addr_xor = 0;
-       } else if (size == 2) {
-               csw_size = CSW_16BIT;
-               ti_be_addr_xor = dap->ti_be_32_quirks ? 2 : 0;
-       } else if (size == 1) {
-               csw_size = CSW_8BIT;
-               ti_be_addr_xor = dap->ti_be_32_quirks ? 3 : 0;
-       } else {
-               return ERROR_TARGET_UNALIGNED_ACCESS;
+       target_addr_t ti_be_addr_xor = 0;
+       target_addr_t ti_be_lane_xor = 0;
+       if (dap->ti_be_32_quirks) {
+               ti_be_lane_xor = 3;
+               switch (size) {
+               case 1:
+                       ti_be_addr_xor = 3;
+                       break;
+               case 2:
+                       ti_be_addr_xor = 2;
+                       break;
+               case 4:
+                       break;
+               default:
+                       LOG_ERROR("Write more than 32 bits not supported with ti_be_32_quirks");
+                       return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+               }
        }
 
        if (ap->unaligned_access_bad && (address % size != 0))
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
-       while (nbytes > 0) {
-               uint32_t this_size = size;
+       /* Nuvoton NPCX quirks prevent packed writes */
+       bool pack = !dap->nu_npcx_quirks;
 
-               /* Select packed transfer if possible */
-               if (addrinc && ap->packed_transfers && nbytes >= 4
-                               && !dap->nu_npcx_quirks
-                               && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {
-                       this_size = 4;
-                       retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED);
-               } else {
-                       retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);
-               }
-
-               if (retval != ERROR_OK)
-                       break;
-
-               retval = mem_ap_setup_tar(ap, address ^ ti_be_addr_xor);
+       while (nbytes > 0) {
+               unsigned int this_size;
+               retval = mem_ap_setup_transfer_verify_size_packing_fallback(ap,
+                                       size, address ^ ti_be_addr_xor,
+                                       addrinc, pack && nbytes >= 4, &this_size);
                if (retval != ERROR_OK)
                        return retval;
 
                /* How many source bytes each transfer will consume, and their location in the DRW,
                 * depends on the type of transfer and alignment. See ARM document IHI0031C. */
-               uint32_t outvalue = 0;
                uint32_t drw_byte_idx = address;
-               if (dap->nu_npcx_quirks && this_size <= 2) {
-                       switch (this_size) {
-                       case 2:
-                               {
-                                       /* Alternate low and high byte to all byte lanes */
-                                       uint32_t low = *buffer++;
-                                       uint32_t high = *buffer++;
-                                       outvalue |= low << 8 * (drw_byte_idx++ & 3);
-                                       outvalue |= high << 8 * (drw_byte_idx++ & 3);
-                                       outvalue |= low << 8 * (drw_byte_idx++ & 3);
-                                       outvalue |= high << 8 * (drw_byte_idx & 3);
-                               }
-                               break;
-                       case 1:
-                               {
-                                       /* Mirror output byte to all byte lanes */
-                                       uint32_t data = *buffer++;
-                                       outvalue |= data;
-                                       outvalue |= data << 8;
-                                       outvalue |= data << 16;
-                                       outvalue |= data << 24;
+               unsigned int drw_ops = DIV_ROUND_UP(this_size, 4);
+
+               while (drw_ops--) {
+                       uint32_t outvalue = 0;
+                       if (dap->nu_npcx_quirks && this_size <= 2) {
+                               switch (this_size) {
+                               case 2:
+                                       {
+                                               /* Alternate low and high byte to all byte lanes */
+                                               uint32_t low = *buffer++;
+                                               uint32_t high = *buffer++;
+                                               outvalue |= low << 8 * (drw_byte_idx++ & 3);
+                                               outvalue |= high << 8 * (drw_byte_idx++ & 3);
+                                               outvalue |= low << 8 * (drw_byte_idx++ & 3);
+                                               outvalue |= high << 8 * (drw_byte_idx & 3);
+                                       }
+                                       break;
+                               case 1:
+                                       {
+                                               /* Mirror output byte to all byte lanes */
+                                               uint32_t data = *buffer++;
+                                               outvalue |= data;
+                                               outvalue |= data << 8;
+                                               outvalue |= data << 16;
+                                               outvalue |= data << 24;
+                                       }
                                }
+                       } else {
+                               unsigned int drw_bytes = MIN(this_size, 4);
+                               while (drw_bytes--)
+                                       outvalue |= (uint32_t)*buffer++ <<
+                                                               8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
                        }
-               } else {
-                       switch (this_size) {
-                       case 4:
-                               outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
-                               outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
-                               /* fallthrough */
-                       case 2:
-                               outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
-                               /* fallthrough */
-                       case 1:
-                               outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx & 3) ^ ti_be_lane_xor);
-                       }
-               }
 
-               nbytes -= this_size;
-
-               retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue);
+                       retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue);
+                       if (retval != ERROR_OK)
+                               break;
+               }
                if (retval != ERROR_OK)
                        break;
 
                mem_ap_update_tar_cache(ap);
+               nbytes -= this_size;
                if (addrinc)
                        address += this_size;
        }
@@ -463,7 +593,8 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
  *
  * @param ap The MEM-AP to access.
  * @param buffer The data buffer to receive the data. No particular alignment is assumed.
- * @param size Which access size to use, in bytes. 1, 2 or 4.
+ * @param size Which access size to use, in bytes. 1, 2, or 4.
+ *     If large data extension is available also accepts sizes 8, 16, 32.
  * @param count The number of reads to do (in size units, not bytes).
  * @param adr Address to be read; it must be readable by the currently selected MEM-AP.
  * @param addrinc Whether the target address should be increased after each read or not. This
@@ -475,8 +606,6 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
 {
        struct adiv5_dap *dap = ap->dap;
        size_t nbytes = size * count;
-       const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
-       uint32_t csw_size;
        target_addr_t address = adr;
        int retval = ERROR_OK;
 
@@ -487,14 +616,10 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
         * Also, packed 8-bit and 16-bit transfers seem to sometimes return garbage in some bytes,
         * so avoid them (ap->packed_transfers is forced to false in mem_ap_init). */
 
-       if (size == 4)
-               csw_size = CSW_32BIT;
-       else if (size == 2)
-               csw_size = CSW_16BIT;
-       else if (size == 1)
-               csw_size = CSW_8BIT;
-       else
-               return ERROR_TARGET_UNALIGNED_ACCESS;
+       if (dap->ti_be_32_quirks && size > 4) {
+               LOG_ERROR("Read more than 32 bits not supported with ti_be_32_quirks");
+               return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+       }
 
        if (ap->unaligned_access_bad && (adr % size != 0))
                return ERROR_TARGET_UNALIGNED_ACCESS;
@@ -502,7 +627,8 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
        /* Allocate buffer to hold the sequence of DRW reads that will be made. This is a significant
         * over-allocation if packed transfers are going to be used, but determining the real need at
         * this point would be messy. */
-       uint32_t *read_buf = calloc(count, sizeof(uint32_t));
+       uint32_t *read_buf = calloc(count, MAX(sizeof(uint32_t), size));
+
        /* Multiplication count * sizeof(uint32_t) may overflow, calloc() is safe */
        uint32_t *read_ptr = read_buf;
        if (!read_buf) {
@@ -514,26 +640,20 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
         * useful bytes it contains, and their location in the word, depends on the type of transfer
         * and alignment. */
        while (nbytes > 0) {
-               uint32_t this_size = size;
-
-               /* Select packed transfer if possible */
-               if (addrinc && ap->packed_transfers && nbytes >= 4
-                               && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {
-                       this_size = 4;
-                       retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED);
-               } else {
-                       retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);
-               }
+               unsigned int this_size;
+               retval = mem_ap_setup_transfer_verify_size_packing_fallback(ap,
+                                       size, address,
+                                       addrinc, nbytes >= 4, &this_size);
                if (retval != ERROR_OK)
                        break;
 
-               retval = mem_ap_setup_tar(ap, address);
-               if (retval != ERROR_OK)
-                       break;
 
-               retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++);
-               if (retval != ERROR_OK)
-                       break;
+               unsigned int drw_ops = DIV_ROUND_UP(this_size, 4);
+               while (drw_ops--) {
+                       retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++);
+                       if (retval != ERROR_OK)
+                               break;
+               }
 
                nbytes -= this_size;
                if (addrinc)
@@ -552,7 +672,9 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
 
        /* If something failed, read TAR to find out how much data was successfully read, so we can
         * at least give the caller what we have. */
-       if (retval != ERROR_OK) {
+       if (retval == ERROR_TARGET_SIZE_NOT_SUPPORTED) {
+               nbytes = 0;
+       } else if (retval != ERROR_OK) {
                target_addr_t tar;
                if (mem_ap_read_tar(ap, &tar) == ERROR_OK) {
                        /* TAR is incremented after failed transfer on some devices (eg Cortex-M4) */
@@ -569,11 +691,12 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
 
        /* Replay loop to populate caller's buffer from the correct word and byte lane */
        while (nbytes > 0) {
-               uint32_t this_size = size;
+               /* Convert transfers longer than 32-bit on word-at-a-time basis */
+               unsigned int this_size = MIN(size, 4);
 
-               if (addrinc && ap->packed_transfers && nbytes >= 4
+               if (size < 4 && addrinc && ap->packed_transfers_supported && nbytes >= 4
                                && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {
-                       this_size = 4;
+                       this_size = 4;  /* Packed read of 4 bytes or 2 halfwords */
                }
 
                switch (this_size) {
@@ -764,7 +887,7 @@ int dap_dp_init_or_reconnect(struct adiv5_dap *dap)
 int mem_ap_init(struct adiv5_ap *ap)
 {
        /* check that we support packed transfers */
-       uint32_t csw, cfg;
+       uint32_t cfg;
        int retval;
        struct adiv5_dap *dap = ap->dap;
 
@@ -781,30 +904,23 @@ int mem_ap_init(struct adiv5_ap *ap)
        ap->cfg_reg = cfg;
        ap->tar_valid = false;
        ap->csw_value = 0;      /* force csw and tar write */
-       retval = mem_ap_setup_transfer(ap, CSW_8BIT | CSW_ADDRINC_PACKED, 0);
-       if (retval != ERROR_OK)
-               return retval;
 
-       retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW(dap), &csw);
-       if (retval != ERROR_OK)
-               return retval;
+       /* CSW 32-bit size must be supported (IHI 0031F and 0074D). */
+       ap->csw_size_supported_mask = BIT(CSW_32BIT);
+       ap->csw_size_probed_mask = BIT(CSW_32BIT);
 
-       retval = dap_run(dap);
-       if (retval != ERROR_OK)
-               return retval;
+       /* Suppress probing sizes longer than 32 bit if AP has no large data extension */
+       if (!(cfg & MEM_AP_REG_CFG_LD))
+               ap->csw_size_probed_mask |= BIT(CSW_64BIT) | BIT(CSW_128BIT) | BIT(CSW_256BIT);
 
-       if (csw & CSW_ADDRINC_PACKED)
-               ap->packed_transfers = true;
-       else
-               ap->packed_transfers = false;
-
-       /* Packed transfers on TI BE-32 processors do not work correctly in
+       /* Both IHI 0031F and 0074D state: Implementations that support transfers
+        * smaller than a word must support packed transfers. Unfortunately at least
+        * Cortex-M0 and Cortex-M0+ do not comply with this rule.
+        * Probe for packed transfers except we know they are broken.
+        * Packed transfers on TI BE-32 processors do not work correctly in
         * many cases. */
-       if (dap->ti_be_32_quirks)
-               ap->packed_transfers = false;
-
-       LOG_DEBUG("MEM_AP Packed Transfers: %s",
-                       ap->packed_transfers ? "enabled" : "disabled");
+       ap->packed_transfers_supported = false;
+       ap->packed_transfers_probed = dap->ti_be_32_quirks ? true : false;
 
        /* The ARM ADI spec leaves implementation-defined whether unaligned
         * memory accesses work, only work partially, or cause a sticky error.
index fc7fdafd84cf72f84cec4f07772ebff850c434dd..60c161f3cacc0bbe7d9fdf7418ec65cc9530f84a 100644 (file)
 #define CSW_8BIT               0
 #define CSW_16BIT              1
 #define CSW_32BIT              2
+#define CSW_64BIT              3
+#define CSW_128BIT             4
+#define CSW_256BIT             5
 #define CSW_ADDRINC_MASK    (3UL << 4)
 #define CSW_ADDRINC_OFF     0UL
 #define CSW_ADDRINC_SINGLE  (1UL << 4)
@@ -269,6 +272,26 @@ struct adiv5_ap {
         */
        uint32_t csw_value;
 
+       /**
+        * Save the supported CSW.Size data types for the MEM-AP.
+        * Each bit corresponds to a data type.
+        * 0b1 = Supported data size. 0b0 = Not supported.
+        * Bit 0 = Byte (8-bits)
+        * Bit 1 = Halfword (16-bits)
+        * Bit 2 = Word (32-bits) - always supported by spec.
+        * Bit 3 = Doubleword (64-bits)
+        * Bit 4 = 128-bits
+        * Bit 5 = 256-bits
+        */
+       uint32_t csw_size_supported_mask;
+       /**
+        * Probed CSW.Size data types for the MEM-AP.
+        * Each bit corresponds to a data type.
+        * 0b1 = Data size has been probed. 0b0 = Not yet probed.
+        * Bits assigned to sizes same way as above.
+        */
+       uint32_t csw_size_probed_mask;
+
        /**
         * Cache for (MEM-AP) AP_REG_TAR register value This is written to
         * configure the address being read or written
@@ -286,7 +309,8 @@ struct adiv5_ap {
        uint32_t tar_autoincr_block;
 
        /* true if packed transfers are supported by the MEM-AP */
-       bool packed_transfers;
+       bool packed_transfers_supported;
+       bool packed_transfers_probed;
 
        /* true if unaligned memory access is not supported by the MEM-AP */
        bool unaligned_access_bad;
index 6caf59887437e8bfb82f9b5888950bb3900752a8..f69ee77ac42627aae66358cf79864e0408fa53fa 100644 (file)
@@ -796,6 +796,8 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t
 #define ERROR_TARGET_NOT_EXAMINED (-311)
 #define ERROR_TARGET_DUPLICATE_BREAKPOINT (-312)
 #define ERROR_TARGET_ALGO_EXIT  (-313)
+#define ERROR_TARGET_SIZE_NOT_SUPPORTED  (-314)
+#define ERROR_TARGET_PACKING_NOT_SUPPORTED  (-315)
 
 extern bool get_target_reset_nag(void);
 

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)