target/target.c: adding keep_alive() to while loop.
[openocd.git] / src / target / target.c
index 055658ea6199819caef683e6943ff552b0926aaa..871588393b52bdf76372954722d18a4cb10206f5 100644 (file)
@@ -54,6 +54,7 @@
 #include "image.h"
 #include "rtos/rtos.h"
 #include "transport/transport.h"
+#include "arm_cti.h"
 
 /* default halt wait timeout (ms) */
 #define DEFAULT_HALT_TIMEOUT 5000
@@ -106,6 +107,9 @@ extern struct target_type or1k_target;
 extern struct target_type quark_x10xx_target;
 extern struct target_type quark_d20xx_target;
 extern struct target_type stm8_target;
+extern struct target_type riscv_target;
+extern struct target_type mem_ap_target;
+extern struct target_type esirisc_target;
 
 static struct target_type *target_types[] = {
        &arm7tdmi_target,
@@ -138,6 +142,9 @@ static struct target_type *target_types[] = {
        &quark_x10xx_target,
        &quark_d20xx_target,
        &stm8_target,
+       &riscv_target,
+       &mem_ap_target,
+       &esirisc_target,
 #if BUILD_TARGET64
        &aarch64_target,
 #endif
@@ -510,7 +517,9 @@ struct target *get_target_by_num(int num)
 
 struct target *get_current_target(struct command_context *cmd_ctx)
 {
-       struct target *target = get_target_by_num(cmd_ctx->current_target);
+       struct target *target = cmd_ctx->current_target_override
+               ? cmd_ctx->current_target_override
+               : cmd_ctx->current_target;
 
        if (target == NULL) {
                LOG_ERROR("BUG: current_target out of bounds");
@@ -808,8 +817,7 @@ done:
 }
 
 /**
- * Downloads a target-specific native code algorithm to the target,
- * executes and leaves it running.
+ * Executes a target-specific native code algorithm and leaves it running.
  *
  * @param target used to run the algorithm
  * @param arch_info target-specific description of the algorithm.
@@ -1039,6 +1047,9 @@ int target_run_flash_async_algorithm(struct target *target,
                retval = target_write_u32(target, wp_addr, wp);
                if (retval != ERROR_OK)
                        break;
+
+               /* Avoid GDB timeouts */
+               keep_alive();
        }
 
        if (retval != ERROR_OK) {
@@ -1193,12 +1204,29 @@ int target_hit_watchpoint(struct target *target,
        return target->type->hit_watchpoint(target, hit_watchpoint);
 }
 
+const char *target_get_gdb_arch(struct target *target)
+{
+       if (target->type->get_gdb_arch == NULL)
+               return NULL;
+       return target->type->get_gdb_arch(target);
+}
+
 int target_get_gdb_reg_list(struct target *target,
                struct reg **reg_list[], int *reg_list_size,
                enum target_register_class reg_class)
 {
        return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class);
 }
+
+bool target_supports_gdb_connection(struct target *target)
+{
+       /*
+        * based on current code, we can simply exclude all the targets that
+        * don't provide get_gdb_reg_list; this could change with new targets.
+        */
+       return !!target->type->get_gdb_reg_list;
+}
+
 int target_step(struct target *target,
                int current, target_addr_t address, int handle_breakpoints)
 {
@@ -1891,8 +1919,42 @@ static void target_destroy(struct target *target)
        if (target->type->deinit_target)
                target->type->deinit_target(target);
 
+       if (target->semihosting)
+               free(target->semihosting);
+
+       jtag_unregister_event_callback(jtag_enable_callback, target);
+
+       struct target_event_action *teap = target->event_action;
+       while (teap) {
+               struct target_event_action *next = teap->next;
+               Jim_DecrRefCount(teap->interp, teap->body);
+               free(teap);
+               teap = next;
+       }
+
+       target_free_all_working_areas(target);
+       /* Now we have none or only one working area marked as free */
+       if (target->working_areas) {
+               free(target->working_areas->backup);
+               free(target->working_areas);
+       }
+
+       /* release the targets SMP list */
+       if (target->smp) {
+               struct target_list *head = target->head;
+               while (head != NULL) {
+                       struct target_list *pos = head->next;
+                       head->target->smp = 0;
+                       free(head);
+                       head = pos;
+               }
+               target->smp = 0;
+       }
+
+       free(target->gdb_port_override);
        free(target->type);
        free(target->trace_info);
+       free(target->fileio_info);
        free(target->cmd_name);
        free(target);
 }
@@ -2219,21 +2281,19 @@ int target_checksum_memory(struct target *target, target_addr_t address, uint32_
        return retval;
 }
 
-int target_blank_check_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* blank,
+int target_blank_check_memory(struct target *target,
+       struct target_memory_check_block *blocks, int num_blocks,
        uint8_t erased_value)
 {
-       int retval;
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       if (target->type->blank_check_memory == 0)
+       if (target->type->blank_check_memory == NULL)
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
-       retval = target->type->blank_check_memory(target, address, size, blank, erased_value);
-
-       return retval;
+       return target->type->blank_check_memory(target, blocks, num_blocks, erased_value);
 }
 
 int target_read_u64(struct target *target, target_addr_t address, uint64_t *value)
@@ -2506,7 +2566,10 @@ static int find_target(struct command_context *cmd_ctx, const char *name)
                return ERROR_FAIL;
        }
 
-       cmd_ctx->current_target = target->target_number;
+       cmd_ctx->current_target = target;
+       if (cmd_ctx->current_target_override)
+               cmd_ctx->current_target_override = target;
+
        return ERROR_OK;
 }
 
