diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index edb4eb58f..c1a49fd54 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -402,16 +402,23 @@ static int kinetis_auto_probe(struct flash_bank *bank); static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { - int retval; LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); - retval = dap_queue_ap_write(dap_ap(dap, MDM_AP), reg, value); + struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_write(ap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a write request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; @@ -423,15 +430,21 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3 static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { - int retval; + struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } - retval = dap_queue_ap_read(dap_ap(dap, MDM_AP), reg, result); + int retval = dap_queue_ap_read(ap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a read request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; @@ -787,12 +800,18 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) if ((val & (MDM_STAT_SYSSEC | MDM_STAT_FREADY)) != MDM_STAT_FREADY) { uint32_t stats[32]; + struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); + if (!ap) { + LOG_ERROR("MDM: failed to get AP"); + return ERROR_OK; + } for (unsigned int i = 0; i < 32; i++) { stats[i] = MDM_STAT_FREADY; - dap_queue_ap_read(dap_ap(dap, MDM_AP), MDM_REG_STAT, &stats[i]); + dap_queue_ap_read(ap, MDM_REG_STAT, &stats[i]); } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed when validating secured state"); return ERROR_OK; diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index 48749e617..fe2072865 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -147,16 +147,23 @@ struct kinetis_ke_flash_bank { static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { - int retval; LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); - retval = dap_queue_ap_write(dap_ap(dap, 1), reg, value); + struct adiv5_ap *ap = dap_get_ap(dap, 1); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_write(ap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a write request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; @@ -167,14 +174,21 @@ static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, ui static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { - int retval; - retval = dap_queue_ap_read(dap_ap(dap, 1), reg, result); + struct adiv5_ap *ap = dap_get_ap(dap, 1); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_read(ap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a read request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index 891383860..1d42ffef4 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -872,16 +872,23 @@ static int sim3x_flash_info(struct flash_bank *bank, struct command_invocation * */ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { - int retval; LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value); - retval = dap_queue_ap_write(dap_ap(dap, SIM3X_AP), reg, value); + struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP); + if (!ap) { + LOG_DEBUG("DAP: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_write(ap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("DAP: failed to queue a write request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("DAP: dap_run failed"); return retval; @@ -892,15 +899,21 @@ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { - int retval; + struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP); + if (!ap) { + LOG_DEBUG("DAP: failed to get AP"); + return ERROR_FAIL; + } - retval = dap_queue_ap_read(dap_ap(dap, SIM3X_AP), reg, result); + int retval = dap_queue_ap_read(ap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("DAP: failed to queue a read request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("DAP: dap_run failed"); return retval; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index ecd93248c..8a8f21d13 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2558,15 +2558,24 @@ static int aarch64_examine_first(struct target *target) if (!pc) return ERROR_FAIL; + if (armv8->debug_ap) { + dap_put_ap(armv8->debug_ap); + armv8->debug_ap = NULL; + } + if (pc->adiv5_config.ap_num == DP_APSEL_INVALID) { /* Search for the APB-AB */ - retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap); + retval = dap_find_get_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap); if (retval != ERROR_OK) { LOG_ERROR("Could not find APB-AP for debug access"); return retval; } } else { - armv8->debug_ap = dap_ap(swjdp, pc->adiv5_config.ap_num); + armv8->debug_ap = dap_get_ap(swjdp, pc->adiv5_config.ap_num); + if (!armv8->debug_ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } } retval = mem_ap_init(armv8->debug_ap); @@ -2755,6 +2764,9 @@ static void aarch64_deinit_target(struct target *target) struct armv8_common *armv8 = &aarch64->armv8_common; struct arm_dpm *dpm = &armv8->dpm; + if (armv8->debug_ap) + dap_put_ap(armv8->debug_ap); + armv8_free_reg_cache(target); free(aarch64->brp_list); free(dpm->dbp); diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 4d5f02b32..7dd523ef0 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -968,20 +968,26 @@ static const char *ap_type_to_description(enum ap_type type) /* * This function checks the ID for each access port to find the requested Access Port type + * It also calls dap_get_ap() to increment the AP refcount */ -int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out) +int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out) { int ap_num; /* Maximum AP number is 255 since the SELECT register is 8 bits */ for (ap_num = 0; ap_num <= DP_APSEL_MAX; ap_num++) { + struct adiv5_ap *ap = dap_get_ap(dap, ap_num); + if (!ap) + continue; /* read the IDR register of the Access Port */ uint32_t id_val = 0; - int retval = dap_queue_ap_read(dap_ap(dap, ap_num), AP_REG_IDR, &id_val); - if (retval != ERROR_OK) + int retval = dap_queue_ap_read(ap, AP_REG_IDR, &id_val); + if (retval != ERROR_OK) { + dap_put_ap(ap); return retval; + } retval = dap_run(dap); @@ -993,15 +999,73 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a ap_type_to_description(type_to_find), ap_num, id_val); - *ap_out = &dap->ap[ap_num]; + *ap_out = ap; return ERROR_OK; } + dap_put_ap(ap); } LOG_DEBUG("No %s found", ap_type_to_description(type_to_find)); return ERROR_FAIL; } +static inline bool is_ap_in_use(struct adiv5_ap *ap) +{ + return ap->refcount > 0 || ap->config_ap_never_release; +} + +static struct adiv5_ap *_dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num) +{ + if (ap_num > DP_APSEL_MAX) { + LOG_ERROR("Invalid AP#%u", ap_num); + return NULL; + } + struct adiv5_ap *ap = &dap->ap[ap_num]; + ++ap->refcount; + return ap; +} + +/* Return AP with specified ap_num. Increment AP refcount */ +struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num) +{ + struct adiv5_ap *ap = _dap_get_ap(dap, ap_num); + if (ap) + LOG_DEBUG("refcount AP#%u get %u", ap_num, ap->refcount); + return ap; +} + +/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */ +struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, unsigned int ap_num) +{ + struct adiv5_ap *ap = _dap_get_ap(dap, ap_num); + if (ap) { + ap->config_ap_never_release = true; + LOG_DEBUG("refcount AP#%u get_config %u", ap_num, ap->refcount); + } + return ap; +} + +/* Decrement AP refcount and release the AP when refcount reaches zero */ +int dap_put_ap(struct adiv5_ap *ap) +{ + if (ap->refcount == 0) { + LOG_ERROR("BUG: refcount AP#%" PRIu8 " put underflow", ap->ap_num); + return ERROR_FAIL; + } + + --ap->refcount; + + LOG_DEBUG("refcount AP#%" PRIu8 " put %u", ap->ap_num, ap->refcount); + if (!is_ap_in_use(ap)) { + /* defaults from dap_instance_init() */ + ap->memaccess_tck = 255; + ap->tar_autoincr_block = (1 << 10); + ap->csw_default = CSW_AHB_DEFAULT; + ap->cfg_reg = MEM_AP_REG_CFG_INVALID; + } + return ERROR_OK; +} + static int dap_get_debugbase(struct adiv5_ap *ap, target_addr_t *dbgbase, uint32_t *apid) { @@ -2117,7 +2181,15 @@ COMMAND_HANDLER(handle_dap_info_command) return ERROR_COMMAND_SYNTAX_ERROR; } - return dap_info_command(CMD, &dap->ap[apsel]); + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + + int retval = dap_info_command(CMD, ap); + dap_put_ap(ap); + return retval; } COMMAND_HANDLER(dap_baseaddr_command) @@ -2152,7 +2224,12 @@ COMMAND_HANDLER(dap_baseaddr_command) * use the ID register to verify it's a MEM-AP. */ - ap = dap_ap(dap, apsel); + ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseaddr_lower); if (retval == ERROR_OK && ap->cfg_reg == MEM_AP_REG_CFG_INVALID) @@ -2165,6 +2242,7 @@ COMMAND_HANDLER(dap_baseaddr_command) if (retval == ERROR_OK) retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) return retval; @@ -2180,22 +2258,35 @@ COMMAND_HANDLER(dap_baseaddr_command) COMMAND_HANDLER(dap_memaccess_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); + struct adiv5_ap *ap; uint32_t memaccess_tck; switch (CMD_ARGC) { case 0: - memaccess_tck = dap->ap[dap->apsel].memaccess_tck; + ap = dap_get_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + memaccess_tck = ap->memaccess_tck; break; case 1: + ap = dap_get_config_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], memaccess_tck); + ap->memaccess_tck = memaccess_tck; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->ap[dap->apsel].memaccess_tck = memaccess_tck; + + dap_put_ap(ap); command_print(CMD, "memory bus access delay set to %" PRIu32 " tck", - dap->ap[dap->apsel].memaccess_tck); + memaccess_tck); return ERROR_OK; } @@ -2228,14 +2319,19 @@ COMMAND_HANDLER(dap_apsel_command) COMMAND_HANDLER(dap_apcsw_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); - uint32_t apcsw = dap->ap[dap->apsel].csw_default; + struct adiv5_ap *ap; uint32_t csw_val, csw_mask; switch (CMD_ARGC) { case 0: + ap = dap_get_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } command_print(CMD, "ap %" PRIu32 " selected, csw 0x%8.8" PRIx32, - dap->apsel, apcsw); - return ERROR_OK; + dap->apsel, ap->csw_default); + break; case 1: if (strcmp(CMD_ARGV[0], "default") == 0) csw_val = CSW_AHB_DEFAULT; @@ -2246,7 +2342,12 @@ COMMAND_HANDLER(dap_apcsw_command) LOG_ERROR("CSW value cannot include 'Size' and 'AddrInc' bit-fields"); return ERROR_COMMAND_ARGUMENT_INVALID; } - apcsw = csw_val; + ap = dap_get_config_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + ap->csw_default = csw_val; break; case 2: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], csw_val); @@ -2255,14 +2356,19 @@ COMMAND_HANDLER(dap_apcsw_command) LOG_ERROR("CSW mask cannot include 'Size' and 'AddrInc' bit-fields"); return ERROR_COMMAND_ARGUMENT_INVALID; } - apcsw = (apcsw & ~csw_mask) | (csw_val & csw_mask); + ap = dap_get_config_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + ap->csw_default = (ap->csw_default & ~csw_mask) | (csw_val & csw_mask); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->ap[dap->apsel].csw_default = apcsw; + dap_put_ap(ap); - return 0; + return ERROR_OK; } @@ -2289,10 +2395,18 @@ COMMAND_HANDLER(dap_apid_command) return ERROR_COMMAND_SYNTAX_ERROR; } - retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid); - if (retval != ERROR_OK) + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + retval = dap_queue_ap_read(ap, AP_REG_IDR, &apid); + if (retval != ERROR_OK) { + dap_put_ap(ap); return retval; + } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) return retval; @@ -2305,7 +2419,6 @@ COMMAND_HANDLER(dap_apreg_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); uint32_t apsel, reg, value; - struct adiv5_ap *ap; int retval; if (CMD_ARGC < 2 || CMD_ARGC > 3) @@ -2318,14 +2431,18 @@ COMMAND_HANDLER(dap_apreg_command) return ERROR_COMMAND_ARGUMENT_INVALID; } - ap = dap_ap(dap, apsel); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg); if (reg >= 256 || (reg & 3)) { command_print(CMD, "Invalid reg value (should be less than 256 and 4 bytes aligned)"); return ERROR_COMMAND_ARGUMENT_INVALID; } + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + if (CMD_ARGC == 3) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); switch (reg) { @@ -2366,6 +2483,8 @@ COMMAND_HANDLER(dap_apreg_command) if (retval == ERROR_OK) retval = dap_run(dap); + dap_put_ap(ap); + if (retval != ERROR_OK) return retval; diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 8c9a60f25..c7ffe7b31 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -259,6 +259,12 @@ struct adiv5_ap { /* MEM AP configuration register indicating LPAE support */ uint32_t cfg_reg; + + /* references counter */ + unsigned int refcount; + + /* AP referenced during config. Never put it, even when refcount reaches zero */ + bool config_ap_never_release; }; @@ -486,6 +492,10 @@ static inline int dap_queue_ap_read(struct adiv5_ap *ap, unsigned reg, uint32_t *data) { assert(ap->dap->ops); + if (ap->refcount == 0) { + ap->refcount = 1; + LOG_ERROR("BUG: refcount AP#%" PRIu8 " used without get", ap->ap_num); + } return ap->dap->ops->queue_ap_read(ap, reg, data); } @@ -502,6 +512,10 @@ static inline int dap_queue_ap_write(struct adiv5_ap *ap, unsigned reg, uint32_t data) { assert(ap->dap->ops); + if (ap->refcount == 0) { + ap->refcount = 1; + LOG_ERROR("BUG: refcount AP#%" PRIu8 " used without get", ap->ap_num); + } return ap->dap->ops->queue_ap_write(ap, reg, data); } @@ -619,15 +633,19 @@ int mem_ap_init(struct adiv5_ap *ap); /* Invalidate cached DP select and cached TAR and CSW of all APs */ void dap_invalidate_cache(struct adiv5_dap *dap); -/* Probe Access Ports to find a particular type */ -int dap_find_ap(struct adiv5_dap *dap, +/* Probe Access Ports to find a particular type. Increment AP refcount */ +int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out); -static inline struct adiv5_ap *dap_ap(struct adiv5_dap *dap, uint8_t ap_num) -{ - return &dap->ap[ap_num]; -} +/* Return AP with specified ap_num. Increment AP refcount */ +struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num); + +/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */ +struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, unsigned int ap_num); + +/* Decrement AP refcount and release the AP when refcount reaches zero */ +int dap_put_ap(struct adiv5_ap *ap); /** Check if SWD multidrop configuration is valid */ static inline bool dap_is_multidrop(struct adiv5_dap *dap) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 96927bf94..74388aef9 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -34,6 +34,7 @@ struct arm_cti { struct list_head lh; char *name; struct adiv5_mem_ap_spot spot; + struct adiv5_ap *ap; }; static LIST_HEAD(all_cti); @@ -65,7 +66,7 @@ struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); + struct adiv5_ap *ap = self->ap; uint32_t tmp; /* Read register */ @@ -84,15 +85,14 @@ static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t int arm_cti_enable(struct arm_cti *self, bool enable) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); uint32_t val = enable ? 1 : 0; - return mem_ap_write_atomic_u32(ap, self->spot.base + CTI_CTR, val); + return mem_ap_write_atomic_u32(self->ap, self->spot.base + CTI_CTR, val); } int arm_cti_ack_events(struct arm_cti *self, uint32_t event) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); + struct adiv5_ap *ap = self->ap; int retval; uint32_t tmp; @@ -134,19 +134,15 @@ int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel) int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); - - return mem_ap_write_atomic_u32(ap, self->spot.base + reg, value); + return mem_ap_write_atomic_u32(self->ap, self->spot.base + reg, value); } int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); - if (!p_value) return ERROR_COMMAND_ARGUMENT_INVALID; - return mem_ap_read_atomic_u32(ap, self->spot.base + reg, p_value); + return mem_ap_read_atomic_u32(self->ap, self->spot.base + reg, p_value); } int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel) @@ -228,6 +224,8 @@ int arm_cti_cleanup_all(void) struct arm_cti *obj, *tmp; list_for_each_entry_safe(obj, tmp, &all_cti, lh) { + if (obj->ap) + dap_put_ap(obj->ap); free(obj->name); free(obj); } @@ -238,7 +236,7 @@ int arm_cti_cleanup_all(void) COMMAND_HANDLER(handle_cti_dump) { struct arm_cti *cti = CMD_DATA; - struct adiv5_ap *ap = dap_ap(cti->spot.dap, cti->spot.ap_num); + struct adiv5_ap *ap = cti->ap; int retval = ERROR_OK; for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++) @@ -518,6 +516,12 @@ static int cti_create(struct jim_getopt_info *goi) list_add_tail(&cti->lh, &all_cti); + cti->ap = dap_get_ap(cti->spot.dap, cti->spot.ap_num); + if (!cti->ap) { + Jim_SetResultString(goi->interp, "Cannot get AP", -1); + return JIM_ERR; + } + return JIM_OK; } diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 2dba45d0b..46e054e69 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -58,6 +58,8 @@ static void dap_instance_init(struct adiv5_dap *dap) /* default CSW value */ dap->ap[i].csw_default = CSW_AHB_DEFAULT; dap->ap[i].cfg_reg = MEM_AP_REG_CFG_INVALID; /* mem_ap configuration reg (large physical addr, etc.) */ + dap->ap[i].refcount = 0; + dap->ap[i].config_ap_never_release = false; } INIT_LIST_HEAD(&dap->cmd_journal); INIT_LIST_HEAD(&dap->cmd_pool); @@ -142,6 +144,10 @@ int dap_cleanup_all(void) list_for_each_entry_safe(obj, tmp, &all_dap, lh) { dap = &obj->dap; + for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) { + if (dap->ap[i].refcount != 0) + LOG_ERROR("BUG: refcount AP#%u still %u at exit", i, dap->ap[i].refcount); + } if (dap->ops && dap->ops->quit) dap->ops->quit(dap); @@ -438,7 +444,14 @@ COMMAND_HANDLER(handle_dap_info_command) return ERROR_COMMAND_SYNTAX_ERROR; } - return dap_info_command(CMD, &dap->ap[apsel]); + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + int retval = dap_info_command(CMD, ap); + dap_put_ap(ap); + return retval; } static const struct command_registration dap_subcommand_handlers[] = { diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index fba3fec4f..5cbd89b86 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -90,6 +90,7 @@ struct arm_tpiu_swo_event_action { struct arm_tpiu_swo_object { struct list_head lh; struct adiv5_mem_ap_spot spot; + struct adiv5_ap *ap; char *name; struct arm_tpiu_swo_event_action *event_action; /* record enable before init */ @@ -233,6 +234,9 @@ int arm_tpiu_swo_cleanup_all(void) ea = next; } + if (obj->ap) + dap_put_ap(obj->ap); + free(obj->name); free(obj->out_filename); free(obj); @@ -596,7 +600,6 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const struct command *c = jim_to_command(interp); struct arm_tpiu_swo_object *obj = c->jim_handler_data; struct command_context *cmd_ctx = current_command_context(interp); - struct adiv5_ap *tpiu_ap = dap_ap(obj->spot.dap, obj->spot.ap_num); uint32_t value; int retval; @@ -644,7 +647,6 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const struct cortex_m_common *cm = target_to_cm(target); obj->recheck_ap_cur_target = false; obj->spot.ap_num = cm->armv7m.debug_ap->ap_num; - tpiu_ap = dap_ap(obj->spot.dap, obj->spot.ap_num); if (obj->spot.ap_num == 0) LOG_INFO(MSG "Confirmed TPIU %s is on AP 0", obj->name); else @@ -655,10 +657,18 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const } /* END_DEPRECATED_TPIU */ + if (!obj->ap) { + obj->ap = dap_get_ap(obj->spot.dap, obj->spot.ap_num); + if (!obj->ap) { + LOG_ERROR("Cannot get AP"); + return JIM_ERR; + } + } + /* trigger the event before any attempt to R/W in the TPIU/SWO */ arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_ENABLE); - retval = wrap_read_u32(target, tpiu_ap, obj->spot.base + TPIU_DEVID_OFFSET, &value); + retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_DEVID_OFFSET, &value); if (retval != ERROR_OK) { LOG_ERROR("Unable to read %s", obj->name); return JIM_ERR; @@ -684,7 +694,7 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const } if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_SYNC) { - retval = wrap_read_u32(target, tpiu_ap, obj->spot.base + TPIU_SSPSR_OFFSET, &value); + retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_SSPSR_OFFSET, &value); if (retval != ERROR_OK) { LOG_ERROR("Cannot read TPIU register SSPSR"); return JIM_ERR; @@ -759,26 +769,26 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const obj->swo_pin_freq = swo_pin_freq; } - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_CSPSR_OFFSET, BIT(obj->port_width - 1)); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_CSPSR_OFFSET, BIT(obj->port_width - 1)); if (retval != ERROR_OK) goto error_exit; - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_ACPR_OFFSET, prescaler - 1); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_ACPR_OFFSET, prescaler - 1); if (retval != ERROR_OK) goto error_exit; - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_SPPR_OFFSET, obj->pin_protocol); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_SPPR_OFFSET, obj->pin_protocol); if (retval != ERROR_OK) goto error_exit; - retval = wrap_read_u32(target, tpiu_ap, obj->spot.base + TPIU_FFCR_OFFSET, &value); + retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_FFCR_OFFSET, &value); if (retval != ERROR_OK) goto error_exit; if (obj->en_formatter) value |= BIT(1); else value &= ~BIT(1); - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_FFCR_OFFSET, value); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_FFCR_OFFSET, value); if (retval != ERROR_OK) goto error_exit; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 20b2e5173..a20339f4b 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2885,15 +2885,24 @@ static int cortex_a_examine_first(struct target *target) int retval = ERROR_OK; uint32_t didr, cpuid, dbg_osreg, dbg_idpfr1; + if (armv7a->debug_ap) { + dap_put_ap(armv7a->debug_ap); + armv7a->debug_ap = NULL; + } + if (pc->ap_num == DP_APSEL_INVALID) { /* Search for the APB-AP - it is needed for access to debug registers */ - retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); + retval = dap_find_get_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); if (retval != ERROR_OK) { LOG_ERROR("Could not find APB-AP for debug access"); return retval; } } else { - armv7a->debug_ap = dap_ap(swjdp, pc->ap_num); + armv7a->debug_ap = dap_get_ap(swjdp, pc->ap_num); + if (!armv7a->debug_ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } } retval = mem_ap_init(armv7a->debug_ap); @@ -3172,6 +3181,9 @@ static void cortex_a_deinit_target(struct target *target) dscr & ~DSCR_HALT_DBG_MODE); } + if (armv7a->debug_ap) + dap_put_ap(armv7a->debug_ap); + free(cortex_a->wrp_list); free(cortex_a->brp_list); arm_free_reg_cache(dpm->arm); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 344cfcf61..0a7668ddf 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1984,6 +1984,10 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, void cortex_m_deinit_target(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = target_to_armv7m(target); + + if (!armv7m->is_hla_target && armv7m->debug_ap) + dap_put_ap(armv7m->debug_ap); free(cortex_m->fp_comparator_list); @@ -2262,10 +2266,10 @@ static void cortex_m_dwt_free(struct target *target) static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp, struct adiv5_ap **debug_ap) { - if (dap_find_ap(swjdp, AP_TYPE_AHB3_AP, debug_ap) == ERROR_OK) + if (dap_find_get_ap(swjdp, AP_TYPE_AHB3_AP, debug_ap) == ERROR_OK) return ERROR_OK; - return dap_find_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap); + return dap_find_get_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap); } int cortex_m_examine(struct target *target) @@ -2279,6 +2283,11 @@ int cortex_m_examine(struct target *target) /* hla_target shares the examine handler but does not support * all its calls */ if (!armv7m->is_hla_target) { + if (armv7m->debug_ap) { + dap_put_ap(armv7m->debug_ap); + armv7m->debug_ap = NULL; + } + if (cortex_m->apsel == DP_APSEL_INVALID) { /* Search for the MEM-AP */ retval = cortex_m_find_mem_ap(swjdp, &armv7m->debug_ap); @@ -2287,7 +2296,11 @@ int cortex_m_examine(struct target *target) return retval; } } else { - armv7m->debug_ap = dap_ap(swjdp, cortex_m->apsel); + armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel); + if (!armv7m->debug_ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } } armv7m->debug_ap->memaccess_tck = 8; diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index eef05b44b..86bb29f21 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -74,8 +74,13 @@ static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *ta static void mem_ap_deinit_target(struct target *target) { + struct mem_ap *mem_ap = target->arch_info; + LOG_DEBUG("%s", __func__); + if (mem_ap->ap) + dap_put_ap(mem_ap->ap); + free(target->private_config); free(target->arch_info); return; @@ -139,7 +144,16 @@ static int mem_ap_examine(struct target *target) struct mem_ap *mem_ap = target->arch_info; if (!target_was_examined(target)) { - mem_ap->ap = dap_ap(mem_ap->dap, mem_ap->ap_num); + if (mem_ap->ap) { + dap_put_ap(mem_ap->ap); + mem_ap->ap = NULL; + } + + mem_ap->ap = dap_get_ap(mem_ap->dap, mem_ap->ap_num); + if (!mem_ap->ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } target_set_examined(target); target->state = TARGET_UNKNOWN; target->debug_reason = DBG_REASON_UNDEFINED;