struct target *all_targets;
static struct target_event_callback *target_event_callbacks;
static struct target_timer_callback *target_timer_callbacks;
+LIST_HEAD(target_reset_callback_list);
static const int polling_interval = 100;
static const Jim_Nvp nvp_assert[] = {
return cp;
}
+const char *target_event_name(enum target_event event)
+{
+ const char *cp;
+ cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name;
+ if (!cp) {
+ LOG_ERROR("Invalid target event: %d", (int)(event));
+ cp = "(*BUG*unknown*BUG*)";
+ }
+ return cp;
+}
+
+const char *target_reset_mode_name(enum target_reset_mode reset_mode)
+{
+ const char *cp;
+ cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name;
+ if (!cp) {
+ LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode));
+ cp = "(*BUG*unknown*BUG*)";
+ }
+ return cp;
+}
+
/* determine the number of the new target */
static int new_target_number(void)
{
return ERROR_FAIL;
}
+ struct target *target;
+ for (target = all_targets; target; target = target->next)
+ target_call_reset_callbacks(target, reset_mode);
+
/* disable polling during reset to make reset event scripts
* more predictable, i.e. dr/irscan & pathmove in events will
* not have JTAG operations injected into the middle of a sequence.
/* We want any events to be processed before the prompt */
retval = target_call_timer_callbacks_now();
- struct target *target;
for (target = all_targets; target; target = target->next) {
target->type->check_reset(target);
target->running_alg = false;
}
LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32,
- (buffer - buffer_orig), count, wp, rp);
+ (size_t) (buffer - buffer_orig), count, wp, rp);
if (rp == 0) {
LOG_ERROR("flash write algorithm aborted by target");
return ERROR_OK;
}
+int target_register_reset_callback(int (*callback)(struct target *target,
+ enum target_reset_mode reset_mode, void *priv), void *priv)
+{
+ struct target_reset_callback *entry;
+
+ if (callback == NULL)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ entry = malloc(sizeof(struct target_reset_callback));
+ if (entry == NULL) {
+ LOG_ERROR("error allocating buffer for reset callback entry");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ entry->callback = callback;
+ entry->priv = priv;
+ list_add(&entry->list, &target_reset_callback_list);
+
+
+ return ERROR_OK;
+}
+
int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
{
struct target_timer_callback **callbacks_p = &target_timer_callbacks;
return ERROR_OK;
}
+int target_unregister_reset_callback(int (*callback)(struct target *target,
+ enum target_reset_mode reset_mode, void *priv), void *priv)
+{
+ struct target_reset_callback *entry;
+
+ if (callback == NULL)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ list_for_each_entry(entry, &target_reset_callback_list, list) {
+ if (entry->callback == callback && entry->priv == priv) {
+ list_del(&entry->list);
+ free(entry);
+ break;
+ }
+ }
+
+ return ERROR_OK;
+}
+
int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
{
struct target_timer_callback **p = &target_timer_callbacks;
return ERROR_OK;
}
+int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode)
+{
+ struct target_reset_callback *callback;
+
+ LOG_DEBUG("target reset %i (%s)", reset_mode,
+ Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name);
+
+ list_for_each_entry(callback, &target_reset_callback_list, list)
+ callback->callback(target, reset_mode, callback->priv);
+
+ return ERROR_OK;
+}
+
static int target_timer_callback_periodic_restart(
struct target_timer_callback *cb, struct timeval *now)
{
for (;;) {
target_poll(target);
if (target->state == TARGET_HALTED) {
- uint32_t t = *((uint32_t *)reg->value);
+ uint32_t t = buf_get_u32(reg->value, 0, 32);
samples[sample_count++] = t;
/* current pc, addr = 0, do not handle breakpoints, not debugging */
retval = target_resume(target, 1, 0, 0, 0);
uint32_t addr, uint32_t asid, uint32_t length, int hw)
{
struct target *target = get_current_target(cmd_ctx);
+ int retval;
if (asid == 0) {
- int retval = breakpoint_add(target, addr, length, hw);
+ retval = breakpoint_add(target, addr, length, hw);
if (ERROR_OK == retval)
command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
else {
return retval;
}
} else if (addr == 0) {
- int retval = context_breakpoint_add(target, asid, length, hw);
+ if (target->type->add_context_breakpoint == NULL) {
+ LOG_WARNING("Context breakpoint not available");
+ return ERROR_OK;
+ }
+ retval = context_breakpoint_add(target, asid, length, hw);
if (ERROR_OK == retval)
command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid);
else {
return retval;
}
} else {
- int retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
+ if (target->type->add_hybrid_breakpoint == NULL) {
+ LOG_WARNING("Hybrid breakpoint not available");
+ return ERROR_OK;
+ }
+ retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
if (ERROR_OK == retval)
command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid);
else {
LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno));
}
-static void writeLong(FILE *f, int l)
+static void writeLong(FILE *f, int l, struct target *target)
{
- int i;
- for (i = 0; i < 4; i++) {
- char c = (l >> (i*8))&0xff;
- writeData(f, &c, 1);
- }
+ uint8_t val[4];
+ target_buffer_set_u32(target, val, l);
+ writeData(f, val, 4);
}
static void writeString(FILE *f, char *s)
typedef unsigned char UNIT[2]; /* unit of profiling */
/* Dump a gmon.out histogram file. */
-static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename,
- bool with_range, uint32_t start_address, uint32_t end_address)
+static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range,
+ uint32_t start_address, uint32_t end_address, struct target *target)
{
uint32_t i;
FILE *f = fopen(filename, "w");
if (f == NULL)
return;
writeString(f, "gmon");
- writeLong(f, 0x00000001); /* Version */
- writeLong(f, 0); /* padding */
- writeLong(f, 0); /* padding */
- writeLong(f, 0); /* padding */
+ writeLong(f, 0x00000001, target); /* Version */
+ writeLong(f, 0, target); /* padding */
+ writeLong(f, 0, target); /* padding */
+ writeLong(f, 0, target); /* padding */
uint8_t zero = 0; /* GMON_TAG_TIME_HIST */
writeData(f, &zero, 1);
}
/* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
- writeLong(f, min); /* low_pc */
- writeLong(f, max); /* high_pc */
- writeLong(f, numBuckets); /* # of buckets */
- writeLong(f, 100); /* KLUDGE! We lie, ca. 100Hz best case. */
+ writeLong(f, min, target); /* low_pc */
+ writeLong(f, max, target); /* high_pc */
+ writeLong(f, numBuckets, target); /* # of buckets */
+ writeLong(f, 100, target); /* KLUDGE! We lie, ca. 100Hz best case. */
writeString(f, "seconds");
for (i = 0; i < (15-strlen("seconds")); i++)
writeData(f, &zero, 1);
}
write_gmon(samples, num_of_samples, CMD_ARGV[1],
- with_range, start_address, end_address);
+ with_range, start_address, end_address, target);
command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]);
free(samples);
return target_create(&goi);
}
-static int jim_target_number(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- /* It's OK to remove this mechanism sometime after August 2010 or so */
- LOG_WARNING("don't use numbers as target identifiers; use names");
- if (goi.argc != 1) {
- Jim_SetResultFormatted(goi.interp, "usage: target number <number>");
- return JIM_ERR;
- }
- jim_wide w;
- int e = Jim_GetOpt_Wide(&goi, &w);
- if (e != JIM_OK)
- return JIM_ERR;
-
- struct target *target;
- for (target = all_targets; NULL != target; target = target->next) {
- if (target->target_number != w)
- continue;
-
- Jim_SetResultString(goi.interp, target_name(target), -1);
- return JIM_OK;
- }
- {
- Jim_Obj *wObj = Jim_NewIntObj(goi.interp, w);
- Jim_SetResultFormatted(goi.interp,
- "Target: number %#s does not exist", wObj);
- Jim_FreeNewObj(interp, wObj);
- }
- return JIM_ERR;
-}
-
-static int jim_target_count(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "<no parameters>");
- return JIM_ERR;
- }
- unsigned count = 0;
- struct target *target = all_targets;
- while (NULL != target) {
- target = target->next;
- count++;
- }
- Jim_SetResult(interp, Jim_NewIntObj(interp, count));
- return JIM_OK;
-}
-
static const struct command_registration target_subcommand_handlers[] = {
{
.name = "init",
.jim_handler = jim_target_names,
.help = "Returns the names of all targets as a list of strings",
},
- {
- .name = "number",
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_number,
- .usage = "number",
- .help = "Returns the name of the numbered target "
- "(DEPRECATED)",
- },
- {
- .name = "count",
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_count,
- .help = "Returns the number of targets as an integer "
- "(DEPRECATED)",
- },
{
.name = "smp",
.mode = COMMAND_ANY,