target/aarch64: Add watchpoint support
[openocd.git] / src / target / arm_adi_v5.c
index 0584844713dcf9724cacbb53bc26c0f03f21ae0d..8f5ad59c3d398289108e8de391e4894da83f8547 100644 (file)
@@ -450,7 +450,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
  * @param buffer The data buffer to receive the data. No particular alignment is assumed.
  * @param size Which access size to use, in bytes. 1, 2 or 4.
  * @param count The number of reads to do (in size units, not bytes).
- * @param address Address to be read; it must be readable by the currently selected MEM-AP.
+ * @param adr Address to be read; it must be readable by the currently selected MEM-AP.
  * @param addrinc Whether the target address should be increased after each read or not. This
  *  should normally be true, except when reading from e.g. a FIFO.
  * @return ERROR_OK on success, otherwise an error code.
@@ -652,35 +652,22 @@ int dap_dp_init(struct adiv5_dap *dap)
 
        LOG_DEBUG("%s", adiv5_dap_name(dap));
 
+       dap->do_reconnect = false;
        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.
+        * In jtag mode only, if the following queue run (in dap_dp_poll_register)
+        * fails and sets 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 */
-
-               retval = dap_dp_read_atomic(dap, DP_CTRL_STAT, NULL);
-               if (retval == ERROR_OK)
-                       break;
-       }
-
        /*
         * 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)
@@ -731,6 +718,35 @@ int dap_dp_init(struct adiv5_dap *dap)
        return retval;
 }
 
+/**
+ * Initialize a DAP or do reconnect if DAP is not accessible.
+ *
+ * @param dap The DAP being initialized.
+ */
+int dap_dp_init_or_reconnect(struct adiv5_dap *dap)
+{
+       LOG_DEBUG("%s", adiv5_dap_name(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;
+
+       dap->do_reconnect = false;
+
+       dap_dp_read_atomic(dap, DP_CTRL_STAT, NULL);
+       if (dap->do_reconnect) {
+               /* dap connect calls dap_dp_init() after transport dependent initialization */
+               return dap->ops->connect(dap);
+       } else {
+               return dap_dp_init(dap);
+       }
+}
+
 /**
  * Initialize a DAP.  This sets up the power domains, prepares the DP
  * for further use, and arranges to use AP #0 for all AP operations
@@ -1479,15 +1495,118 @@ int dap_info_command(struct command_invocation *cmd,
 
 enum adiv5_cfg_param {
        CFG_DAP,
-       CFG_AP_NUM
+       CFG_AP_NUM,
+       CFG_BASEADDR,
+       CFG_CTIBASE, /* DEPRECATED */
 };
 
 static const Jim_Nvp nvp_config_opts[] = {
-       { .name = "-dap",    .value = CFG_DAP },
-       { .name = "-ap-num", .value = CFG_AP_NUM },
+       { .name = "-dap",       .value = CFG_DAP },
+       { .name = "-ap-num",    .value = CFG_AP_NUM },
+       { .name = "-baseaddr",  .value = CFG_BASEADDR },
+       { .name = "-ctibase",   .value = CFG_CTIBASE }, /* DEPRECATED */
        { .name = NULL, .value = -1 }
 };
 
+static int adiv5_jim_spot_configure(Jim_GetOptInfo *goi,
+               struct adiv5_dap **dap_p, int *ap_num_p, uint32_t *base_p)
+{
+       if (!goi->argc)
+               return JIM_OK;
+
+       Jim_SetEmptyResult(goi->interp);
+
+       Jim_Nvp *n;
+       int e = Jim_Nvp_name2value_obj(goi->interp, nvp_config_opts,
+                               goi->argv[0], &n);
+       if (e != JIM_OK)
+               return JIM_CONTINUE;
+
+       /* base_p can be NULL, then '-baseaddr' option is treated as unknown */
+       if (!base_p && (n->value == CFG_BASEADDR || n->value == CFG_CTIBASE))
+               return JIM_CONTINUE;
+
+       e = Jim_GetOpt_Obj(goi, NULL);
+       if (e != JIM_OK)
+               return e;
+
+       switch (n->value) {
+       case CFG_DAP:
+               if (goi->isconfigure) {
+                       Jim_Obj *o_t;
+                       struct adiv5_dap *dap;
+                       e = Jim_GetOpt_Obj(goi, &o_t);
+                       if (e != JIM_OK)
+                               return e;
+                       dap = dap_instance_by_jim_obj(goi->interp, o_t);
+                       if (!dap) {
+                               Jim_SetResultString(goi->interp, "DAP name invalid!", -1);
+                               return JIM_ERR;
+                       }
+                       if (*dap_p && *dap_p != dap) {
+                               Jim_SetResultString(goi->interp,
+                                       "DAP assignment cannot be changed!", -1);
+                               return JIM_ERR;
+                       }
+                       *dap_p = dap;
+               } else {
+                       if (goi->argc)
+                               goto err_no_param;
+                       if (!*dap_p) {
+                               Jim_SetResultString(goi->interp, "DAP not configured", -1);
+                               return JIM_ERR;
+                       }
+                       Jim_SetResultString(goi->interp, adiv5_dap_name(*dap_p), -1);
+               }
+               break;
+
+       case CFG_AP_NUM:
+               if (goi->isconfigure) {
+                       jim_wide ap_num;
+                       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;
+                       }
+                       *ap_num_p = ap_num;
+               } else {
+                       if (goi->argc)
+                               goto err_no_param;
+                       if (*ap_num_p == DP_APSEL_INVALID) {
+                               Jim_SetResultString(goi->interp, "AP number not configured", -1);
+                               return JIM_ERR;
+                       }
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, *ap_num_p));
+               }
+               break;
+
+       case CFG_CTIBASE:
+               LOG_WARNING("DEPRECATED! use \'-baseaddr' not \'-ctibase\'");
+               /* fall through */
+       case CFG_BASEADDR:
+               if (goi->isconfigure) {
+                       jim_wide base;
+                       e = Jim_GetOpt_Wide(goi, &base);
+                       if (e != JIM_OK)
+                               return e;
+                       *base_p = (uint32_t)base;
+               } else {
+                       if (goi->argc)
+                               goto err_no_param;
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, *base_p));
+               }
+               break;
+       };
+
+       return JIM_OK;
+
+err_no_param:
+       Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
+       return JIM_ERR;
+}
+
 int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi)
 {
        struct adiv5_private_config *pc;
@@ -1502,90 +1621,19 @@ int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi)
 
        target->has_dap = true;
 
