target/adiv5: probe MEM-AP supported transfer sizes including large data
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
This commit is contained in:
parent
ffdcec938f
commit
adcc8ef87b
|
@ -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;
|
||||
|
||||
/* Nuvoton NPCX quirks prevent packed writes */
|
||||
bool pack = !dap->nu_npcx_quirks;
|
||||
|
||||
while (nbytes > 0) {
|
||||
uint32_t this_size = size;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue);
|
||||
if (retval != ERROR_OK)
|
||||
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 {
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
|
||||
/* 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 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;
|
||||
}
|
||||
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;
|
||||
|
||||
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.
|
||||
|
|
|
@ -165,6 +165,9 @@
|
|||
#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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue