X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.c;h=03e642bfeaec701b228a40195208cb652dc41507;hp=4dc2594cf52169b28489d16a9f0b99eeec63c77a;hb=1e3ba2046cf93dd037fd6e5c7babf95dd2716a1f;hpb=1dc466f5156741f643c946485cdf280a1054fc7a diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 4dc2594cf5..03e642bfea 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -652,6 +652,15 @@ int dap_dp_init(struct adiv5_dap *dap) dap_invalidate_cache(dap); + /* + * Early initialize dap->dp_ctrl_stat. + * In jtag mode only, if the following atomic reads fail and set the + * sticky error, it will trigger the clearing of the sticky. Without this + * initialization system and debug power would be disabled while clearing + * the sticky error bit. + */ + dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; + for (size_t i = 0; i < 30; i++) { /* DP initialization */ @@ -660,7 +669,18 @@ int dap_dp_init(struct adiv5_dap *dap) break; } - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); + /* + * This write operation clears the sticky error bit in jtag mode only and + * is ignored in swd mode. It also powers-up system and debug domains in + * both jtag and swd modes, if not done before. + * Actually we do not need to clear the sticky error here because it has + * been already cleared (if it was set) in the previous atomic read. This + * write could be removed, but this initial part of dap_dp_init() is the + * result of years of fine tuning and there are strong concerns about any + * unnecessary code change. It doesn't harm, so let's keep it here and + * preserve the historical sequence of read/write operations! + */ + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat | SSTICKYERR); if (retval != ERROR_OK) return retval; @@ -668,7 +688,6 @@ int dap_dp_init(struct adiv5_dap *dap) if (retval != ERROR_OK) return retval; - dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); if (retval != ERROR_OK) return retval; @@ -793,7 +812,7 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a int ap_num; /* Maximum AP number is 255 since the SELECT register is 8 bits */ - for (ap_num = 0; ap_num <= 255; ap_num++) { + for (ap_num = 0; ap_num <= DP_APSEL_MAX; ap_num++) { /* read the IDR register of the Access Port */ uint32_t id_val = 0; @@ -1429,7 +1448,7 @@ int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi) pc = (struct adiv5_private_config *)target->private_config; if (pc == NULL) { pc = calloc(1, sizeof(struct adiv5_private_config)); - pc->ap_num = -1; + pc->ap_num = DP_APSEL_INVALID; target->private_config = pc; } @@ -1498,6 +1517,10 @@ int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi) e = Jim_GetOpt_Wide(goi, &ap_num); if (e != JIM_OK) return e; + if (ap_num < 0 || ap_num > DP_APSEL_MAX) { + Jim_SetResultString(goi->interp, "Invalid AP number!", -1); + return JIM_ERR; + } pc->ap_num = ap_num; } else { if (goi->argc != 0) { @@ -1507,11 +1530,11 @@ int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi) return JIM_ERR; } - if (pc->ap_num < 0) { + if (pc->ap_num == DP_APSEL_INVALID) { Jim_SetResultString(goi->interp, "AP number not configured", -1); return JIM_ERR; } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, (int)pc->ap_num)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, pc->ap_num)); } break; } @@ -1543,7 +1566,7 @@ COMMAND_HANDLER(handle_dap_info_command) break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); - if (apsel >= 256) + if (apsel > DP_APSEL_MAX) return ERROR_COMMAND_SYNTAX_ERROR; break; default: @@ -1566,7 +1589,7 @@ COMMAND_HANDLER(dap_baseaddr_command) case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ - if (apsel >= 256) + if (apsel > DP_APSEL_MAX) return ERROR_COMMAND_SYNTAX_ERROR; break; default: @@ -1616,17 +1639,16 @@ COMMAND_HANDLER(dap_memaccess_command) COMMAND_HANDLER(dap_apsel_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); - uint32_t apsel, apid; - int retval; + uint32_t apsel; switch (CMD_ARGC) { case 0: - apsel = dap->apsel; - break; + command_print(CMD_CTX, "%" PRIi32, dap->apsel); + return ERROR_OK; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ - if (apsel >= 256) + if (apsel > DP_APSEL_MAX) return ERROR_COMMAND_SYNTAX_ERROR; break; default: @@ -1634,18 +1656,7 @@ COMMAND_HANDLER(dap_apsel_command) } dap->apsel = apsel; - - retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid); - if (retval != ERROR_OK) - return retval; - retval = dap_run(dap); - if (retval != ERROR_OK) - return retval; - - command_print(CMD_CTX, "ap %" PRIi32 " selected, identification register 0x%8.8" PRIx32, - apsel, apid); - - return retval; + return ERROR_OK; } COMMAND_HANDLER(dap_apcsw_command) @@ -1703,7 +1714,7 @@ COMMAND_HANDLER(dap_apid_command) case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ - if (apsel >= 256) + if (apsel > DP_APSEL_MAX) return ERROR_COMMAND_SYNTAX_ERROR; break; default: @@ -1734,7 +1745,7 @@ COMMAND_HANDLER(dap_apreg_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ - if (apsel >= 256) + if (apsel > DP_APSEL_MAX) return ERROR_COMMAND_SYNTAX_ERROR; ap = dap_ap(dap, apsel); @@ -1746,8 +1757,10 @@ COMMAND_HANDLER(dap_apreg_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); switch (reg) { case MEM_AP_REG_CSW: - ap->csw_default = 0; /* invalid, force write */ - retval = mem_ap_setup_csw(ap, value); + ap->csw_value = 0; /* invalid, in case write fails */ + retval = dap_queue_ap_write(ap, reg, value); + if (retval == ERROR_OK) + ap->csw_value = value; break; case MEM_AP_REG_TAR: ap->tar_valid = false; /* invalid, force write */ @@ -1772,6 +1785,37 @@ COMMAND_HANDLER(dap_apreg_command) return retval; } +COMMAND_HANDLER(dap_dpreg_command) +{ + struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); + uint32_t reg, value; + int retval; + + if (CMD_ARGC < 1 || CMD_ARGC > 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], reg); + if (reg >= 256 || (reg & 3)) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 2) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + retval = dap_queue_dp_write(dap, reg, value); + } else { + retval = dap_queue_dp_read(dap, reg, &value); + } + if (retval == ERROR_OK) + retval = dap_run(dap); + + if (retval != ERROR_OK) + return retval; + + if (CMD_ARGC == 1) + command_print(CMD_CTX, "0x%08" PRIx32, value); + + return retval; +} + COMMAND_HANDLER(dap_ti_be_32_quirks_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); @@ -1807,7 +1851,7 @@ const struct command_registration dap_instance_commands[] = { { .name = "apsel", .handler = dap_apsel_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "Set the currently selected AP (default 0) " "and display the result", .usage = "[ap_num]", @@ -1815,7 +1859,7 @@ const struct command_registration dap_instance_commands[] = { { .name = "apcsw", .handler = dap_apcsw_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "Set CSW default bits", .usage = "[value [mask]]", }, @@ -1836,6 +1880,14 @@ const struct command_registration dap_instance_commands[] = { "(reg is byte address of a word register, like 0 4 8...)", .usage = "ap_num reg [value]", }, + { + .name = "dpreg", + .handler = dap_dpreg_command, + .mode = COMMAND_EXEC, + .help = "read/write a register from DP " + "(reg is byte address (bank << 4 | reg) of a word register, like 0 4 8...)", + .usage = "reg [value]", + }, { .name = "baseaddr", .handler = dap_baseaddr_command,