-       if (goi->argc > 0) {
-               Jim_Nvp *n;
-
-               Jim_SetEmptyResult(goi->interp);
-
-               /* check first if topmost item is for us */
-               e = Jim_Nvp_name2value_obj(goi->interp, nvp_config_opts,
-                                                                  goi->argv[0], &n);
-               if (e != JIM_OK)
-                       return JIM_CONTINUE;
-
-               e = Jim_GetOpt_Obj(goi, NULL);
-               if (e != JIM_OK)
-                       return e;
-
-               switch (n->value) {
-               case CFG_DAP:
-                       if (goi->isconfigure) {
-                               Jim_Obj *o_t;
-                               struct adiv5_dap *dap;
-                               e = Jim_GetOpt_Obj(goi, &o_t);
-                               if (e != JIM_OK)
-                                       return e;
-                               dap = dap_instance_by_jim_obj(goi->interp, o_t);
-                               if (dap == NULL) {
-                                       Jim_SetResultString(goi->interp, "DAP name invalid!", -1);
-                                       return JIM_ERR;
-                               }
-                               if (pc->dap != NULL && pc->dap != dap) {
-                                       Jim_SetResultString(goi->interp,
-                                               "DAP assignment cannot be changed after target was created!", -1);
-                                       return JIM_ERR;
-                               }
-                               if (target->tap_configured) {
-                                       Jim_SetResultString(goi->interp,
-                                               "-chain-position and -dap configparams are mutually exclusive!", -1);
-                                       return JIM_ERR;
-                               }
-                               pc->dap = dap;
-                               target->tap = dap->tap;
-                               target->dap_configured = true;
-                       } else {
-                               if (goi->argc != 0) {
-                                       Jim_WrongNumArgs(goi->interp,
-                                                                               goi->argc, goi->argv,
-                                       "NO PARAMS");
-                                       return JIM_ERR;
-                               }
-
-                               if (pc->dap == NULL) {
-                                       Jim_SetResultString(goi->interp, "DAP not configured", -1);
-                                       return JIM_ERR;
-                               }
-                               Jim_SetResultString(goi->interp, adiv5_dap_name(pc->dap), -1);
-                       }
-                       break;
+       e = adiv5_jim_spot_configure(goi, &pc->dap, &pc->ap_num, NULL);
+       if (e != JIM_OK)
+               return e;
 
-               case CFG_AP_NUM:
-                       if (goi->isconfigure) {
-                               jim_wide ap_num;
-                               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) {
-                                       Jim_WrongNumArgs(goi->interp,
-                                                                        goi->argc, goi->argv,
-                                         "NO PARAMS");
-                                       return JIM_ERR;
-                               }
-
-                               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, pc->ap_num));
-                       }
-                       break;
+       if (pc->dap && !target->dap_configured) {
+               if (target->tap_configured) {
+                       pc->dap = NULL;
+                       Jim_SetResultString(goi->interp,
+                               "-chain-position and -dap configparams are mutually exclusive!", -1);
+                       return JIM_ERR;
                }
+               target->tap = pc->dap->tap;
+               target->dap_configured = true;
        }
 
        return JIM_OK;