@@ -2534,7 +2597,7 @@ COMMAND_HANDLER(handle_targets_command)
                else
                        state = "tap-disabled";
 
-               if (CMD_CTX->current_target == target->target_number)
+               if (CMD_CTX->current_target == target)
                        marker = '*';
 
                /* keep columns lined up to match the headers above */
@@ -2753,6 +2816,8 @@ COMMAND_HANDLER(handle_reg_command)
                        for (i = 0, reg = cache->reg_list;
                                        i < cache->num_regs;
                                        i++, reg++, count++) {
+                               if (reg->exist == false)
+                                       continue;
                                /* only print cached values if they are valid */
                                if (reg->valid) {
                                        value = buf_to_str(reg->value,
@@ -2806,14 +2871,15 @@ COMMAND_HANDLER(handle_reg_command)
                /* access a single register by its name */
                reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1);
 
-               if (!reg) {
-                       command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
-                       return ERROR_OK;
-               }
+               if (!reg)
+                       goto not_found;
        }
 
        assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */
 
+       if (!reg->exist)
+               goto not_found;
+
        /* display a register */
        if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
                        && (CMD_ARGV[1][0] <= '9')))) {
@@ -2847,6 +2913,10 @@ COMMAND_HANDLER(handle_reg_command)
        }
 
        return ERROR_COMMAND_SYNTAX_ERROR;
+
+not_found:
+       command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(handle_poll_command)
@@ -2938,6 +3008,9 @@ COMMAND_HANDLER(handle_halt_command)
        LOG_DEBUG("-");
 
        struct target *target = get_current_target(CMD_CTX);
+
+       target->verbose_halt_msg = true;
+
        int retval = target_halt(target);
        if (ERROR_OK != retval)
                return retval;
@@ -4092,8 +4165,9 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
         * argv[3] = memory address
         * argv[4] = count of times to read
         */
+
        if (argc < 4 || argc > 5) {
-               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems [phys]");
+               Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]");
                return JIM_ERR;
        }
        varname = Jim_GetString(argv[0], &len);
