X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farm_dap.c;h=59d577e7f0407cfe2b8a45a80950ad3936dc723f;hb=1fe82f9f1db62f0ab59471e1cdaf02643bf7a66c;hp=0eb55a9cbec076d99625032d7d6791990e6af67b;hpb=bb78fa10c77411bbdf665c17eac954b7741f2040;p=openocd.git diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 0eb55a9cbe..59d577e7f0 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); @@ -127,6 +129,14 @@ static int dap_init_all(void) } else dap->ops = &jtag_dp_ops; + if (dap->adi_version == 0) { + LOG_DEBUG("DAP %s configured by default to use ADIv5 protocol", jtag_tap_name(dap->tap)); + dap->adi_version = 5; + } else { + LOG_DEBUG("DAP %s configured to use %s protocol by user cfg file", jtag_tap_name(dap->tap), + is_adiv6(dap) ? "ADIv6" : "ADIv5"); + } + retval = dap->ops->connect(dap); if (retval != ERROR_OK) return retval; @@ -142,6 +152,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); @@ -155,11 +169,19 @@ int dap_cleanup_all(void) enum dap_cfg_param { CFG_CHAIN_POSITION, CFG_IGNORE_SYSPWRUPACK, + CFG_DP_ID, + CFG_INSTANCE_ID, + CFG_ADIV6, + CFG_ADIV5, }; static const struct jim_nvp nvp_config_opts[] = { - { .name = "-chain-position", .value = CFG_CHAIN_POSITION }, + { .name = "-chain-position", .value = CFG_CHAIN_POSITION }, { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK }, + { .name = "-dp-id", .value = CFG_DP_ID }, + { .name = "-instance-id", .value = CFG_INSTANCE_ID }, + { .name = "-adiv6", .value = CFG_ADIV6 }, + { .name = "-adiv5", .value = CFG_ADIV5 }, { .name = NULL, .value = -1 } }; @@ -197,6 +219,54 @@ static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap case CFG_IGNORE_SYSPWRUPACK: dap->dap.ignore_syspwrupack = true; break; + case CFG_DP_ID: { + jim_wide w; + e = jim_getopt_wide(goi, &w); + if (e != JIM_OK) { + Jim_SetResultFormatted(goi->interp, + "create %s: bad parameter %s", + dap->name, n->name); + return JIM_ERR; + } + if (w < 0 || w > DP_TARGETSEL_DPID_MASK) { + Jim_SetResultFormatted(goi->interp, + "create %s: %s out of range", + dap->name, n->name); + return JIM_ERR; + } + dap->dap.multidrop_targetsel = + (dap->dap.multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK) + | (w & DP_TARGETSEL_DPID_MASK); + dap->dap.multidrop_dp_id_valid = true; + break; + } + case CFG_INSTANCE_ID: { + jim_wide w; + e = jim_getopt_wide(goi, &w); + if (e != JIM_OK) { + Jim_SetResultFormatted(goi->interp, + "create %s: bad parameter %s", + dap->name, n->name); + return JIM_ERR; + } + if (w < 0 || w > 15) { + Jim_SetResultFormatted(goi->interp, + "create %s: %s out of range", + dap->name, n->name); + return JIM_ERR; + } + dap->dap.multidrop_targetsel = + (dap->dap.multidrop_targetsel & DP_TARGETSEL_DPID_MASK) + | ((w << DP_TARGETSEL_INSTANCEID_SHIFT) & DP_TARGETSEL_INSTANCEID_MASK); + dap->dap.multidrop_instance_id_valid = true; + break; + } + case CFG_ADIV6: + dap->dap.adi_version = 6; + break; + case CFG_ADIV5: + dap->dap.adi_version = 5; + break; default: break; } @@ -205,6 +275,52 @@ static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap return JIM_OK; } +static int dap_check_config(struct adiv5_dap *dap) +{ + if (transport_is_jtag() || transport_is_dapdirect_jtag() || transport_is_hla()) + return ERROR_OK; + + struct arm_dap_object *obj; + bool new_multidrop = dap_is_multidrop(dap); + bool had_multidrop = new_multidrop; + uint32_t targetsel = dap->multidrop_targetsel; + unsigned int non_multidrop_count = had_multidrop ? 0 : 1; + + list_for_each_entry(obj, &all_dap, lh) { + struct adiv5_dap *dap_it = &obj->dap; + + if (transport_is_swd()) { + if (dap_is_multidrop(dap_it)) { + had_multidrop = true; + if (new_multidrop && dap_it->multidrop_targetsel == targetsel) { + uint32_t dp_id = targetsel & DP_TARGETSEL_DPID_MASK; + uint32_t instance_id = targetsel >> DP_TARGETSEL_INSTANCEID_SHIFT; + LOG_ERROR("%s and %s have the same multidrop selectors -dp-id 0x%08" + PRIx32 " and -instance-id 0x%" PRIx32, + obj->name, adiv5_dap_name(dap), + dp_id, instance_id); + return ERROR_FAIL; + } + } else { + non_multidrop_count++; + } + } else if (transport_is_dapdirect_swd()) { + non_multidrop_count++; + } + } + + if (non_multidrop_count > 1) { + LOG_ERROR("Two or more SWD non multidrop DAPs are not supported"); + return ERROR_FAIL; + } + if (had_multidrop && non_multidrop_count) { + LOG_ERROR("Mixing of SWD multidrop DAPs and non multidrop DAPs is not supported"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + static int dap_create(struct jim_getopt_info *goi) { struct command_context *cmd_ctx; @@ -251,7 +367,13 @@ static int dap_create(struct jim_getopt_info *goi) goto err; } - struct command_registration dap_commands[] = { + e = dap_check_config(&dap->dap); + if (e != ERROR_OK) { + e = JIM_ERR; + goto err; + } + + struct command_registration dap_create_commands[] = { { .name = cp, .mode = COMMAND_ANY, @@ -264,9 +386,9 @@ static int dap_create(struct jim_getopt_info *goi) /* don't expose the instance commands when using hla */ if (transport_is_hla()) - dap_commands[0].chain = NULL; + dap_create_commands[0].chain = NULL; - e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap); + e = register_commands_with_data(cmd_ctx, NULL, dap_create_commands, dap); if (e != ERROR_OK) { e = JIM_ERR; goto err; @@ -340,7 +462,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[] = {