X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.c;h=03e642bfeaec701b228a40195208cb652dc41507;hp=302ea78913cdc939ef9f92952fc670d8b345169c;hb=1e3ba2046cf93dd037fd6e5c7babf95dd2716a1f;hpb=e48690cb26e4ab3499623c70feae7ad7c54b94bd diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 302ea78913..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: @@ -1625,7 +1648,7 @@ COMMAND_HANDLER(dap_apsel_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: @@ -1691,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: @@ -1722,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); @@ -1734,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 */