@@ -4442,17 +4516,28 @@ void target_handle_event(struct target *target, enum target_event e)
 
        for (teap = target->event_action; teap != NULL; teap = teap->next) {
                if (teap->event == e) {
-                       LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s",
+                       LOG_DEBUG("target(%d): %s (%s) event: %d (%s) action: %s",
                                           target->target_number,
                                           target_name(target),
                                           target_type_name(target),
                                           e,
                                           Jim_Nvp_value2name_simple(nvp_target_event, e)->name,
                                           Jim_GetString(teap->body, NULL));
+
+                       /* Override current target by the target an event
+                        * is issued from (lot of scripts need it).
+                        * Return back to previous override as soon
+                        * as the handler processing is done */
+                       struct command_context *cmd_ctx = current_command_context(teap->interp);
+                       struct target *saved_target_override = cmd_ctx->current_target_override;
+                       cmd_ctx->current_target_override = target;
+
                        if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) {
                                Jim_MakeErrorMessage(teap->interp);
                                command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL));
                        }
+
+                       cmd_ctx->current_target_override = saved_target_override;
                }
        }
 }
@@ -4482,9 +4567,9 @@ enum target_cfg_param {
        TCFG_COREID,
        TCFG_CHAIN_POSITION,
        TCFG_DBGBASE,
-       TCFG_CTIBASE,
        TCFG_RTOS,
        TCFG_DEFER_EXAMINE,
+       TCFG_GDB_PORT,
 };
 
 static Jim_Nvp nvp_config_opts[] = {
@@ -4498,9 +4583,9 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-coreid",           .value = TCFG_COREID },
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
        { .name = "-dbgbase",          .value = TCFG_DBGBASE },
-       { .name = "-ctibase",          .value = TCFG_CTIBASE },
        { .name = "-rtos",             .value = TCFG_RTOS },
        { .name = "-defer-examine",    .value = TCFG_DEFER_EXAMINE },
+       { .name = "-gdb-port",         .value = TCFG_GDB_PORT },
        { .name = NULL, .value = -1 }
 };
 
@@ -4735,6 +4820,13 @@ no_params:
                        if (goi->isconfigure) {
                                Jim_Obj *o_t;
                                struct jtag_tap *tap;
+
+                               if (target->has_dap) {
+                                       Jim_SetResultString(goi->interp,
+                                               "target requires -dap parameter instead of -chain-position!", -1);
+                                       return JIM_ERR;
+                               }
+
                                target_free_all_working_areas(target);
                                e = Jim_GetOpt_Obj(goi, &o_t);
                                if (e != JIM_OK)
@@ -4742,8 +4834,8 @@ no_params:
                                tap = jtag_tap_by_jim_obj(goi->interp, o_t);
                                if (tap == NULL)
                                        return JIM_ERR;
-                               /* make this exactly 1 or 0 */
                                target->tap = tap;
+                               target->tap_configured = true;
                        } else {
                                if (goi->argc != 0)
                                        goto no_params;
@@ -4765,20 +4857,6 @@ no_params:
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
                        /* loop for more */
                        break;
-               case TCFG_CTIBASE:
-                       if (goi->isconfigure) {
-                               e = Jim_GetOpt_Wide(goi, &w);
-                               if (e != JIM_OK)
-                                       return e;
-                               target->ctibase = (uint32_t)w;
-                               target->ctibase_set = true;
-                       } else {
-                               if (goi->argc != 0)
-                                       goto no_params;
-                       }
-                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->ctibase));
-                       /* loop for more */
-                       break;
                case TCFG_RTOS:
                        /* RTOS */
                        {
@@ -4795,6 +4873,20 @@ no_params:
                        /* loop for more */
                        break;
 
+               case TCFG_GDB_PORT:
+                       if (goi->isconfigure) {
+                               const char *s;
+                               e = Jim_GetOpt_String(goi, &s, NULL);
+                               if (e != JIM_OK)
+                                       return e;
+                               target->gdb_port_override = strdup(s);
+                       } else {
+                               if (goi->argc != 0)
+                                       goto no_params;
+                       }
+                       Jim_SetResultString(goi->interp, target->gdb_port_override ? : "undefined", -1);
+                       /* loop for more */
+                       break;
                }
        } /* while (goi->argc) */
 
