aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/flash/nor/kinetis.c29
-rw-r--r--src/flash/nor/kinetis_ke.c22
-rw-r--r--src/flash/nor/sim3x.c21
-rw-r--r--src/target/aarch64.c16
-rw-r--r--src/target/arm_adi_v5.c161
-rw-r--r--src/target/arm_adi_v5.h30
-rw-r--r--src/target/arm_cti.c26
-rw-r--r--src/target/arm_dap.c15
-rw-r--r--src/target/arm_tpiu_swo.c28
-rw-r--r--src/target/cortex_a.c16
-rw-r--r--src/target/cortex_m.c19
-rw-r--r--src/target/mem_ap.c16
12 files changed, 330 insertions, 69 deletions
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index edb4eb5..c1a49fd 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 48749e6..fe20728 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 8913838..1d42ffe 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 ecd9324..8a8f21d 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 4d5f02b..7dd523e 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 8c9a60f..c7ffe7b 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 96927bf..74388ae 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 2dba45d..46e054e 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 fba3fec..5cbd89b 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 20b2e51..a20339f 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 344cfcf..0a7668d 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 eef05b4..86bb29f 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;