X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=ef4568564694e7bffa701deeac68ad60fd1643a0;hp=c2408b27c584436320f2434f1ead3ad220ea5a6e;hb=b71ae9b1a704a9631698d7d4a92b1dfdfc9a0f69;hpb=5bc0dc0c9d3609d16dc27f6bd4b6fea9a4e29760;ds=sidebyside diff --git a/src/target/target.c b/src/target/target.c index c2408b27c5..ef45685646 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -139,6 +139,7 @@ static struct target_type *target_types[] = { 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[] = { @@ -280,6 +281,28 @@ const char *target_state_name(struct target *t) 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) { @@ -601,6 +624,10 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res 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. @@ -623,7 +650,6 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res /* 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; @@ -1312,6 +1338,28 @@ int target_register_event_callback(int (*callback)(struct target *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; @@ -1330,6 +1378,7 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int (*callbacks_p)->callback = callback; (*callbacks_p)->periodic = periodic; (*callbacks_p)->time_ms = time_ms; + (*callbacks_p)->removed = false; gettimeofday(&now, NULL); (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000; @@ -1369,26 +1418,39 @@ int target_unregister_event_callback(int (*callback)(struct target *target, return ERROR_OK; } -int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) +int target_unregister_reset_callback(int (*callback)(struct target *target, + enum target_reset_mode reset_mode, void *priv), void *priv) { - struct target_timer_callback **p = &target_timer_callbacks; - struct target_timer_callback *c = target_timer_callbacks; + struct target_reset_callback *entry; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; - while (c) { - struct target_timer_callback *next = c->next; + 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) +{ + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (struct target_timer_callback *c = target_timer_callbacks; + c; c = c->next) { if ((c->callback == callback) && (c->priv == priv)) { - *p = next; - free(c); + c->removed = true; return ERROR_OK; - } else - p = &(c->next); - c = next; + } } - return ERROR_OK; + return ERROR_FAIL; } int target_call_event_callbacks(struct target *target, enum target_event event) @@ -1415,6 +1477,19 @@ int target_call_event_callbacks(struct target *target, enum target_event event) 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) { @@ -1442,31 +1517,44 @@ static int target_call_timer_callback(struct target_timer_callback *cb, static int target_call_timer_callbacks_check_time(int checktime) { + static bool callback_processing; + + /* Do not allow nesting */ + if (callback_processing) + return ERROR_OK; + + callback_processing = true; + keep_alive(); struct timeval now; gettimeofday(&now, NULL); - struct target_timer_callback *callback = target_timer_callbacks; - while (callback) { - /* cleaning up may unregister and free this callback */ - struct target_timer_callback *next_callback = callback->next; + /* Store an address of the place containing a pointer to the + * next item; initially, that's a standalone "root of the + * list" variable. */ + struct target_timer_callback **callback = &target_timer_callbacks; + while (*callback) { + if ((*callback)->removed) { + struct target_timer_callback *p = *callback; + *callback = (*callback)->next; + free(p); + continue; + } - bool call_it = callback->callback && - ((!checktime && callback->periodic) || - now.tv_sec > callback->when.tv_sec || - (now.tv_sec == callback->when.tv_sec && - now.tv_usec >= callback->when.tv_usec)); + bool call_it = (*callback)->callback && + ((!checktime && (*callback)->periodic) || + now.tv_sec > (*callback)->when.tv_sec || + (now.tv_sec == (*callback)->when.tv_sec && + now.tv_usec >= (*callback)->when.tv_usec)); - if (call_it) { - int retval = target_call_timer_callback(callback, &now); - if (retval != ERROR_OK) - return retval; - } + if (call_it) + target_call_timer_callback(*callback, &now); - callback = next_callback; + callback = &(*callback)->next; } + callback_processing = false; return ERROR_OK; } @@ -1819,7 +1907,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples, 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); @@ -5333,55 +5421,6 @@ static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 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 "); - 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, ""); - 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", @@ -5416,21 +5455,6 @@ static const struct command_registration target_subcommand_handlers[] = { .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,