@@ -5395,21 +5487,19 @@ static const struct command_registration target_instance_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .jim_handler = jim_target_examine,
                .help = "used internally for reset processing",
-               .usage = "arp_examine ['allow-defer']",
+               .usage = "['allow-defer']",
        },
        {
                .name = "was_examined",
                .mode = COMMAND_EXEC,
                .jim_handler = jim_target_was_examined,
                .help = "used internally for reset processing",
-               .usage = "was_examined",
        },
        {
                .name = "examine_deferred",
                .mode = COMMAND_EXEC,
                .jim_handler = jim_target_examine_deferred,
                .help = "used internally for reset processing",
-               .usage = "examine_deferred",
        },
        {
                .name = "arp_halt_gdb",
@@ -5530,7 +5620,7 @@ static int target_create(Jim_GetOptInfo *goi)
        target = calloc(1, sizeof(struct target));
        /* set target number */
        target->target_number = new_target_number();
-       cmd_ctx->current_target = target->target_number;
+       cmd_ctx->current_target = target;
 
        /* allocate memory for each unique target type */
        target->type = calloc(1, sizeof(struct target_type));
@@ -5556,7 +5646,7 @@ static int target_create(Jim_GetOptInfo *goi)
        target->next                = NULL;
        target->arch_info           = NULL;
 
-       target->display             = 1;
+       target->verbose_halt_msg        = true;
 
        target->halt_issued                     = false;
 
@@ -5571,16 +5661,31 @@ static int target_create(Jim_GetOptInfo *goi)
        target->rtos = NULL;
        target->rtos_auto_detect = false;
 
+       target->gdb_port_override = NULL;
+
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
 
-       if (target->tap == NULL) {
-               Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
-               e = JIM_ERR;
+       if (e == JIM_OK) {
+               if (target->has_dap) {
+                       if (!target->dap_configured) {
+                               Jim_SetResultString(goi->interp, "-dap ?name? required when creating target", -1);
+                               e = JIM_ERR;
+                       }
+               } else {
+                       if (!target->tap_configured) {
+                               Jim_SetResultString(goi->interp, "-chain-position ?name? required when creating target", -1);
+                               e = JIM_ERR;
+                       }
+               }
+               /* tap must be set after target was configured */
+               if (target->tap == NULL)
+                       e = JIM_ERR;
        }
 
        if (e != JIM_OK) {
+               free(target->gdb_port_override);
                free(target->type);
                free(target);
                return e;
@@ -5594,14 +5699,24 @@ static int target_create(Jim_GetOptInfo *goi)
        cp = Jim_GetString(new_cmd, NULL);
        target->cmd_name = strdup(cp);
 
+       if (target->type->target_create) {
+               e = (*(target->type->target_create))(target, goi->interp);
+               if (e != ERROR_OK) {
+                       LOG_DEBUG("target_create failed");
+                       free(target->gdb_port_override);
+                       free(target->type);
+                       free(target->cmd_name);
+                       free(target);
+                       return JIM_ERR;
+               }
+       }
+
        /* create the target specific commands */
        if (target->type->commands) {
                e = register_commands(cmd_ctx, NULL, target->type->commands);
                if (ERROR_OK != e)
                        LOG_ERROR("unable to register '%s' commands", cp);
        }
-       if (target->type->target_create)
-               (*(target->type->target_create))(target, goi->interp);
 
        /* append to end of list */
        {
@@ -6355,7 +6470,7 @@ static const struct command_registration target_exec_command_handlers[] = {
                .handler = handle_bp_command,
                .mode = COMMAND_EXEC,
                .help = "list or set hardware or software breakpoint",
-               .usage = "<address> [<asid>]<length> ['hw'|'hw_ctx']",
+               .usage = "<address> [<asid>] <length> ['hw'|'hw_ctx']",
        },
        {
                .name = "rbp",

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)