@@ -1602,6 +1650,19 @@ int adiv5_verify_config(struct adiv5_private_config *pc)
        return ERROR_OK;
 }
 
+int adiv5_jim_mem_ap_spot_configure(struct adiv5_mem_ap_spot *cfg,
+               Jim_GetOptInfo *goi)
+{
+       return adiv5_jim_spot_configure(goi, &cfg->dap, &cfg->ap_num, &cfg->base);
+}
+
+int adiv5_mem_ap_spot_init(struct adiv5_mem_ap_spot *p)
+{
+       p->dap = NULL;
+       p->ap_num = DP_APSEL_INVALID;
+       p->base = 0;
+       return ERROR_OK;
+}
 
 COMMAND_HANDLER(handle_dap_info_command)
 {
@@ -1682,7 +1743,7 @@ COMMAND_HANDLER(dap_memaccess_command)
        }
        dap->ap[dap->apsel].memaccess_tck = memaccess_tck;
 
-       command_print(CMD, "memory bus access delay set to %" PRIi32 " tck",
+       command_print(CMD, "memory bus access delay set to %" PRIu32 " tck",
                        dap->ap[dap->apsel].memaccess_tck);
 
        return ERROR_OK;
@@ -1695,7 +1756,7 @@ COMMAND_HANDLER(dap_apsel_command)
 
        switch (CMD_ARGC) {
        case 0:
-               command_print(CMD, "%" PRIi32, dap->apsel);
+               command_print(CMD, "%" PRIu32, dap->apsel);
                return ERROR_OK;
        case 1:
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
@@ -1721,7 +1782,7 @@ COMMAND_HANDLER(dap_apcsw_command)
 
        switch (CMD_ARGC) {
        case 0:
-               command_print(CMD, "ap %" PRIi32 " selected, csw 0x%8.8" PRIx32,
+               command_print(CMD, "ap %" PRIu32 " selected, csw 0x%8.8" PRIx32,
                        dap->apsel, apcsw);
                return ERROR_OK;
        case 1:

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)