X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.c;h=70ef302dc44f47a3d9fe970a02dd900513ae077b;hb=a6c4eb03455f6e97fc25183aae249d6ccdcbfb0f;hp=f7e58d08b8fbc561fe4c8ed47c1e05d6059418a6;hpb=5387d616a3d1b4550f9acecda26ead380d37dedf;p=openocd.git diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index f7e58d08b8..70ef302dc4 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -113,34 +113,33 @@ void dap_ap_select(struct adiv5_dap *dap, uint8_t ap) * Values MUST BE UPDATED BEFORE AP ACCESS. */ dap->ap_bank_value = -1; - dap->ap_csw_value = -1; - dap->ap_tar_value = -1; } } static int dap_setup_accessport_csw(struct adiv5_dap *dap, uint32_t csw) { csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT | - dap->apcsw[dap->ap_current >> 24]; + dap->ap[dap_ap_get_select(dap)].csw_default; - if (csw != dap->ap_csw_value) { + if (csw != dap->ap[dap_ap_get_select(dap)].csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ - int retval = dap_queue_ap_write(dap, AP_REG_CSW, csw); + int retval = dap_queue_ap_write(dap, MEM_AP_REG_CSW, csw); if (retval != ERROR_OK) return retval; - dap->ap_csw_value = csw; + dap->ap[dap_ap_get_select(dap)].csw_value = csw; } return ERROR_OK; } static int dap_setup_accessport_tar(struct adiv5_dap *dap, uint32_t tar) { - if (tar != dap->ap_tar_value || dap->ap_csw_value & CSW_ADDRINC_MASK) { + if (tar != dap->ap[dap_ap_get_select(dap)].tar_value || + (dap->ap[dap_ap_get_select(dap)].csw_value & CSW_ADDRINC_MASK)) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ - int retval = dap_queue_ap_write(dap, AP_REG_TAR, tar); + int retval = dap_queue_ap_write(dap, MEM_AP_REG_TAR, tar); if (retval != ERROR_OK) return retval; - dap->ap_tar_value = tar; + dap->ap[dap_ap_get_select(dap)].tar_value = tar; } return ERROR_OK; } @@ -149,7 +148,7 @@ static int dap_setup_accessport_tar(struct adiv5_dap *dap, uint32_t tar) * Queue transactions setting up transfer parameters for the * currently selected MEM-AP. * - * Subsequent transfers using registers like AP_REG_DRW or AP_REG_BD2 + * Subsequent transfers using registers like MEM_AP_REG_DRW or MEM_AP_REG_BD2 * initiate data reads or writes using memory or peripheral addresses. * If the CSW is configured for it, the TAR may be automatically * incremented after each transfer. @@ -187,7 +186,7 @@ int dap_setup_accessport(struct adiv5_dap *dap, uint32_t csw, uint32_t tar) * * @return ERROR_OK for success. Otherwise a fault code. */ -int mem_ap_read_u32(struct adiv5_dap *dap, uint32_t address, +static int mem_ap_read_u32(struct adiv5_dap *dap, uint32_t address, uint32_t *value) { int retval; @@ -200,7 +199,7 @@ int mem_ap_read_u32(struct adiv5_dap *dap, uint32_t address, if (retval != ERROR_OK) return retval; - return dap_queue_ap_read(dap, AP_REG_BD0 | (address & 0xC), value); + return dap_queue_ap_read(dap, MEM_AP_REG_BD0 | (address & 0xC), value); } /** @@ -215,7 +214,7 @@ int mem_ap_read_u32(struct adiv5_dap *dap, uint32_t address, * @return ERROR_OK for success; *value holds the result. * Otherwise a fault code. */ -int mem_ap_read_atomic_u32(struct adiv5_dap *dap, uint32_t address, +static int mem_ap_read_atomic_u32(struct adiv5_dap *dap, uint32_t address, uint32_t *value) { int retval; @@ -238,7 +237,7 @@ int mem_ap_read_atomic_u32(struct adiv5_dap *dap, uint32_t address, * * @return ERROR_OK for success. Otherwise a fault code. */ -int mem_ap_write_u32(struct adiv5_dap *dap, uint32_t address, +static int mem_ap_write_u32(struct adiv5_dap *dap, uint32_t address, uint32_t value) { int retval; @@ -251,7 +250,7 @@ int mem_ap_write_u32(struct adiv5_dap *dap, uint32_t address, if (retval != ERROR_OK) return retval; - return dap_queue_ap_write(dap, AP_REG_BD0 | (address & 0xC), + return dap_queue_ap_write(dap, MEM_AP_REG_BD0 | (address & 0xC), value); } @@ -266,7 +265,7 @@ int mem_ap_write_u32(struct adiv5_dap *dap, uint32_t address, * * @return ERROR_OK for success; the data was written. Otherwise a fault code. */ -int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address, +static int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address, uint32_t value) { int retval = mem_ap_write_u32(dap, address, value); @@ -289,9 +288,10 @@ int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address, * should normally be true, except when writing to e.g. a FIFO. * @return ERROR_OK on success, otherwise an error code. */ -int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, uint32_t count, +static int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address, bool addrinc) { + struct adiv5_ap *ap = &dap->ap[dap_ap_get_select(dap)]; size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; @@ -324,7 +324,7 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui return ERROR_TARGET_UNALIGNED_ACCESS; } - if (dap->unaligned_access_bad && (address % size != 0)) + if (ap->unaligned_access_bad && (address % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; retval = dap_setup_accessport_tar(dap, address ^ addr_xor); @@ -335,8 +335,8 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui uint32_t this_size = size; /* Select packed transfer if possible */ - if (addrinc && dap->packed_transfers && nbytes >= 4 - && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) { + if (addrinc && ap->packed_transfers && nbytes >= 4 + && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED); } else { @@ -379,12 +379,12 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui nbytes -= this_size; - retval = dap_queue_ap_write(dap, AP_REG_DRW, outvalue); + retval = dap_queue_ap_write(dap, MEM_AP_REG_DRW, outvalue); if (retval != ERROR_OK) break; /* Rewrite TAR if it wrapped or we're xoring addresses */ - if (addrinc && (addr_xor || (address % dap->tar_autoincr_block < size && nbytes > 0))) { + if (addrinc && (addr_xor || (address % ap->tar_autoincr_block < size && nbytes > 0))) { retval = dap_setup_accessport_tar(dap, address ^ addr_xor); if (retval != ERROR_OK) break; @@ -397,7 +397,7 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui if (retval != ERROR_OK) { uint32_t tar; - if (dap_queue_ap_read(dap, AP_REG_TAR, &tar) == ERROR_OK + if (dap_queue_ap_read(dap, MEM_AP_REG_TAR, &tar) == ERROR_OK && dap_run(dap) == ERROR_OK) LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar); else @@ -419,9 +419,10 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui * should normally be true, except when reading from e.g. a FIFO. * @return ERROR_OK on success, otherwise an error code. */ -int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t count, +static int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t adr, bool addrinc) { + struct adiv5_ap *ap = &dap->ap[dap_ap_get_select(dap)]; size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; @@ -444,7 +445,7 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t else return ERROR_TARGET_UNALIGNED_ACCESS; - if (dap->unaligned_access_bad && (adr % size != 0)) + if (ap->unaligned_access_bad && (adr % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; /* Allocate buffer to hold the sequence of DRW reads that will be made. This is a significant @@ -470,8 +471,8 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t uint32_t this_size = size; /* Select packed transfer if possible */ - if (addrinc && dap->packed_transfers && nbytes >= 4 - && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) { + if (addrinc && ap->packed_transfers && nbytes >= 4 + && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED); } else { @@ -480,7 +481,7 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t if (retval != ERROR_OK) break; - retval = dap_queue_ap_read(dap, AP_REG_DRW, read_ptr++); + retval = dap_queue_ap_read(dap, MEM_AP_REG_DRW, read_ptr++); if (retval != ERROR_OK) break; @@ -488,7 +489,7 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t address += this_size; /* Rewrite TAR if it wrapped */ - if (addrinc && address % dap->tar_autoincr_block < size && nbytes > 0) { + if (addrinc && address % ap->tar_autoincr_block < size && nbytes > 0) { retval = dap_setup_accessport_tar(dap, address); if (retval != ERROR_OK) break; @@ -507,7 +508,7 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t * at least give the caller what we have. */ if (retval != ERROR_OK) { uint32_t tar; - if (dap_queue_ap_read(dap, AP_REG_TAR, &tar) == ERROR_OK + if (dap_queue_ap_read(dap, MEM_AP_REG_TAR, &tar) == ERROR_OK && dap_run(dap) == ERROR_OK) { LOG_ERROR("Failed to read memory at 0x%08"PRIx32, tar); if (nbytes > tar - address) @@ -522,8 +523,8 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t while (nbytes > 0) { uint32_t this_size = size; - if (addrinc && dap->packed_transfers && nbytes >= 4 - && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) { + if (addrinc && ap->packed_transfers && nbytes >= 4 + && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; } @@ -628,6 +629,23 @@ extern const struct dap_ops jtag_dp_ops; /*--------------------------------------------------------------------------*/ +/** + * Create a new DAP + */ +struct adiv5_dap *dap_init(void) +{ + struct adiv5_dap *dap = calloc(1, sizeof(struct adiv5_dap)); + int i; + /* Set up with safe defaults */ + for (i = 0; i <= 255; i++) { + /* memaccess_tck max is 255 */ + dap->ap[i].memaccess_tck = 255; + /* Number of bits for tar autoincrement, impl. dep. at least 10 */ + dap->ap[i].tar_autoincr_block = (1<<10); + } + return dap; +} + /** * Initialize a DAP. This sets up the power domains, prepares the DP * for further use, and arranges to use AP #0 for all AP operations @@ -640,11 +658,12 @@ extern const struct dap_ops jtag_dp_ops; * in layering. (JTAG is useful without any debug target; but not SWD.) * And this may not even use an AHB-AP ... e.g. DAP-Lite uses an APB-AP. */ -int ahbap_debugport_init(struct adiv5_dap *dap) +int ahbap_debugport_init(struct adiv5_dap *dap, uint8_t apsel) { /* check that we support packed transfers */ uint32_t csw, cfg; int retval; + struct adiv5_ap *ap = &dap->ap[apsel]; LOG_DEBUG(" "); @@ -661,8 +680,8 @@ int ahbap_debugport_init(struct adiv5_dap *dap) * Should we probe, or take a hint from the caller? * Presumably we can ignore the possibility of multiple APs. */ - dap->ap_current = !0; - dap_ap_select(dap, 0); + dap->ap_current = -1; + dap_ap_select(dap, apsel); dap->last_read = NULL; for (size_t i = 0; i < 10; i++) { @@ -718,11 +737,11 @@ int ahbap_debugport_init(struct adiv5_dap *dap) if (retval != ERROR_OK) continue; - retval = dap_queue_ap_read(dap, AP_REG_CSW, &csw); + retval = dap_queue_ap_read(dap, MEM_AP_REG_CSW, &csw); if (retval != ERROR_OK) continue; - retval = dap_queue_ap_read(dap, AP_REG_CFG, &cfg); + retval = dap_queue_ap_read(dap, MEM_AP_REG_CFG, &cfg); if (retval != ERROR_OK) continue; @@ -737,17 +756,17 @@ int ahbap_debugport_init(struct adiv5_dap *dap) return retval; if (csw & CSW_ADDRINC_PACKED) - dap->packed_transfers = true; + ap->packed_transfers = true; else - dap->packed_transfers = false; + ap->packed_transfers = false; /* Packed transfers on TI BE-32 processors do not work correctly in * many cases. */ if (dap->ti_be_32_quirks) - dap->packed_transfers = false; + ap->packed_transfers = false; LOG_DEBUG("MEM_AP Packed Transfers: %s", - dap->packed_transfers ? "enabled" : "disabled"); + ap->packed_transfers ? "enabled" : "disabled"); /* The ARM ADI spec leaves implementation-defined whether unaligned * memory accesses work, only work partially, or cause a sticky error. @@ -755,7 +774,7 @@ int ahbap_debugport_init(struct adiv5_dap *dap) * and unaligned writes seem to cause a sticky error. * TODO: it would be nice to have a way to detect whether unaligned * operations are supported on other processors. */ - dap->unaligned_access_bad = dap->ti_be_32_quirks; + ap->unaligned_access_bad = dap->ti_be_32_quirks; LOG_DEBUG("MEM_AP CFG: large data %d, long address %d, big-endian %d", !!(cfg & 0x04), !!(cfg & 0x02), !!(cfg & 0x01)); @@ -844,10 +863,10 @@ int dap_get_debugbase(struct adiv5_dap *dap, int ap, if (ap >= 256) return ERROR_COMMAND_SYNTAX_ERROR; - ap_old = dap->ap_current; + ap_old = dap_ap_get_select(dap); dap_ap_select(dap, ap); - retval = dap_queue_ap_read(dap, AP_REG_BASE, dbgbase); + retval = dap_queue_ap_read(dap, MEM_AP_REG_BASE, dbgbase); if (retval != ERROR_OK) return retval; retval = dap_queue_ap_read(dap, AP_REG_IDR, apid); @@ -873,7 +892,7 @@ int dap_lookup_cs_component(struct adiv5_dap *dap, int ap, return ERROR_COMMAND_SYNTAX_ERROR; *addr = 0; - ap_old = dap->ap_current; + ap_old = dap_ap_get_select(dap); dap_ap_select(dap, ap); do { @@ -1408,7 +1427,7 @@ static int dap_info_command(struct command_context *cmd_ctx, if (retval != ERROR_OK) return retval; - ap_old = dap->ap_current; + ap_old = dap_ap_get_select(dap); dap_ap_select(dap, ap); /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ @@ -1499,7 +1518,7 @@ COMMAND_HANDLER(dap_baseaddr_command) * though they're not common for now. This should * use the ID register to verify it's a MEM-AP. */ - retval = dap_queue_ap_read(dap, AP_REG_BASE, &baseaddr); + retval = dap_queue_ap_read(dap, MEM_AP_REG_BASE, &baseaddr); if (retval != ERROR_OK) return retval; retval = dap_run(dap); @@ -1521,7 +1540,7 @@ COMMAND_HANDLER(dap_memaccess_command) switch (CMD_ARGC) { case 0: - memaccess_tck = dap->memaccess_tck; + memaccess_tck = dap->ap[dap->apsel].memaccess_tck; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], memaccess_tck); @@ -1529,10 +1548,10 @@ COMMAND_HANDLER(dap_memaccess_command) default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->memaccess_tck = memaccess_tck; + dap->ap[dap->apsel].memaccess_tck = memaccess_tck; command_print(CMD_CTX, "memory bus access delay set to %" PRIi32 " tck", - dap->memaccess_tck); + dap->ap[dap->apsel].memaccess_tck); return ERROR_OK; } @@ -1582,7 +1601,7 @@ COMMAND_HANDLER(dap_apcsw_command) struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; - uint32_t apcsw = dap->apcsw[dap->apsel], sprot = 0; + uint32_t apcsw = dap->ap[dap->apsel].csw_default, sprot = 0; switch (CMD_ARGC) { case 0: @@ -1602,7 +1621,7 @@ COMMAND_HANDLER(dap_apcsw_command) default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->apcsw[dap->apsel] = apcsw; + dap->ap[dap->apsel].csw_default = apcsw; return 0; }