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,
&quark_d20xx_target,
&stm8_target,
&riscv_target,
+ &mem_ap_target,
+ &esirisc_target,
#if BUILD_TARGET64
&aarch64_target,
#endif
- &mem_ap_target,
NULL,
};
{ .name = "single-step" , .value = DBG_REASON_SINGLESTEP },
{ .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED },
{ .name = "program-exit" , .value = DBG_REASON_EXIT },
+ { .name = "exception-catch" , .value = DBG_REASON_EXC_CATCH },
{ .name = "undefined" , .value = DBG_REASON_UNDEFINED },
{ .name = NULL, .value = -1 },
};
struct target *get_current_target(struct command_context *cmd_ctx)
{
- struct target *target = cmd_ctx->current_target_override
- ? cmd_ctx->current_target_override
- : cmd_ctx->current_target;
+ struct target *target = get_current_target_or_null(cmd_ctx);
if (target == NULL) {
LOG_ERROR("BUG: current_target out of bounds");
return target;
}
+struct target *get_current_target_or_null(struct command_context *cmd_ctx)
+{
+ return cmd_ctx->current_target_override
+ ? cmd_ctx->current_target_override
+ : cmd_ctx->current_target;
+}
+
int target_poll(struct target *target)
{
int retval;
retval = target_write_u32(target, wp_addr, wp);
if (retval != ERROR_OK)
break;
+
+ /* Avoid GDB timeouts */
+ keep_alive();
}
if (retval != ERROR_OK) {
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)
{
return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c);
}
+target_addr_t target_address_max(struct target *target)
+{
+ unsigned bits = target_address_bits(target);
+ if (sizeof(target_addr_t) * 8 == bits)
+ return (target_addr_t) -1;
+ else
+ return (((target_addr_t) 1) << bits) - 1;
+}
+
+unsigned target_address_bits(struct target *target)
+{
+ if (target->type->address_bits)
+ return target->type->address_bits(target);
+ return 32;
+}
+
int target_profiling(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
{
return retval;
retval = target_register_timer_callback(&handle_target,
- polling_interval, 1, cmd_ctx->interp);
+ polling_interval, TARGET_TIMER_TYPE_PERIODIC, cmd_ctx->interp);
if (ERROR_OK != retval)
return retval;
return ERROR_OK;
}
-int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
+int target_register_timer_callback(int (*callback)(void *priv),
+ unsigned int time_ms, enum target_timer_type type, void *priv)
{
struct target_timer_callback **callbacks_p = &target_timer_callbacks;
(*callbacks_p) = malloc(sizeof(struct target_timer_callback));
(*callbacks_p)->callback = callback;
- (*callbacks_p)->periodic = periodic;
+ (*callbacks_p)->type = type;
(*callbacks_p)->time_ms = time_ms;
(*callbacks_p)->removed = false;
{
cb->callback(cb->priv);
- if (cb->periodic)
+ if (cb->type == TARGET_TIMER_TYPE_PERIODIC)
return target_timer_callback_periodic_restart(cb, now);
return target_unregister_timer_callback(cb->callback, cb->priv);
}
bool call_it = (*callback)->callback &&
- ((!checktime && (*callback)->periodic) ||
+ ((!checktime && (*callback)->type == TARGET_TIMER_TYPE_PERIODIC) ||
timeval_compare(&now, &(*callback)->when) >= 0);
if (call_it)
return target_free_working_area_restore(target, area, 1);
}
+/* free resources and restore memory, if restoring memory fails,
+ * free up resources anyway
+ */
+static void target_free_all_working_areas_restore(struct target *target, int restore)
+{
+ struct working_area *c = target->working_areas;
+
+ LOG_DEBUG("freeing all working areas");
+
+ /* Loop through all areas, restoring the allocated ones and marking them as free */
+ while (c) {
+ if (!c->free) {
+ if (restore)
+ target_restore_working_area(target, c);
+ c->free = true;
+ *c->user = NULL; /* Same as above */
+ c->user = NULL;
+ }
+ c = c->next;
+ }
+
+ /* Run a merge pass to combine all areas into one */
+ target_merge_working_areas(target);
+
+ print_wa_layout(target);
+}
+
+void target_free_all_working_areas(struct target *target)
+{
+ target_free_all_working_areas_restore(target, 1);
+
+ /* Now we have none or only one working area marked as free */
+ if (target->working_areas) {
+ /* Free the last one to allow on-the-fly moving and resizing */
+ free(target->working_areas->backup);
+ free(target->working_areas);
+ target->working_areas = NULL;
+ }
+}
+
+/* Find the largest number of bytes that can be allocated */
+uint32_t target_get_working_area_avail(struct target *target)
+{
+ struct working_area *c = target->working_areas;
+ uint32_t max_size = 0;
+
+ if (c == NULL)
+ return target->working_area_size;
+
+ while (c) {
+ if (c->free && max_size < c->size)
+ max_size = c->size;
+
+ c = c->next;
+ }
+
+ return max_size;
+}
+
static void target_destroy(struct target *target)
{
if (target->type->deinit_target)
}
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) {
all_targets = NULL;
}
-/* free resources and restore memory, if restoring memory fails,
- * free up resources anyway
- */
-static void target_free_all_working_areas_restore(struct target *target, int restore)
-{
- struct working_area *c = target->working_areas;
-
- LOG_DEBUG("freeing all working areas");
-
- /* Loop through all areas, restoring the allocated ones and marking them as free */
- while (c) {
- if (!c->free) {
- if (restore)
- target_restore_working_area(target, c);
- c->free = true;
- *c->user = NULL; /* Same as above */
- c->user = NULL;
- }
- c = c->next;
- }
-
- /* Run a merge pass to combine all areas into one */
- target_merge_working_areas(target);
-
- print_wa_layout(target);
-}
-
-void target_free_all_working_areas(struct target *target)
-{
- target_free_all_working_areas_restore(target, 1);
-}
-
-/* Find the largest number of bytes that can be allocated */
-uint32_t target_get_working_area_avail(struct target *target)
-{
- struct working_area *c = target->working_areas;
- uint32_t max_size = 0;
-
- if (c == NULL)
- return target->working_area_size;
-
- while (c) {
- if (c->free && max_size < c->size)
- max_size = c->size;
-
- c = c->next;
- }
-
- return max_size;
-}
-
int target_arch_state(struct target *target)
{
int retval;
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,
/* 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')))) {
}
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)
if (asid == 0) {
retval = breakpoint_add(target, addr, length, hw);
+ /* error is always logged in breakpoint_add(), do not print it again */
if (ERROR_OK == retval)
command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr);
- else {
- LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used");
- return retval;
- }
+
} else if (addr == 0) {
if (target->type->add_context_breakpoint == NULL) {
- LOG_WARNING("Context breakpoint not available");
- return ERROR_OK;
+ LOG_ERROR("Context breakpoint not available");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
retval = context_breakpoint_add(target, asid, length, hw);
+ /* error is always logged in context_breakpoint_add(), do not print it again */
if (ERROR_OK == retval)
command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid);
- else {
- LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used");
- return retval;
- }
+
} else {
if (target->type->add_hybrid_breakpoint == NULL) {
- LOG_WARNING("Hybrid breakpoint not available");
- return ERROR_OK;
+ LOG_ERROR("Hybrid breakpoint not available");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
+ /* error is always logged in hybrid_breakpoint_add(), do not print it again */
if (ERROR_OK == retval)
command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid);
- else {
- LOG_ERROR("Failure setting breakpoint, the same address is already used");
- return retval;
- }
}
- return ERROR_OK;
+ return retval;
}
COMMAND_HANDLER(handle_bp_command)
if (goi->argc != 0)
goto no_params;
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
+ Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->coreid));
/* loop for more */
break;
/* List for human, Events defined for this target.
* scripts/programs should use 'name cget -event NAME'
*/
-static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+COMMAND_HANDLER(handle_target_event_list)
{
- struct command_context *cmd_ctx = current_command_context(interp);
- assert(cmd_ctx != NULL);
-
- struct target *target = Jim_CmdPrivData(interp);
+ struct target *target = get_current_target(CMD_CTX);
struct target_event_action *teap = target->event_action;
- command_print(cmd_ctx, "Event actions for target (%d) %s\n",
+
+ command_print(CMD_CTX, "Event actions for target (%d) %s\n",
target->target_number,
target_name(target));
- command_print(cmd_ctx, "%-25s | Body", "Event");
- command_print(cmd_ctx, "------------------------- | "
+ command_print(CMD_CTX, "%-25s | Body", "Event");
+ command_print(CMD_CTX, "------------------------- | "
"----------------------------------------");
while (teap) {
Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event);
- command_print(cmd_ctx, "%-25s | %s",
+ command_print(CMD_CTX, "%-25s | %s",
opt->name, Jim_GetString(teap->body, NULL));
teap = teap->next;
}
- command_print(cmd_ctx, "***END***");
- return JIM_OK;
+ command_print(CMD_CTX, "***END***");
+ return ERROR_OK;
}
static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
},
{
.name = "eventlist",
+ .handler = handle_target_event_list,
.mode = COMMAND_EXEC,
- .jim_handler = jim_target_event_list,
.help = "displays a table of events defined for this target",
+ .usage = "",
},
{
.name = "curstate",
.mode = COMMAND_CONFIG,
.handler = handle_target_init_command,
.help = "initialize targets",
+ .usage = "",
},
{
.name = "create",
- /* REVISIT this should be COMMAND_CONFIG ... */
- .mode = COMMAND_ANY,
+ .mode = COMMAND_CONFIG,
.jim_handler = jim_target_create,
.usage = "name type '-chain-position' name [options ...]",
.help = "Creates and selects a new target",
.name = "target",
.mode = COMMAND_CONFIG,
.help = "configure target",
-
.chain = target_subcommand_handlers,
+ .usage = "",
},
COMMAND_REGISTRATION_DONE
};