X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=a282aab6ad908919c9307b981022267aa616d176;hp=4a9095a6764d8565bdbbcccf6b3ff83ee1894234;hb=f1f8d9a6c9b1fd35d79627b568faa2409f13311f;hpb=17a9dea53a71e9d7e241262725f3dd707b620d37 diff --git a/src/target/target.c b/src/target/target.c index 4a9095a676..a282aab6ad 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2,7 +2,7 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * - * Copyright (C) 2007-2009 Øyvind Harboe * + * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008, Duane Ellis * @@ -33,21 +33,24 @@ #include "config.h" #endif +#include +#include +#include + #include "target.h" #include "target_type.h" #include "target_request.h" #include "breakpoints.h" -#include "time_support.h" #include "register.h" #include "trace.h" #include "image.h" -#include "jtag.h" - -static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); -static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv); -static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv); +static int target_array2mem(Jim_Interp *interp, struct target *target, + int argc, Jim_Obj *const *argv); +static int target_mem2array(Jim_Interp *interp, struct target *target, + int argc, Jim_Obj *const *argv); +static int target_register_user_commands(struct command_context *cmd_ctx); /* targets */ extern struct target_type arm7tdmi_target; @@ -55,6 +58,7 @@ extern struct target_type arm720t_target; extern struct target_type arm9tdmi_target; extern struct target_type arm920t_target; extern struct target_type arm966e_target; +extern struct target_type arm946e_target; extern struct target_type arm926ejs_target; extern struct target_type fa526_target; extern struct target_type feroceon_target; @@ -65,14 +69,18 @@ extern struct target_type cortexa8_target; extern struct target_type arm11_target; extern struct target_type mips_m4k_target; extern struct target_type avr_target; +extern struct target_type dsp563xx_target; +extern struct target_type testee_target; +extern struct target_type avr32_ap7k_target; -struct target_type *target_types[] = +static struct target_type *target_types[] = { &arm7tdmi_target, &arm9tdmi_target, &arm920t_target, &arm720t_target, &arm966e_target, + &arm946e_target, &arm926ejs_target, &fa526_target, &feroceon_target, @@ -83,14 +91,18 @@ struct target_type *target_types[] = &arm11_target, &mips_m4k_target, &avr_target, + &dsp563xx_target, + &testee_target, + &avr32_ap7k_target, NULL, }; struct target *all_targets = NULL; -struct target_event_callback *target_event_callbacks = NULL; -struct target_timer_callback *target_timer_callbacks = NULL; +static struct target_event_callback *target_event_callbacks = NULL; +static struct target_timer_callback *target_timer_callbacks = NULL; +static const int polling_interval = 100; -const Jim_Nvp nvp_assert[] = { +static const Jim_Nvp nvp_assert[] = { { .name = "assert", NVP_ASSERT }, { .name = "deassert", NVP_DEASSERT }, { .name = "T", NVP_ASSERT }, @@ -100,7 +112,7 @@ const Jim_Nvp nvp_assert[] = { { .name = NULL, .value = -1 } }; -const Jim_Nvp nvp_error_target[] = { +static const Jim_Nvp nvp_error_target[] = { { .value = ERROR_TARGET_INVALID, .name = "err-invalid" }, { .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" }, { .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" }, @@ -115,7 +127,7 @@ const Jim_Nvp nvp_error_target[] = { { .value = -1, .name = NULL } }; -const char *target_strerror_safe(int err) +static const char *target_strerror_safe(int err) { const Jim_Nvp *n; @@ -145,6 +157,7 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_RESET_START, .name = "reset-start" }, { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" }, + { .value = TARGET_EVENT_RESET_ASSERT, .name = "reset-assert" }, { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" }, { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" }, { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" }, @@ -152,8 +165,8 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" }, { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" }, { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" }, - { .value = TARGET_EVENT_RESET_INIT , .name = "reset-init" }, - { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, + { .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" }, + { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" }, { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" }, @@ -177,7 +190,7 @@ static const Jim_Nvp nvp_target_event[] = { { .name = NULL, .value = -1 } }; -const Jim_Nvp nvp_target_state[] = { +static const Jim_Nvp nvp_target_state[] = { { .name = "unknown", .value = TARGET_UNKNOWN }, { .name = "running", .value = TARGET_RUNNING }, { .name = "halted", .value = TARGET_HALTED }, @@ -186,7 +199,7 @@ const Jim_Nvp nvp_target_state[] = { { .name = NULL, .value = -1 }, }; -const Jim_Nvp nvp_target_debug_reason [] = { +static const Jim_Nvp nvp_target_debug_reason [] = { { .name = "debug-request" , .value = DBG_REASON_DBGRQ }, { .name = "breakpoint" , .value = DBG_REASON_BREAKPOINT }, { .name = "watchpoint" , .value = DBG_REASON_WATCHPOINT }, @@ -197,7 +210,7 @@ const Jim_Nvp nvp_target_debug_reason [] = { { .name = NULL, .value = -1 }, }; -const Jim_Nvp nvp_target_endian[] = { +static const Jim_Nvp nvp_target_endian[] = { { .name = "big", .value = TARGET_BIG_ENDIAN }, { .name = "little", .value = TARGET_LITTLE_ENDIAN }, { .name = "be", .value = TARGET_BIG_ENDIAN }, @@ -205,7 +218,7 @@ const Jim_Nvp nvp_target_endian[] = { { .name = NULL, .value = -1 }, }; -const Jim_Nvp nvp_reset_modes[] = { +static const Jim_Nvp nvp_reset_modes[] = { { .name = "unknown", .value = RESET_UNKNOWN }, { .name = "run" , .value = RESET_RUN }, { .name = "halt" , .value = RESET_HALT }, @@ -213,6 +226,19 @@ const Jim_Nvp nvp_reset_modes[] = { { .name = NULL , .value = -1 }, }; +const char *debug_reason_name(struct target *t) +{ + const char *cp; + + cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason, + t->debug_reason)->name; + if (!cp) { + LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason)); + cp = "(*BUG*unknown*BUG*)"; + } + return cp; +} + const char * target_state_name( struct target *t ) { @@ -262,7 +288,7 @@ uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer) } /* read a uint8_t from a buffer in target memory endianness */ -uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) +static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) { return *buffer & 0x0ff; } @@ -286,7 +312,7 @@ void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t valu } /* write a uint8_t to a buffer in target memory endianness */ -void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value) +static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value) { *buffer = value; } @@ -405,6 +431,36 @@ int target_halt(struct target *target) return ERROR_OK; } +/** + * Make the target (re)start executing using its saved execution + * context (possibly with some modifications). + * + * @param target Which target should start executing. + * @param current True to use the target's saved program counter instead + * of the address parameter + * @param address Optionally used as the program counter. + * @param handle_breakpoints True iff breakpoints at the resumption PC + * should be skipped. (For example, maybe execution was stopped by + * such a breakpoint, in which case it would be counterprodutive to + * let it re-trigger. + * @param debug_execution False if all working areas allocated by OpenOCD + * should be released and/or restored to their original contents. + * (This would for example be true to run some downloaded "helper" + * algorithm code, which resides in one such working buffer and uses + * another for data storage.) + * + * @todo Resolve the ambiguity about what the "debug_execution" flag + * signifies. For example, Target implementations don't agree on how + * it relates to invalidation of the register cache, or to whether + * breakpoints and watchpoints should be enabled. (It would seem wrong + * to enable breakpoints when running downloaded "helper" algorithms + * (debug_execution true), since the breakpoints would be set to match + * target firmware being debugged, not the helper algorithm.... and + * enabling them could cause such helpers to malfunction (for example, + * by overwriting data with a breakpoint instruction. On the other + * hand the infrastructure for running such helpers might use this + * procedure but rely on hardware breakpoint to detect termination.) + */ int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int retval; @@ -416,9 +472,9 @@ int target_resume(struct target *target, int current, uint32_t address, int hand return ERROR_FAIL; } - /* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can - * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?) - * the application. + /* note that resume *must* be asynchronous. The CPU can halt before + * we poll. The CPU can even halt at the current PC as a result of + * a software breakpoint being inserted by (a bug?) the application. */ if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK) return retval; @@ -426,7 +482,7 @@ int target_resume(struct target *target, int current, uint32_t address, int hand return retval; } -int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) +static int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) { char buf[100]; int retval; @@ -446,18 +502,24 @@ int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode jtag_poll_set_enabled(false); sprintf(buf, "ocd_process_reset %s", n->name); - retval = Jim_Eval(interp, buf); + retval = Jim_Eval(cmd_ctx->interp, buf); jtag_poll_set_enabled(save_poll); if (retval != JIM_OK) { - Jim_PrintErrorMessage(interp); + Jim_MakeErrorMessage(cmd_ctx->interp); + command_print(NULL,"%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL)); return ERROR_FAIL; } /* 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); + } + return retval; } @@ -480,6 +542,12 @@ static int default_examine(struct target *target) return ERROR_OK; } +/* no check by default */ +static int default_check_reset(struct target *target) +{ + return ERROR_OK; +} + int target_examine_one(struct target *target) { return target->type->examine(target); @@ -520,7 +588,7 @@ int target_examine(void) } return retval; } -const char *target_get_name(struct target *target) +const char *target_type_name(struct target *target) { return target->type->name; } @@ -554,29 +622,61 @@ static int target_soft_reset_halt_imp(struct target *target) } if (!target->type->soft_reset_halt_imp) { LOG_ERROR("Target %s does not support soft_reset_halt", - target->cmd_name); + target_name(target)); return ERROR_FAIL; } return target->type->soft_reset_halt_imp(target); } -static int target_run_algorithm_imp(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) +/** + * Downloads a target-specific native code algorithm to the target, + * and executes it. * Note that some targets may need to set up, enable, + * and tear down a breakpoint (hard or * soft) to detect algorithm + * termination, while others may support lower overhead schemes where + * soft breakpoints embedded in the algorithm automatically terminate the + * algorithm. + * + * @param target used to run the algorithm + * @param arch_info target-specific description of the algorithm. + */ +int target_run_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_param, + uint32_t entry_point, uint32_t exit_point, + int timeout_ms, void *arch_info) { + int retval = ERROR_FAIL; + if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; + goto done; } - return target->type->run_algorithm_imp(target, num_mem_params, mem_params, num_reg_params, reg_param, entry_point, exit_point, timeout_ms, arch_info); + if (!target->type->run_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + + target->running_alg = true; + retval = target->type->run_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_param, + entry_point, exit_point, timeout_ms, arch_info); + target->running_alg = false; + +done: + return retval; } + int target_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return target->type->read_memory(target, address, size, count, buffer); } -int target_read_phys_memory(struct target *target, +static int target_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return target->type->read_phys_memory(target, address, size, count, buffer); @@ -588,7 +688,7 @@ int target_write_memory(struct target *target, return target->type->write_memory(target, address, size, count, buffer); } -int target_write_phys_memory(struct target *target, +static int target_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return target->type->write_phys_memory(target, address, size, count, buffer); @@ -603,6 +703,10 @@ int target_bulk_write_memory(struct target *target, int target_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } return target->type->add_breakpoint(target, breakpoint); } int target_remove_breakpoint(struct target *target, @@ -614,6 +718,10 @@ int target_remove_breakpoint(struct target *target, int target_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } return target->type->add_watchpoint(target, watchpoint); } int target_remove_watchpoint(struct target *target, @@ -634,17 +742,6 @@ int target_step(struct target *target, } -int target_run_algorithm(struct target *target, - int num_mem_params, struct mem_param *mem_params, - int num_reg_params, struct reg_param *reg_param, - uint32_t entry_point, uint32_t exit_point, - int timeout_ms, void *arch_info) -{ - return target->type->run_algorithm(target, - num_mem_params, mem_params, num_reg_params, reg_param, - entry_point, exit_point, timeout_ms, arch_info); -} - /** * Reset the @c examined flag for the given target. * Pure paranoia -- targets are zeroed on allocation. @@ -654,222 +751,145 @@ static void target_reset_examined(struct target *target) target->examined = false; } - - -static int default_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) +static int +err_read_phys_memory(struct target *target, uint32_t address, + uint32_t size, uint32_t count, uint8_t *buffer) { LOG_ERROR("Not implemented: %s", __func__); return ERROR_FAIL; } -static int default_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) +static int +err_write_phys_memory(struct target *target, uint32_t address, + uint32_t size, uint32_t count, uint8_t *buffer) { LOG_ERROR("Not implemented: %s", __func__); return ERROR_FAIL; } -static int arm_cp_check(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm) +static int handle_target(void *priv); + +static int target_init_one(struct command_context *cmd_ctx, + struct target *target) { - /* basic check */ - if (!target_was_examined(target)) - { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } + target_reset_examined(target); - if ((cpnum <0) || (cpnum > 15)) - { - LOG_ERROR("Illegal co-processor %d", cpnum); - return ERROR_FAIL; - } + struct target_type *type = target->type; + if (type->examine == NULL) + type->examine = default_examine; - if (op1 > 7) - { - LOG_ERROR("Illegal op1"); - return ERROR_FAIL; - } + if (type->check_reset== NULL) + type->check_reset = default_check_reset; - if (op2 > 7) + int retval = type->init_target(cmd_ctx, target); + if (ERROR_OK != retval) { - LOG_ERROR("Illegal op2"); - return ERROR_FAIL; + LOG_ERROR("target '%s' init failed", target_name(target)); + return retval; } - if (CRn > 15) - { - LOG_ERROR("Illegal CRn"); - return ERROR_FAIL; - } + /** + * @todo get rid of those *memory_imp() methods, now that all + * callers are using target_*_memory() accessors ... and make + * sure the "physical" paths handle the same issues. + */ + /* a non-invasive way(in terms of patches) to add some code that + * runs before the type->write/read_memory implementation + */ + type->write_memory_imp = target->type->write_memory; + type->write_memory = target_write_memory_imp; + + type->read_memory_imp = target->type->read_memory; + type->read_memory = target_read_memory_imp; + + type->soft_reset_halt_imp = target->type->soft_reset_halt; + type->soft_reset_halt = target_soft_reset_halt_imp; - if (CRm > 15) + /* Sanity-check MMU support ... stub in what we must, to help + * implement it in stages, but warn if we need to do so. + */ + if (type->mmu) { - LOG_ERROR("Illegal CRm"); - return ERROR_FAIL; + if (type->write_phys_memory == NULL) + { + LOG_ERROR("type '%s' is missing write_phys_memory", + type->name); + type->write_phys_memory = err_write_phys_memory; + } + if (type->read_phys_memory == NULL) + { + LOG_ERROR("type '%s' is missing read_phys_memory", + type->name); + type->read_phys_memory = err_read_phys_memory; + } + if (type->virt2phys == NULL) + { + LOG_ERROR("type '%s' is missing virt2phys", type->name); + type->virt2phys = identity_virt2phys; + } } + else + { + /* Make sure no-MMU targets all behave the same: make no + * distinction between physical and virtual addresses, and + * ensure that virt2phys() is always an identity mapping. + */ + if (type->write_phys_memory || type->read_phys_memory + || type->virt2phys) + { + LOG_WARNING("type '%s' has bad MMU hooks", type->name); + } + type->mmu = no_mmu; + type->write_phys_memory = type->write_memory; + type->read_phys_memory = type->read_memory; + type->virt2phys = identity_virt2phys; + } return ERROR_OK; } -int target_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) +static int target_init(struct command_context *cmd_ctx) { + struct target *target; int retval; - retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm); - if (retval != ERROR_OK) - return retval; - - return target->type->mrc(target, cpnum, op1, op2, CRn, CRm, value); -} + for (target = all_targets; target; target = target->next) + { + retval = target_init_one(cmd_ctx, target); + if (ERROR_OK != retval) + return retval; + } -int target_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) -{ - int retval; + if (!all_targets) + return ERROR_OK; - retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm); - if (retval != ERROR_OK) + retval = target_register_user_commands(cmd_ctx); + if (ERROR_OK != retval) return retval; - return target->type->mcr(target, cpnum, op1, op2, CRn, CRm, value); -} - -static int -err_read_phys_memory(struct target *target, uint32_t address, - uint32_t size, uint32_t count, uint8_t *buffer) -{ - LOG_ERROR("Not implemented: %s", __func__); - return ERROR_FAIL; -} + retval = target_register_timer_callback(&handle_target, + polling_interval, 1, cmd_ctx->interp); + if (ERROR_OK != retval) + return retval; -static int -err_write_phys_memory(struct target *target, uint32_t address, - uint32_t size, uint32_t count, uint8_t *buffer) -{ - LOG_ERROR("Not implemented: %s", __func__); - return ERROR_FAIL; + return ERROR_OK; } -int target_init(struct command_context *cmd_ctx) +COMMAND_HANDLER(handle_target_init_command) { - struct target *target; - int retval; - - for (target = all_targets; target; target = target->next) { - struct target_type *type = target->type; - - target_reset_examined(target); - if (target->type->examine == NULL) - { - target->type->examine = default_examine; - } - - if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK) - { - LOG_ERROR("target '%s' init failed", target_get_name(target)); - return retval; - } - - /** - * @todo MCR/MRC are ARM-specific; don't require them in - * all targets, or for ARMs without coprocessors. - */ - if (target->type->mcr == NULL) - { - target->type->mcr = default_mcr; - } else - { - const struct command_registration mcr_cmd = { - .name = "mcr", - .mode = COMMAND_EXEC, - .jim_handler = &jim_mcrmrc, - .help = "write coprocessor", - .usage = " ", - }; - register_command(cmd_ctx, NULL, &mcr_cmd); - } - - if (target->type->mrc == NULL) - { - target->type->mrc = default_mrc; - } else - { - const struct command_registration mrc_cmd = { - .name = "mrc", - .jim_handler = &jim_mcrmrc, - .help = "read coprocessor", - .usage = " ", - }; - register_command(cmd_ctx, NULL, &mrc_cmd); - } - - - /** - * @todo get rid of those *memory_imp() methods, now that all - * callers are using target_*_memory() accessors ... and make - * sure the "physical" paths handle the same issues. - */ - - /* a non-invasive way(in terms of patches) to add some code that - * runs before the type->write/read_memory implementation - */ - target->type->write_memory_imp = target->type->write_memory; - target->type->write_memory = target_write_memory_imp; - target->type->read_memory_imp = target->type->read_memory; - target->type->read_memory = target_read_memory_imp; - target->type->soft_reset_halt_imp = target->type->soft_reset_halt; - target->type->soft_reset_halt = target_soft_reset_halt_imp; - target->type->run_algorithm_imp = target->type->run_algorithm; - target->type->run_algorithm = target_run_algorithm_imp; - - /* Sanity-check MMU support ... stub in what we must, to help - * implement it in stages, but warn if we need to do so. - */ - if (type->mmu) { - if (type->write_phys_memory == NULL) { - LOG_ERROR("type '%s' is missing %s", - type->name, - "write_phys_memory"); - type->write_phys_memory = err_write_phys_memory; - } - if (type->read_phys_memory == NULL) { - LOG_ERROR("type '%s' is missing %s", - type->name, - "read_phys_memory"); - type->read_phys_memory = err_read_phys_memory; - } - if (type->virt2phys == NULL) { - LOG_ERROR("type '%s' is missing %s", - type->name, - "virt2phys"); - type->virt2phys = identity_virt2phys; - } - - /* Make sure no-MMU targets all behave the same: make no - * distinction between physical and virtual addresses, and - * ensure that virt2phys() is always an identity mapping. - */ - } else { - if (type->write_phys_memory - || type->read_phys_memory - || type->virt2phys) - LOG_WARNING("type '%s' has broken MMU hooks", - type->name); - - type->mmu = no_mmu; - type->write_phys_memory = type->write_memory; - type->read_phys_memory = type->read_memory; - type->virt2phys = identity_virt2phys; - } - } + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; - if (all_targets) + static bool target_initialized = false; + if (target_initialized) { - if ((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK) - return retval; - if ((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK) - return retval; + LOG_INFO("'target init' has already been called"); + return ERROR_OK; } + target_initialized = true; - return ERROR_OK; + LOG_DEBUG("Initializing targets..."); + return target_init(CMD_CTX); } int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv) @@ -961,7 +981,7 @@ int target_unregister_event_callback(int (*callback)(struct target *target, enum return ERROR_OK; } -int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) +static int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) { struct target_timer_callback **p = &target_timer_callbacks; struct target_timer_callback *c = target_timer_callbacks; @@ -1084,7 +1104,7 @@ int target_call_timer_callbacks_now(void) return target_call_timer_callbacks_check_time(0); } -int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area) +int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area) { struct working_area *c = target->working_areas; struct working_area *new_wa = NULL; @@ -1162,8 +1182,6 @@ int target_alloc_working_area(struct target *target, uint32_t size, struct worki if (free_size < size) { - LOG_WARNING("not enough working area available(requested %u, free %u)", - (unsigned)(size), (unsigned)(free_size)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1204,7 +1222,20 @@ int target_alloc_working_area(struct target *target, uint32_t size, struct worki return ERROR_OK; } -int target_free_working_area_restore(struct target *target, struct working_area *area, int restore) +int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area) +{ + int retval; + + retval = target_alloc_working_area_try(target, size, area); + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) + { + LOG_WARNING("not enough working area available(requested %u)", (unsigned)(size)); + } + return retval; + +} + +static int target_free_working_area_restore(struct target *target, struct working_area *area, int restore) { if (area->free) return ERROR_OK; @@ -1233,7 +1264,7 @@ int target_free_working_area(struct target *target, struct working_area *area) /* free resources and restore memory, if restoring memory fails, * free up resources anyway */ -void target_free_all_working_areas_restore(struct target *target, int restore) +static void target_free_all_working_areas_restore(struct target *target, int restore) { struct working_area *c = target->working_areas; @@ -1695,8 +1726,8 @@ DumpTargets: command_print(CMD_CTX, "%2d%c %-18s %-10s %-6s %-18s %s", target->target_number, marker, - target->cmd_name, - target_get_name(target), + target_name(target), + target_type_name(target), Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness)->name, target->tap->dotted_name, @@ -1775,20 +1806,21 @@ static int sense_handler(void) return ERROR_OK; } -static void target_call_event_callbacks_all(enum target_event e) { - struct target *target; - target = all_targets; - while (target) { - target_call_event_callbacks(target, e); - target = target->next; - } -} +static int backoff_times = 0; +static int backoff_count = 0; /* process target state changes */ -int handle_target(void *priv) +static int handle_target(void *priv) { + Jim_Interp *interp = (Jim_Interp *)priv; int retval = ERROR_OK; + if (!is_jtag_poll_safe()) + { + /* polling is disabled currently */ + return ERROR_OK; + } + /* we do not want to recurse here... */ static int recursive = 0; if (! recursive) @@ -1802,7 +1834,7 @@ int handle_target(void *priv) int did_something = 0; if (runSrstAsserted) { - target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); + LOG_INFO("srst asserted detected, running srst_asserted proc."); Jim_Eval(interp, "srst_asserted"); did_something = 1; } @@ -1813,7 +1845,7 @@ int handle_target(void *priv) } if (runPowerDropout) { - target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); + LOG_INFO("Power dropout detected, running power_dropout proc."); Jim_Eval(interp, "power_dropout"); did_something = 1; } @@ -1839,6 +1871,14 @@ int handle_target(void *priv) recursive = 0; } + if (backoff_times > backoff_count) + { + /* do not poll this time as we failed previously */ + backoff_count++; + return ERROR_OK; + } + backoff_count = 0; + /* Poll targets for state changes unless that's globally disabled. * Skip targets that are currently disabled. */ @@ -1855,9 +1895,26 @@ int handle_target(void *priv) /* polling may fail silently until the target has been examined */ if ((retval = target_poll(target)) != ERROR_OK) { + /* 100ms polling interval. Increase interval between polling up to 5000ms */ + if (backoff_times * polling_interval < 5000) + { + backoff_times *= 2; + backoff_times++; + } + LOG_USER("Polling target failed, GDB will be halted. Polling again in %dms", backoff_times * polling_interval); + + /* Tell GDB to halt the debugger. This allows the user to + * run monitor commands to handle the situation. + */ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); return retval; } + /* Since we succeeded, we reset backoff count */ + if (backoff_times > 0) + { + LOG_USER("Polling succeeded again"); + } + backoff_times = 0; } } @@ -2104,11 +2161,11 @@ COMMAND_HANDLER(handle_halt_command) if (CMD_ARGC == 1) { - unsigned wait; - retval = parse_uint(CMD_ARGV[0], &wait); + unsigned wait_local; + retval = parse_uint(CMD_ARGV[0], &wait_local); if (ERROR_OK != retval) return ERROR_COMMAND_SYNTAX_ERROR; - if (!wait) + if (!wait_local) return ERROR_OK; } @@ -2205,11 +2262,12 @@ static void handle_md_output(struct command_context *cmd_ctx, const char *value_fmt; switch (size) { case 4: value_fmt = "%8.8x "; break; - case 2: value_fmt = "%4.2x "; break; + case 2: value_fmt = "%4.4x "; break; case 1: value_fmt = "%2.2x "; break; default: + /* "can't happen", caller checked */ LOG_ERROR("invalid memory read size: %u", size); - exit(-1); + return; } for (unsigned i = 0; i < count; i++) @@ -2290,6 +2348,76 @@ COMMAND_HANDLER(handle_md_command) return retval; } +typedef int (*target_write_fn)(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + +static int target_write_memory_fast(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +{ + return target_write_buffer(target, address, size * count, buffer); +} + +static int target_fill_mem(struct target *target, + uint32_t address, + target_write_fn fn, + unsigned data_size, + /* value */ + uint32_t b, + /* count */ + unsigned c) +{ + /* We have to write in reasonably large chunks to be able + * to fill large memory areas with any sane speed */ + const unsigned chunk_size = 16384; + uint8_t *target_buf = malloc(chunk_size * data_size); + if (target_buf == NULL) + { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + for (unsigned i = 0; i < chunk_size; i ++) + { + switch (data_size) + { + case 4: + target_buffer_set_u32(target, target_buf + i*data_size, b); + break; + case 2: + target_buffer_set_u16(target, target_buf + i*data_size, b); + break; + case 1: + target_buffer_set_u8(target, target_buf + i*data_size, b); + break; + default: + exit(-1); + } + } + + int retval = ERROR_OK; + + for (unsigned x = 0; x < c; x += chunk_size) + { + unsigned current; + current = c - x; + if (current > chunk_size) + { + current = chunk_size; + } + retval = fn(target, address + x * data_size, data_size, current, target_buf); + if (retval != ERROR_OK) + { + break; + } + /* avoid GDB timeouts */ + keep_alive(); + } + free(target_buf); + + return retval; +} + + COMMAND_HANDLER(handle_mw_command) { if (CMD_ARGC < 2) @@ -2297,8 +2425,7 @@ COMMAND_HANDLER(handle_mw_command) return ERROR_COMMAND_SYNTAX_ERROR; } bool physical=strcmp(CMD_ARGV[0], "phys")==0; - int (*fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_write_fn fn; if (physical) { CMD_ARGC--; @@ -2306,7 +2433,7 @@ COMMAND_HANDLER(handle_mw_command) fn=target_write_phys_memory; } else { - fn=target_write_memory; + fn = target_write_memory_fast; } if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -2323,35 +2450,22 @@ COMMAND_HANDLER(handle_mw_command) struct target *target = get_current_target(CMD_CTX); unsigned wordsize; - uint8_t value_buf[4]; switch (CMD_NAME[2]) { case 'w': wordsize = 4; - target_buffer_set_u32(target, value_buf, value); break; case 'h': wordsize = 2; - target_buffer_set_u16(target, value_buf, value); break; case 'b': wordsize = 1; - value_buf[0] = value; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - for (unsigned i = 0; i < count; i++) - { - int retval = fn(target, - address + i * wordsize, wordsize, 1, value_buf); - if (ERROR_OK != retval) - return retval; - keep_alive(); - } - - return ERROR_OK; + return target_fill_mem(target, address, fn, wordsize, value, count); } static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, @@ -2472,7 +2586,7 @@ COMMAND_HANDLER(handle_load_image_command) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "downloaded %" PRIu32 " bytes " - "in %fs (%0.3f kb/s)", image_size, + "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } @@ -2485,33 +2599,25 @@ COMMAND_HANDLER(handle_load_image_command) COMMAND_HANDLER(handle_dump_image_command) { struct fileio fileio; - uint8_t buffer[560]; - int retvaltemp; - - + int retval, retvaltemp; + uint32_t address, size; + struct duration bench; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC != 3) - { - command_print(CMD_CTX, "usage: dump_image
"); - return ERROR_OK; - } + return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address); - uint32_t size; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); - if (fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) - { - return ERROR_OK; - } + retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY); + if (retval != ERROR_OK) + return retval; - struct duration bench; duration_start(&bench); - int retval = ERROR_OK; + retval = ERROR_OK; while (size > 0) { size_t size_written; @@ -2532,16 +2638,20 @@ COMMAND_HANDLER(handle_dump_image_command) address += this_run_size; } - if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK) - return retvaltemp; - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + int filesize; + retval = fileio_size(&fileio, &filesize); + if (retval != ERROR_OK) + return retval; command_print(CMD_CTX, - "dumped %zu bytes in %fs (%0.3f kb/s)", fileio.size, - duration_elapsed(&bench), duration_kbps(&bench, fileio.size)); + "dumped %ld bytes in %fs (%0.3f KiB/s)", (long)filesize, + duration_elapsed(&bench), duration_kbps(&bench, filesize)); } + if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK) + return retvaltemp; + return retval; } @@ -2594,6 +2704,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) } image_size = 0x0; + int diffs = 0; retval = ERROR_OK; for (i = 0; i < image.num_sections; i++) { @@ -2614,7 +2725,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) if (verify) { /* calculate checksum of image */ - image_calculate_checksum(buffer, buf_cnt, &checksum); + retval = image_calculate_checksum(buffer, buf_cnt, &checksum); + if (retval != ERROR_OK) + { + free(buffer); + break; + } retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum); if (retval != ERROR_OK) @@ -2628,7 +2744,10 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) /* failed crc checksum, fall back to a binary compare */ uint8_t *data; - command_print(CMD_CTX, "checksum mismatch - attempting binary compare"); + if (diffs == 0) + { + LOG_ERROR("checksum mismatch - attempting binary compare"); + } data = (uint8_t*)malloc(buf_cnt); @@ -2649,22 +2768,22 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) if (data[t] != buffer[t]) { command_print(CMD_CTX, - "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", + "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", + diffs, (unsigned)(t + image.sections[i].base_address), data[t], buffer[t]); - free(data); - free(buffer); - retval = ERROR_FAIL; - goto done; - } - if ((t%16384) == 0) - { - keep_alive(); + if (diffs++ >= 127) + { + command_print(CMD_CTX, "More than 128 errors, the rest are not printed."); + free(data); + free(buffer); + goto done; + } } + keep_alive(); } } - free(data); } } else @@ -2677,11 +2796,19 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) free(buffer); image_size += buf_cnt; } + if (diffs > 0) + { + command_print(CMD_CTX, "No more differences found."); + } done: + if (diffs > 0) + { + retval = ERROR_FAIL; + } if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "verified %" PRIu32 " bytes " - "in %fs (%0.3f kb/s)", image_size, + "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } @@ -2969,8 +3096,8 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam long long a = address-min; long long b = length-1; long long c = addressSpace-1; - int index = (a*b)/c; /* danger!!!! int32 overflows */ - buckets[index]++; + int index_t = (a*b)/c; /* danger!!!! int32 overflows */ + buckets[index_t]++; } /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */ @@ -3010,7 +3137,8 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam fclose(f); } -/* profiling samples the CPU PC as quickly as OpenOCD is able, which will be used as a random sampling of PC */ +/* profiling samples the CPU PC as quickly as OpenOCD is able, + * which will be used as a random sampling of PC */ COMMAND_HANDLER(handle_profile_command) { struct target *target = get_current_target(CMD_CTX); @@ -3026,6 +3154,12 @@ COMMAND_HANDLER(handle_profile_command) timeval_add_time(&timeout, offset, 0); + /** + * @todo: Some cores let us sample the PC without the + * annoying halt/resume step; for example, ARMv7 PCSR. + * Provide a way to use that more efficient mechanism. + */ + command_print(CMD_CTX, "Starting profiling. Halting and resuming the target as often as we can..."); static const int maxSample = 10000; @@ -3128,12 +3262,9 @@ static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct command_context *context; struct target *target; - context = Jim_GetAssocData(interp, "context"); - if (context == NULL) - { - LOG_ERROR("mem2array: no command context"); - return JIM_ERR; - } + context = current_command_context(interp); + assert (context != NULL); + target = get_current_target(context); if (target == NULL) { @@ -3324,11 +3455,9 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct command_context *context; struct target *target; - context = Jim_GetAssocData(interp, "context"); - if (context == NULL) { - LOG_ERROR("array2mem: no command context"); - return JIM_ERR; - } + context = current_command_context(interp); + assert (context != NULL); + target = get_current_target(context); if (target == NULL) { LOG_ERROR("array2mem: no current target"); @@ -3337,7 +3466,9 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return target_array2mem(interp,target, argc-1, argv + 1); } -static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) + +static int target_array2mem(Jim_Interp *interp, struct target *target, + int argc, Jim_Obj *const *argv) { long l; uint32_t width; @@ -3355,7 +3486,7 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, * argv[4] = count to write */ if (argc != 4) { - Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); + Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems"); return JIM_ERR; } varname = Jim_GetString(argv[0], &len); @@ -3481,22 +3612,6 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, return JIM_OK; } -void target_all_handle_event(enum target_event e) -{ - struct target *target; - - LOG_DEBUG("**all*targets: event: %d, %s", - (int)e, - Jim_Nvp_value2name_simple(nvp_target_event, e)->name); - - target = all_targets; - while (target) { - target_handle_event(target, e); - target = target->next; - } -} - - /* FIX? should we propagate errors here rather than printing them * and continuing? */ @@ -3508,19 +3623,34 @@ void target_handle_event(struct target *target, enum target_event e) if (teap->event == e) { LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s", target->target_number, - target->cmd_name, - target_get_name(target), + target_name(target), + target_type_name(target), e, Jim_Nvp_value2name_simple(nvp_target_event, e)->name, Jim_GetString(teap->body, NULL)); - if (Jim_EvalObj(interp, teap->body) != JIM_OK) + if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) { - Jim_PrintErrorMessage(interp); + Jim_MakeErrorMessage(teap->interp); + command_print(NULL,"%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL)); } } } } +/** + * Returns true only if the target has a handler for the specified event. + */ +bool target_has_event_action(struct target *target, enum target_event event) +{ + struct target_event_action *teap; + + for (teap = target->event_action; teap != NULL; teap = teap->next) { + if (teap->event == event) + return true; + } + return false; +} + enum target_cfg_param { TCFG_TYPE, TCFG_EVENT, @@ -3583,16 +3713,20 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) case TCFG_TYPE: /* not setable */ if (goi->isconfigure) { - Jim_SetResult_sprintf(goi->interp, "not setable: %s", n->name); + Jim_SetResultFormatted(goi->interp, + "not settable: %s", n->name); return JIM_ERR; } else { no_params: if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); + Jim_WrongNumArgs(goi->interp, + goi->argc, goi->argv, + "NO PARAMS"); return JIM_ERR; } } - Jim_SetResultString(goi->interp, target_get_name(target), -1); + Jim_SetResultString(goi->interp, + target_type_name(target), -1); /* loop for more */ break; case TCFG_EVENT: @@ -3639,9 +3773,10 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) replace = false; } teap->event = n->value; + teap->interp = goi->interp; Jim_GetOpt_Obj(goi, &o); if (teap->body) { - Jim_DecrRefCount(interp, teap->body); + Jim_DecrRefCount(teap->interp, teap->body); } teap->body = Jim_DuplicateObj(goi->interp, o); /* @@ -3689,7 +3824,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) goto no_params; } } - Jim_SetResult(interp, Jim_NewIntObj(goi->interp, target->working_area_virt)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt)); /* loop for more */ break; @@ -3707,7 +3842,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) goto no_params; } } - Jim_SetResult(interp, Jim_NewIntObj(goi->interp, target->working_area_phys)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys)); /* loop for more */ break; @@ -3724,7 +3859,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) goto no_params; } } - Jim_SetResult(interp, Jim_NewIntObj(goi->interp, target->working_area_size)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); /* loop for more */ break; @@ -3742,7 +3877,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) goto no_params; } } - Jim_SetResult(interp, Jim_NewIntObj(goi->interp, target->backup_working_area)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area)); /* loop for more e*/ break; @@ -3771,7 +3906,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) case TCFG_VARIANT: if (goi->isconfigure) { if (goi->argc < 1) { - Jim_SetResult_sprintf(goi->interp, + Jim_SetResultFormatted(goi->interp, "%s ?STRING?", n->name); return JIM_ERR; @@ -3791,14 +3926,14 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) break; case TCFG_CHAIN_POSITION: if (goi->isconfigure) { - Jim_Obj *o; + Jim_Obj *o_t; struct jtag_tap *tap; target_free_all_working_areas(target); - e = Jim_GetOpt_Obj(goi, &o); + e = Jim_GetOpt_Obj(goi, &o_t); if (e != JIM_OK) { return e; } - tap = jtag_tap_by_jim_obj(goi->interp, o); + tap = jtag_tap_by_jim_obj(goi->interp, o_t); if (tap == NULL) { return JIM_ERR; } @@ -3809,7 +3944,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) goto no_params; } } - Jim_SetResultString(interp, target->tap->dotted_name, -1); + Jim_SetResultString(goi->interp, target->tap->dotted_name, -1); /* loop for more e*/ break; } @@ -3820,422 +3955,621 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) return JIM_OK; } -/** this is the 'tcl' handler for the target specific command */ -static int tcl_target_func(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int +jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; - jim_wide a,b,c; - int x,y,z; - uint8_t target_buf[32]; - Jim_Nvp *n; - struct target *target; - struct command_context *cmd_ctx; - int e; - enum { - TS_CMD_CONFIGURE, - TS_CMD_CGET, - - TS_CMD_MWW, TS_CMD_MWH, TS_CMD_MWB, - TS_CMD_MDW, TS_CMD_MDH, TS_CMD_MDB, - TS_CMD_MRW, TS_CMD_MRH, TS_CMD_MRB, - TS_CMD_MEM2ARRAY, TS_CMD_ARRAY2MEM, - TS_CMD_EXAMINE, - TS_CMD_POLL, - TS_CMD_RESET, - TS_CMD_HALT, - TS_CMD_WAITSTATE, - TS_CMD_EVENTLIST, - TS_CMD_CURSTATE, - TS_CMD_INVOKE_EVENT, - }; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); + int need_args = 1 + goi.isconfigure; + if (goi.argc < need_args) + { + Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, + goi.isconfigure + ? "missing: -option VALUE ..." + : "missing: -option ..."); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(goi.interp); + return target_configure(&goi, target); +} - static const Jim_Nvp target_options[] = { - { .name = "configure", .value = TS_CMD_CONFIGURE }, - { .name = "cget", .value = TS_CMD_CGET }, - { .name = "mww", .value = TS_CMD_MWW }, - { .name = "mwh", .value = TS_CMD_MWH }, - { .name = "mwb", .value = TS_CMD_MWB }, - { .name = "mdw", .value = TS_CMD_MDW }, - { .name = "mdh", .value = TS_CMD_MDH }, - { .name = "mdb", .value = TS_CMD_MDB }, - { .name = "mem2array", .value = TS_CMD_MEM2ARRAY }, - { .name = "array2mem", .value = TS_CMD_ARRAY2MEM }, - { .name = "eventlist", .value = TS_CMD_EVENTLIST }, - { .name = "curstate", .value = TS_CMD_CURSTATE }, - - { .name = "arp_examine", .value = TS_CMD_EXAMINE }, - { .name = "arp_poll", .value = TS_CMD_POLL }, - { .name = "arp_reset", .value = TS_CMD_RESET }, - { .name = "arp_halt", .value = TS_CMD_HALT }, - { .name = "arp_waitstate", .value = TS_CMD_WAITSTATE }, - { .name = "invoke-event", .value = TS_CMD_INVOKE_EVENT }, - - { .name = NULL, .value = -1 }, - }; +static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *cmd_name = Jim_GetString(argv[0], NULL); + + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - /* go past the "command" */ - Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); + if (goi.argc < 2 || goi.argc > 4) + { + Jim_SetResultFormatted(goi.interp, + "usage: %s [phys]
[]", cmd_name); + return JIM_ERR; + } - target = Jim_CmdPrivData(goi.interp); - cmd_ctx = Jim_GetAssocData(goi.interp, "context"); + target_write_fn fn; + fn = target_write_memory_fast; - /* commands here are in an NVP table */ - e = Jim_GetOpt_Nvp(&goi, target_options, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, target_options, 0); + int e; + if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) + { + /* consume it */ + struct Jim_Obj *obj; + e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + + fn = target_write_phys_memory; + } + + jim_wide a; + e = Jim_GetOpt_Wide(&goi, &a); + if (e != JIM_OK) + return e; + + jim_wide b; + e = Jim_GetOpt_Wide(&goi, &b); + if (e != JIM_OK) return e; + + jim_wide c = 1; + if (goi.argc == 1) + { + e = Jim_GetOpt_Wide(&goi, &c); + if (e != JIM_OK) + return e; } - /* Assume blank result */ - Jim_SetEmptyResult(goi.interp); - switch (n->value) { - case TS_CMD_CONFIGURE: - if (goi.argc < 2) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option VALUE ..."); - return JIM_ERR; - } - goi.isconfigure = 1; - return target_configure(&goi, target); - case TS_CMD_CGET: - // some things take params - if (goi.argc < 1) { - Jim_WrongNumArgs(goi.interp, 0, goi.argv, "missing: ?-option?"); - return JIM_ERR; - } - goi.isconfigure = 0; - return target_configure(&goi, target); - break; - case TS_CMD_MWW: - case TS_CMD_MWH: - case TS_CMD_MWB: - /* argv[0] = cmd - * argv[1] = address - * argv[2] = data - * argv[3] = optional count. - */ + /* all args must be consumed */ + if (goi.argc != 0) + { + return JIM_ERR; + } - if ((goi.argc == 2) || (goi.argc == 3)) { - /* all is well */ - } else { - mwx_error: - Jim_SetResult_sprintf(goi.interp, "expected: %s ADDR DATA [COUNT]", n->name); - return JIM_ERR; - } + struct target *target = Jim_CmdPrivData(goi.interp); + unsigned data_size; + if (strcasecmp(cmd_name, "mww") == 0) { + data_size = 4; + } + else if (strcasecmp(cmd_name, "mwh") == 0) { + data_size = 2; + } + else if (strcasecmp(cmd_name, "mwb") == 0) { + data_size = 1; + } else { + LOG_ERROR("command '%s' unknown: ", cmd_name); + return JIM_ERR; + } - e = Jim_GetOpt_Wide(&goi, &a); - if (e != JIM_OK) { - goto mwx_error; - } + return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR; +} - e = Jim_GetOpt_Wide(&goi, &b); - if (e != JIM_OK) { - goto mwx_error; - } - if (goi.argc == 3) { - e = Jim_GetOpt_Wide(&goi, &c); - if (e != JIM_OK) { - goto mwx_error; - } - } else { - c = 1; - } +static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *cmd_name = Jim_GetString(argv[0], NULL); - switch (n->value) { - case TS_CMD_MWW: - target_buffer_set_u32(target, target_buf, b); - b = 4; - break; - case TS_CMD_MWH: - target_buffer_set_u16(target, target_buf, b); - b = 2; - break; - case TS_CMD_MWB: - target_buffer_set_u8(target, target_buf, b); - b = 1; - break; - } - for (x = 0 ; x < c ; x++) { - e = target_write_memory(target, a, b, 1, target_buf); - if (e != ERROR_OK) { - Jim_SetResult_sprintf(interp, "Error writing @ 0x%08x: %d\n", (int)(a), e); - return JIM_ERR; - } - /* b = width */ - a = a + b; - } - return JIM_OK; - break; + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - /* display */ - case TS_CMD_MDW: - case TS_CMD_MDH: - case TS_CMD_MDB: - /* argv[0] = command - * argv[1] = address - * argv[2] = optional count - */ - if ((goi.argc == 2) || (goi.argc == 3)) { - Jim_SetResult_sprintf(goi.interp, "expected: %s ADDR [COUNT]", n->name); - return JIM_ERR; - } - e = Jim_GetOpt_Wide(&goi, &a); + if ((goi.argc < 1) || (goi.argc > 3)) + { + Jim_SetResultFormatted(goi.interp, + "usage: %s [phys]
[]", cmd_name); + return JIM_ERR; + } + + int (*fn)(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + fn=target_read_memory; + + int e; + if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) + { + /* consume it */ + struct Jim_Obj *obj; + e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + + fn=target_read_phys_memory; + } + + jim_wide a; + e = Jim_GetOpt_Wide(&goi, &a); + if (e != JIM_OK) { + return JIM_ERR; + } + jim_wide c; + if (goi.argc == 1) { + e = Jim_GetOpt_Wide(&goi, &c); if (e != JIM_OK) { return JIM_ERR; } - if (goi.argc) { - e = Jim_GetOpt_Wide(&goi, &c); - if (e != JIM_OK) { - return JIM_ERR; - } - } else { - c = 1; + } else { + c = 1; + } + + /* all args must be consumed */ + if (goi.argc != 0) + { + return JIM_ERR; + } + + jim_wide b = 1; /* shut up gcc */ + if (strcasecmp(cmd_name, "mdw") == 0) + b = 4; + else if (strcasecmp(cmd_name, "mdh") == 0) + b = 2; + else if (strcasecmp(cmd_name, "mdb") == 0) + b = 1; + else { + LOG_ERROR("command '%s' unknown: ", cmd_name); + return JIM_ERR; + } + + /* convert count to "bytes" */ + c = c * b; + + struct target *target = Jim_CmdPrivData(goi.interp); + uint8_t target_buf[32]; + jim_wide x, y, z; + while (c > 0) { + y = c; + if (y > 16) { + y = 16; } - b = 1; /* shut up gcc */ - switch (n->value) { - case TS_CMD_MDW: - b = 4; - break; - case TS_CMD_MDH: - b = 2; - break; - case TS_CMD_MDB: - b = 1; - break; + e = fn(target, a, b, y / b, target_buf); + if (e != ERROR_OK) { + char tmp[10]; + snprintf(tmp, sizeof(tmp), "%08lx", (long)a); + Jim_SetResultFormatted(interp, "error reading target @ 0x%s", tmp); + return JIM_ERR; } - /* convert to "bytes" */ - c = c * b; - /* count is now in 'BYTES' */ - while (c > 0) { - y = c; - if (y > 16) { - y = 16; + command_print(NULL, "0x%08x ", (int)(a)); + switch (b) { + case 4: + for (x = 0; x < 16 && x < y; x += 4) + { + z = target_buffer_get_u32(target, &(target_buf[ x ])); + command_print(NULL, "%08x ", (int)(z)); } - e = target_read_memory(target, a, b, y / b, target_buf); - if (e != ERROR_OK) { - Jim_SetResult_sprintf(interp, "error reading target @ 0x%08lx", (int)(a)); - return JIM_ERR; + for (; (x < 16) ; x += 4) { + command_print(NULL, " "); } - - Jim_fprintf(interp, interp->cookie_stdout, "0x%08x ", (int)(a)); - switch (b) { - case 4: - for (x = 0 ; (x < 16) && (x < y) ; x += 4) { - z = target_buffer_get_u32(target, &(target_buf[ x * 4 ])); - Jim_fprintf(interp, interp->cookie_stdout, "%08x ", (int)(z)); - } - for (; (x < 16) ; x += 4) { - Jim_fprintf(interp, interp->cookie_stdout, " "); - } - break; - case 2: - for (x = 0 ; (x < 16) && (x < y) ; x += 2) { - z = target_buffer_get_u16(target, &(target_buf[ x * 2 ])); - Jim_fprintf(interp, interp->cookie_stdout, "%04x ", (int)(z)); - } - for (; (x < 16) ; x += 2) { - Jim_fprintf(interp, interp->cookie_stdout, " "); - } - break; - case 1: - default: - for (x = 0 ; (x < 16) && (x < y) ; x += 1) { - z = target_buffer_get_u8(target, &(target_buf[ x * 4 ])); - Jim_fprintf(interp, interp->cookie_stdout, "%02x ", (int)(z)); - } - for (; (x < 16) ; x += 1) { - Jim_fprintf(interp, interp->cookie_stdout, " "); - } - break; + break; + case 2: + for (x = 0; x < 16 && x < y; x += 2) + { + z = target_buffer_get_u16(target, &(target_buf[ x ])); + command_print(NULL, "%04x ", (int)(z)); } - /* ascii-ify the bytes */ - for (x = 0 ; x < y ; x++) { - if ((target_buf[x] >= 0x20) && - (target_buf[x] <= 0x7e)) { - /* good */ - } else { - /* smack it */ - target_buf[x] = '.'; - } + for (; (x < 16) ; x += 2) { + command_print(NULL, " "); } - /* space pad */ - while (x < 16) { - target_buf[x] = ' '; - x++; + break; + case 1: + default: + for (x = 0 ; (x < 16) && (x < y) ; x += 1) { + z = target_buffer_get_u8(target, &(target_buf[ x ])); + command_print(NULL, "%02x ", (int)(z)); } - /* terminate */ - target_buf[16] = 0; - /* print - with a newline */ - Jim_fprintf(interp, interp->cookie_stdout, "%s\n", target_buf); - /* NEXT... */ - c -= 16; - a += 16; - } - return JIM_OK; - case TS_CMD_MEM2ARRAY: - return target_mem2array(goi.interp, target, goi.argc, goi.argv); - break; - case TS_CMD_ARRAY2MEM: - return target_array2mem(goi.interp, target, goi.argc, goi.argv); - break; - case TS_CMD_EXAMINE: - if (goi.argc) { - Jim_WrongNumArgs(goi.interp, 2, argv, "[no parameters]"); - return JIM_ERR; - } - if (!target->tap->enabled) - goto err_tap_disabled; - e = target->type->examine(target); - if (e != ERROR_OK) { - Jim_SetResult_sprintf(interp, "examine-fails: %d", e); - return JIM_ERR; - } - return JIM_OK; - case TS_CMD_POLL: - if (goi.argc) { - Jim_WrongNumArgs(goi.interp, 2, argv, "[no parameters]"); - return JIM_ERR; - } - if (!target->tap->enabled) - goto err_tap_disabled; - if (!(target_was_examined(target))) { - e = ERROR_TARGET_NOT_EXAMINED; - } else { - e = target->type->poll(target); - } - if (e != ERROR_OK) { - Jim_SetResult_sprintf(interp, "poll-fails: %d", e); - return JIM_ERR; - } else { - return JIM_OK; - } - break; - case TS_CMD_RESET: - if (goi.argc != 2) { - Jim_WrongNumArgs(interp, 2, argv, - "([tT]|[fF]|assert|deassert) BOOL"); - return JIM_ERR; - } - e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1); - return e; - } - /* the halt or not param */ - e = Jim_GetOpt_Wide(&goi, &a); - if (e != JIM_OK) { - return e; - } - if (!target->tap->enabled) - goto err_tap_disabled; - if (!target->type->assert_reset - || !target->type->deassert_reset) { - Jim_SetResult_sprintf(interp, - "No target-specific reset for %s", - target->cmd_name); - return JIM_ERR; - } - /* determine if we should halt or not. */ - target->reset_halt = !!a; - /* When this happens - all workareas are invalid. */ - target_free_all_working_areas_restore(target, 0); - - /* do the assert */ - if (n->value == NVP_ASSERT) { - e = target->type->assert_reset(target); - } else { - e = target->type->deassert_reset(target); - } - return (e == ERROR_OK) ? JIM_OK : JIM_ERR; - case TS_CMD_HALT: - if (goi.argc) { - Jim_WrongNumArgs(goi.interp, 0, argv, "halt [no parameters]"); - return JIM_ERR; - } - if (!target->tap->enabled) - goto err_tap_disabled; - e = target->type->halt(target); - return (e == ERROR_OK) ? JIM_OK : JIM_ERR; - case TS_CMD_WAITSTATE: - /* params: statename timeoutmsecs */ - if (goi.argc != 2) { - Jim_SetResult_sprintf(goi.interp, "%s STATENAME TIMEOUTMSECS", n->name); - return JIM_ERR; - } - e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, nvp_target_state,1); - return e; - } - e = Jim_GetOpt_Wide(&goi, &a); - if (e != JIM_OK) { - return e; - } - if (!target->tap->enabled) - goto err_tap_disabled; - e = target_wait_state(target, n->value, a); - if (e != ERROR_OK) { - Jim_SetResult_sprintf(goi.interp, - "target: %s wait %s fails (%d) %s", - target->cmd_name, - n->name, - e, target_strerror_safe(e)); - return JIM_ERR; - } else { - return JIM_OK; + for (; (x < 16) ; x += 1) { + command_print(NULL, " "); + } + break; } - case TS_CMD_EVENTLIST: - /* List for human, Events defined for this target. - * scripts/programs should use 'name cget -event NAME' - */ - { - struct target_event_action *teap; - teap = target->event_action; - command_print(cmd_ctx, "Event actions for target (%d) %s\n", - target->target_number, - target->cmd_name); - command_print(cmd_ctx, "%-25s | Body", "Event"); - command_print(cmd_ctx, "------------------------- | ----------------------------------------"); - while (teap) { - command_print(cmd_ctx, - "%-25s | %s", - Jim_Nvp_value2name_simple(nvp_target_event, teap->event)->name, - Jim_GetString(teap->body, NULL)); - teap = teap->next; + /* ascii-ify the bytes */ + for (x = 0 ; x < y ; x++) { + if ((target_buf[x] >= 0x20) && + (target_buf[x] <= 0x7e)) { + /* good */ + } else { + /* smack it */ + target_buf[x] = '.'; } - command_print(cmd_ctx, "***END***"); - return JIM_OK; } - case TS_CMD_CURSTATE: - if (goi.argc != 0) { - Jim_WrongNumArgs(goi.interp, 0, argv, "[no parameters]"); - return JIM_ERR; + /* space pad */ + while (x < 16) { + target_buf[x] = ' '; + x++; } - Jim_SetResultString(goi.interp, - target_state_name( target ), - -1); - return JIM_OK; - case TS_CMD_INVOKE_EVENT: - if (goi.argc != 1) { - Jim_SetResult_sprintf(goi.interp, "%s ?EVENTNAME?",n->name); - return JIM_ERR; - } - e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); - return e; - } - target_handle_event(target, n->value); - return JIM_OK; + /* terminate */ + target_buf[16] = 0; + /* print - with a newline */ + command_print(NULL, "%s\n", target_buf); + /* NEXT... */ + c -= 16; + a += 16; } - return JIM_ERR; + return JIM_OK; +} + +static int jim_target_mem2array(Jim_Interp *interp, + int argc, Jim_Obj *const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + return target_mem2array(interp, target, argc - 1, argv + 1); +} -err_tap_disabled: - Jim_SetResult_sprintf(interp, "[TAP is disabled]"); +static int jim_target_array2mem(Jim_Interp *interp, + int argc, Jim_Obj *const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + return target_array2mem(interp, target, argc - 1, argv + 1); +} + +static int jim_target_tap_disabled(Jim_Interp *interp) +{ + Jim_SetResultFormatted(interp, "[TAP is disabled]"); return JIM_ERR; } +static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + + int e = target->type->examine(target); + if (e != ERROR_OK) + { + Jim_Obj *eObj = Jim_NewIntObj(interp, e); + Jim_SetResultFormatted(interp, "examine-fails: %#s", eObj); + Jim_FreeNewObj(interp, eObj); + return JIM_ERR; + } + return JIM_OK; +} + +static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + + if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) + return JIM_ERR; + + return JIM_OK; +} + +static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + + int e; + if (!(target_was_examined(target))) { + e = ERROR_TARGET_NOT_EXAMINED; + } else { + e = target->type->poll(target); + } + if (e != ERROR_OK) + { + Jim_Obj *eObj = Jim_NewIntObj(interp, e); + Jim_SetResultFormatted(interp, "poll-fails: %#s", eObj); + Jim_FreeNewObj(interp, eObj); + return JIM_ERR; + } + return JIM_OK; +} + +static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + + if (goi.argc != 2) + { + Jim_WrongNumArgs(interp, 0, argv, + "([tT]|[fF]|assert|deassert) BOOL"); + return JIM_ERR; + } + + Jim_Nvp *n; + int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n); + if (e != JIM_OK) + { + Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1); + return e; + } + /* the halt or not param */ + jim_wide a; + e = Jim_GetOpt_Wide(&goi, &a); + if (e != JIM_OK) + return e; + + struct target *target = Jim_CmdPrivData(goi.interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + if (!(target_was_examined(target))) + { + LOG_ERROR("Target not examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } + if (!target->type->assert_reset || !target->type->deassert_reset) + { + Jim_SetResultFormatted(interp, + "No target-specific reset for %s", + target_name(target)); + return JIM_ERR; + } + /* determine if we should halt or not. */ + target->reset_halt = !!a; + /* When this happens - all workareas are invalid. */ + target_free_all_working_areas_restore(target, 0); + + /* do the assert */ + if (n->value == NVP_ASSERT) { + e = target->type->assert_reset(target); + } else { + e = target->type->deassert_reset(target); + } + return (e == ERROR_OK) ? JIM_OK : JIM_ERR; +} + +static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + int e = target->type->halt(target); + return (e == ERROR_OK) ? JIM_OK : JIM_ERR; +} + +static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + + /* params: statename timeoutmsecs */ + if (goi.argc != 2) + { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, + "%s ", cmd_name); + return JIM_ERR; + } + + Jim_Nvp *n; + int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(&goi, nvp_target_state,1); + return e; + } + jim_wide a; + e = Jim_GetOpt_Wide(&goi, &a); + if (e != JIM_OK) { + return e; + } + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + + e = target_wait_state(target, n->value, a); + if (e != ERROR_OK) + { + Jim_Obj *eObj = Jim_NewIntObj(interp, e); + Jim_SetResultFormatted(goi.interp, + "target: %s wait %s fails (%#s) %s", + target_name(target), n->name, + eObj, target_strerror_safe(e)); + Jim_FreeNewObj(interp, eObj); + return JIM_ERR; + } + return JIM_OK; +} +/* 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) +{ + struct command_context *cmd_ctx = current_command_context(interp); + assert (cmd_ctx != NULL); + + struct target *target = Jim_CmdPrivData(interp); + struct target_event_action *teap = target->event_action; + 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, "------------------------- | " + "----------------------------------------"); + while (teap) + { + Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event); + command_print(cmd_ctx, "%-25s | %s", + opt->name, Jim_GetString(teap->body, NULL)); + teap = teap->next; + } + command_print(cmd_ctx, "***END***"); + return JIM_OK; +} +static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + Jim_SetResultString(interp, target_state_name(target), -1); + return JIM_OK; +} +static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc != 1) + { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); + return JIM_ERR; + } + Jim_Nvp *n; + int e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n); + if (e != JIM_OK) + { + Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); + return e; + } + struct target *target = Jim_CmdPrivData(interp); + target_handle_event(target, n->value); + return JIM_OK; +} + +static const struct command_registration target_instance_command_handlers[] = { + { + .name = "configure", + .mode = COMMAND_CONFIG, + .jim_handler = jim_target_configure, + .help = "configure a new target for use", + .usage = "[target_attribute ...]", + }, + { + .name = "cget", + .mode = COMMAND_ANY, + .jim_handler = jim_target_configure, + .help = "returns the specified target attribute", + .usage = "target_attribute", + }, + { + .name = "mww", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mw, + .help = "Write 32-bit word(s) to target memory", + .usage = "address data [count]", + }, + { + .name = "mwh", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mw, + .help = "Write 16-bit half-word(s) to target memory", + .usage = "address data [count]", + }, + { + .name = "mwb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mw, + .help = "Write byte(s) to target memory", + .usage = "address data [count]", + }, + { + .name = "mdw", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_md, + .help = "Display target memory as 32-bit words", + .usage = "address [count]", + }, + { + .name = "mdh", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_md, + .help = "Display target memory as 16-bit half-words", + .usage = "address [count]", + }, + { + .name = "mdb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_md, + .help = "Display target memory as 8-bit bytes", + .usage = "address [count]", + }, + { + .name = "array2mem", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_array2mem, + .help = "Writes Tcl array of 8/16/32 bit numbers " + "to target memory", + .usage = "arrayname bitwidth address count", + }, + { + .name = "mem2array", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mem2array, + .help = "Loads Tcl array of 8/16/32 bit numbers " + "from target memory", + .usage = "arrayname bitwidth address count", + }, + { + .name = "eventlist", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_event_list, + .help = "displays a table of events defined for this target", + }, + { + .name = "curstate", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_current_state, + .help = "displays the current state of this target", + }, + { + .name = "arp_examine", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_examine, + .help = "used internally for reset processing", + }, + { + .name = "arp_halt_gdb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_halt_gdb, + .help = "used internally for reset processing to halt GDB", + }, + { + .name = "arp_poll", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_poll, + .help = "used internally for reset processing", + }, + { + .name = "arp_reset", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_reset, + .help = "used internally for reset processing", + }, + { + .name = "arp_halt", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_halt, + .help = "used internally for reset processing", + }, + { + .name = "arp_waitstate", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_wait_state, + .help = "used internally for reset processing", + }, + { + .name = "invoke-event", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_invoke_event, + .help = "invoke handler for specified event", + .usage = "event_name", + }, + COMMAND_REGISTRATION_DONE +}; + static int target_create(Jim_GetOptInfo *goi) { Jim_Obj *new_cmd; @@ -4247,7 +4581,9 @@ static int target_create(Jim_GetOptInfo *goi) struct target *target; struct command_context *cmd_ctx; - cmd_ctx = Jim_GetAssocData(goi->interp, "context"); + cmd_ctx = current_command_context(goi->interp); + assert (cmd_ctx != NULL); + if (goi->argc < 3) { Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options..."); return JIM_ERR; @@ -4259,7 +4595,7 @@ static int target_create(Jim_GetOptInfo *goi) cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); if (cmd) { cp = Jim_GetString(new_cmd, NULL); - Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp); + Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); return JIM_ERR; } @@ -4274,7 +4610,7 @@ static int target_create(Jim_GetOptInfo *goi) } } if (target_types[x] == NULL) { - Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp); + Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); for (x = 0 ; target_types[x] ; x++) { if (target_types[x + 1]) { Jim_AppendStrings(goi->interp, @@ -4342,7 +4678,7 @@ static int target_create(Jim_GetOptInfo *goi) if (target->tap == NULL) { - Jim_SetResultString(interp, "-chain-position required when creating target", -1); + Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1); e = JIM_ERR; } @@ -4385,136 +4721,200 @@ static int target_create(Jim_GetOptInfo *goi) } /* now - create the new target name command */ - const struct command_registration target_command = { - .name = cp, - .jim_handler = &tcl_target_func, - .jim_handler_data = target, - .help = "target command group", + const const struct command_registration target_subcommands[] = { + { + .chain = target_instance_command_handlers, + }, + { + .chain = target->type->commands, + }, + COMMAND_REGISTRATION_DONE }; - struct command *c = register_command(cmd_ctx, NULL, &target_command); - return (NULL != c) ? ERROR_OK : ERROR_FAIL; + const const struct command_registration target_commands[] = { + { + .name = cp, + .mode = COMMAND_ANY, + .help = "target command group", + .chain = target_subcommands, + }, + COMMAND_REGISTRATION_DONE + }; + e = register_commands(cmd_ctx, NULL, target_commands); + if (ERROR_OK != e) + return JIM_ERR; + + struct command *c = command_find_in_context(cmd_ctx, cp); + assert(c); + command_set_handler_data(c, target); + + return (ERROR_OK == e) ? JIM_OK : JIM_ERR; } -static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - int x,r,e; - jim_wide w; - struct command_context *cmd_ctx; - struct target *target; - Jim_GetOptInfo goi; - enum tcmd { - /* TG = target generic */ - TG_CMD_CREATE, - TG_CMD_TYPES, - TG_CMD_NAMES, - TG_CMD_CURRENT, - TG_CMD_NUMBER, - TG_CMD_COUNT, - }; - const char *target_cmds[] = { - "create", "types", "names", "current", "number", - "count", - NULL /* terminate */ - }; - - LOG_DEBUG("Target command params:"); - LOG_DEBUG("%s", Jim_Debug_ArgvString(interp, argc, argv)); + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); + return JIM_ERR; + } + struct command_context *cmd_ctx = current_command_context(interp); + assert (cmd_ctx != NULL); - cmd_ctx = Jim_GetAssocData(interp, "context"); + Jim_SetResultString(interp, get_current_target(cmd_ctx)->cmd_name, -1); + return JIM_OK; +} - Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); +static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); + return JIM_ERR; + } + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + for (unsigned x = 0; NULL != target_types[x]; x++) + { + Jim_ListAppendElement(interp, Jim_GetResult(interp), + Jim_NewStringObj(interp, target_types[x]->name, -1)); + } + return JIM_OK; +} - if (goi.argc == 0) { - Jim_WrongNumArgs(interp, 1, argv, "missing: command ..."); +static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); return JIM_ERR; } + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + struct target *target = all_targets; + while (target) + { + Jim_ListAppendElement(interp, Jim_GetResult(interp), + Jim_NewStringObj(interp, target_name(target), -1)); + target = target->next; + } + return JIM_OK; +} - /* Jim_GetOpt_Debug(&goi); */ - r = Jim_GetOpt_Enum(&goi, target_cmds, &x); - if (r != JIM_OK) { - return r; +static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc < 3) + { + Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, + " [ ...]"); + return JIM_ERR; } + return target_create(&goi); +} - switch (x) { - default: - Jim_Panic(goi.interp,"Why am I here?"); +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; - case TG_CMD_CURRENT: - if (goi.argc != 0) { - Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters"); - return JIM_ERR; - } - Jim_SetResultString(goi.interp, get_current_target(cmd_ctx)->cmd_name, -1); - return JIM_OK; - case TG_CMD_TYPES: - if (goi.argc != 0) { - Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters"); - return JIM_ERR; - } - Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0)); - for (x = 0 ; target_types[x] ; x++) { - Jim_ListAppendElement(goi.interp, - Jim_GetResult(goi.interp), - Jim_NewStringObj(goi.interp, target_types[x]->name, -1)); - } - return JIM_OK; - case TG_CMD_NAMES: - if (goi.argc != 0) { - Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters"); - return JIM_ERR; - } - Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0)); - target = all_targets; - while (target) { - Jim_ListAppendElement(goi.interp, - Jim_GetResult(goi.interp), - Jim_NewStringObj(goi.interp, target->cmd_name, -1)); - target = target->next; - } - return JIM_OK; - case TG_CMD_CREATE: - if (goi.argc < 3) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "?name ... config options ..."); - return JIM_ERR; - } - return target_create(&goi); - break; - case TG_CMD_NUMBER: - /* 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_SetResult_sprintf(goi.interp, "expected: target number ?NUMBER?"); - return JIM_ERR; - } - e = Jim_GetOpt_Wide(&goi, &w); - if (e != JIM_OK) { - return JIM_ERR; - } - for (x = 0, target = all_targets; target; target = target->next, x++) { - if (target->target_number == w) - break; - } - if (target == NULL) { - Jim_SetResult_sprintf(goi.interp, - "Target: number %d does not exist", (int)(w)); - return JIM_ERR; - } - Jim_SetResultString(goi.interp, target->cmd_name, -1); - return JIM_OK; - case TG_CMD_COUNT: - if (goi.argc != 0) { - Jim_WrongNumArgs(goi.interp, 0, goi.argv, ""); - return JIM_ERR; - } - for (x = 0, target = all_targets; target; target = target->next, x++) + } + 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_SetResult(goi.interp, Jim_NewIntObj(goi.interp, x)); + + 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", + .mode = COMMAND_CONFIG, + .handler = handle_target_init_command, + .help = "initialize targets", + }, + { + .name = "create", + /* REVISIT this should be COMMAND_CONFIG ... */ + .mode = COMMAND_ANY, + .jim_handler = jim_target_create, + .usage = "name type '-chain-position' name [options ...]", + .help = "Creates and selects a new target", + }, + { + .name = "current", + .mode = COMMAND_ANY, + .jim_handler = jim_target_current, + .help = "Returns the currently selected target", + }, + { + .name = "types", + .mode = COMMAND_ANY, + .jim_handler = jim_target_types, + .help = "Returns the available target types as " + "a list of strings", + }, + { + .name = "names", + .mode = COMMAND_ANY, + .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)", + }, + COMMAND_REGISTRATION_DONE +}; struct FastLoad { @@ -4638,7 +5038,7 @@ COMMAND_HANDLER(handle_fast_load_image_command) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "Loaded %" PRIu32 " bytes " - "in %fs (%0.3f kb/s)", image_size, + "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); command_print(CMD_CTX, @@ -4686,106 +5086,21 @@ COMMAND_HANDLER(handle_fast_load_command) return retval; } -static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct command_context *context; - struct target *target; - int retval; - - context = Jim_GetAssocData(interp, "context"); - if (context == NULL) { - LOG_ERROR("array2mem: no command context"); - return JIM_ERR; - } - target = get_current_target(context); - if (target == NULL) { - LOG_ERROR("array2mem: no current target"); - return JIM_ERR; - } - - if ((argc < 6) || (argc > 7)) - { - return JIM_ERR; - } - - int cpnum; - uint32_t op1; - uint32_t op2; - uint32_t CRn; - uint32_t CRm; - uint32_t value; - - int e; - long l; - e = Jim_GetLong(interp, argv[1], &l); - if (e != JIM_OK) { - return e; - } - cpnum = l; - - e = Jim_GetLong(interp, argv[2], &l); - if (e != JIM_OK) { - return e; - } - op1 = l; - - e = Jim_GetLong(interp, argv[3], &l); - if (e != JIM_OK) { - return e; - } - CRn = l; - - e = Jim_GetLong(interp, argv[4], &l); - if (e != JIM_OK) { - return e; - } - CRm = l; - - e = Jim_GetLong(interp, argv[5], &l); - if (e != JIM_OK) { - return e; - } - op2 = l; - - value = 0; - - if (argc == 7) - { - e = Jim_GetLong(interp, argv[6], &l); - if (e != JIM_OK) { - return e; - } - value = l; - - retval = target_mcr(target, cpnum, op1, op2, CRn, CRm, value); - if (retval != ERROR_OK) - return JIM_ERR; - } else - { - retval = target_mrc(target, cpnum, op1, op2, CRn, CRm, &value); - if (retval != ERROR_OK) - return JIM_ERR; - - Jim_SetResult(interp, Jim_NewIntObj(interp, value)); - } - - return JIM_OK; -} - static const struct command_registration target_command_handlers[] = { { .name = "targets", - .handler = &handle_targets_command, + .handler = handle_targets_command, .mode = COMMAND_ANY, - .help = "change current command line target (one parameter) " - "or list targets (no parameters)", - .usage = "[]", + .help = "change current default target (one parameter) " + "or prints table of all targets (no parameters)", + .usage = "[target]", }, { .name = "target", .mode = COMMAND_CONFIG, - .jim_handler = &jim_target, .help = "configure target", + + .chain = target_subcommand_handlers, }, COMMAND_REGISTRATION_DONE }; @@ -4795,72 +5110,92 @@ int target_register_commands(struct command_context *cmd_ctx) return register_commands(cmd_ctx, NULL, target_command_handlers); } +static bool target_reset_nag = true; + +bool get_target_reset_nag(void) +{ + return target_reset_nag; +} + +COMMAND_HANDLER(handle_target_reset_nag) +{ + return CALL_COMMAND_HANDLER(handle_command_parse_bool, + &target_reset_nag, "Nag after each reset about options to improve " + "performance"); +} + static const struct command_registration target_exec_command_handlers[] = { { .name = "fast_load_image", - .handler = &handle_fast_load_image_command, + .handler = handle_fast_load_image_command, .mode = COMMAND_ANY, - .help = "Load image into memory, mainly for profiling purposes", - .usage = "
['bin'|'ihex'|'elf'|'s19'] " - "[min_address] [max_length]", + .help = "Load image into server memory for later use by " + "fast_load; primarily for profiling", + .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " + "[min_address [max_length]]", }, { .name = "fast_load", - .handler = &handle_fast_load_command, - .mode = COMMAND_ANY, + .handler = handle_fast_load_command, + .mode = COMMAND_EXEC, .help = "loads active fast load image to current target " "- mainly for profiling purposes", }, { .name = "profile", - .handler = &handle_profile_command, + .handler = handle_profile_command, .mode = COMMAND_EXEC, .help = "profiling samples the CPU PC", }, /** @todo don't register virt2phys() unless target supports it */ { .name = "virt2phys", - .handler = &handle_virt2phys_command, + .handler = handle_virt2phys_command, .mode = COMMAND_ANY, .help = "translate a virtual address into a physical address", + .usage = "virtual_address", }, - { .name = "reg", - .handler = &handle_reg_command, + .handler = handle_reg_command, .mode = COMMAND_EXEC, - .help = "display or set a register", + .help = "display or set a register; with no arguments, " + "displays all registers and their values", + .usage = "[(register_name|register_number) [value]]", }, - { .name = "poll", - .handler = &handle_poll_command, + .handler = handle_poll_command, .mode = COMMAND_EXEC, - .help = "poll target state", + .help = "poll target state; or reconfigure background polling", + .usage = "['on'|'off']", }, { .name = "wait_halt", - .handler = &handle_wait_halt_command, + .handler = handle_wait_halt_command, .mode = COMMAND_EXEC, - .help = "wait for target halt", - .usage = "[time (s)]", + .help = "wait up to the specified number of milliseconds " + "(default 5) for a previously requested halt", + .usage = "[milliseconds]", }, { .name = "halt", - .handler = &handle_halt_command, + .handler = handle_halt_command, .mode = COMMAND_EXEC, - .help = "halt target", + .help = "request target to halt, then wait up to the specified" + "number of milliseconds (default 5) for it to complete", + .usage = "[milliseconds]", }, { .name = "resume", - .handler = &handle_resume_command, + .handler = handle_resume_command, .mode = COMMAND_EXEC, - .help = "resume target", - .usage = "[
]", + .help = "resume target execution from current PC or address", + .usage = "[address]", }, { .name = "reset", - .handler = &handle_reset_command, + .handler = handle_reset_command, .mode = COMMAND_EXEC, .usage = "[run|halt|init]", .help = "Reset all targets into the specified mode." @@ -4868,137 +5203,139 @@ static const struct command_registration target_exec_command_handlers[] = { }, { .name = "soft_reset_halt", - .handler = &handle_soft_reset_halt_command, + .handler = handle_soft_reset_halt_command, .mode = COMMAND_EXEC, .help = "halt the target and do a soft reset", }, { - .name = "step", - .handler = &handle_step_command, + .handler = handle_step_command, .mode = COMMAND_EXEC, - .help = "step one instruction from current PC or [addr]", - .usage = "[
]", + .help = "step one instruction from current PC or address", + .usage = "[address]", }, { - .name = "mdw", - .handler = &handle_md_command, + .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory words", - .usage = "[phys] [count]", + .usage = "['phys'] address [count]", }, { .name = "mdh", - .handler = &handle_md_command, + .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory half-words", - .usage = "[phys] [count]", + .usage = "['phys'] address [count]", }, { .name = "mdb", - .handler = &handle_md_command, + .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory bytes", - .usage = "[phys] [count]", + .usage = "['phys'] address [count]", }, { - .name = "mww", - .handler = &handle_mw_command, + .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory word", - .usage = "[phys] [count]", + .usage = "['phys'] address value [count]", }, { .name = "mwh", - .handler = &handle_mw_command, + .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory half-word", - .usage = "[phys] [count]", + .usage = "['phys'] address value [count]", }, { .name = "mwb", - .handler = &handle_mw_command, + .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory byte", - .usage = "[phys] [count]", + .usage = "['phys'] address value [count]", }, { - .name = "bp", - .handler = &handle_bp_command, + .handler = handle_bp_command, .mode = COMMAND_EXEC, - .help = "list or set breakpoint", - .usage = "[
[hw]]", + .help = "list or set hardware or software breakpoint", + .usage = "[address length ['hw']]", }, { .name = "rbp", - .handler = &handle_rbp_command, + .handler = handle_rbp_command, .mode = COMMAND_EXEC, .help = "remove breakpoint", - .usage = "
", + .usage = "address", }, { - .name = "wp", - .handler = &handle_wp_command, + .handler = handle_wp_command, .mode = COMMAND_EXEC, - .help = "list or set watchpoint", - .usage = "[
[value] [mask]]", + .help = "list (no params) or create watchpoints", + .usage = "[address length [('r'|'w'|'a') value [mask]]]", }, { .name = "rwp", - .handler = &handle_rwp_command, + .handler = handle_rwp_command, .mode = COMMAND_EXEC, .help = "remove watchpoint", - .usage = "
", - + .usage = "address", }, { .name = "load_image", - .handler = &handle_load_image_command, + .handler = handle_load_image_command, .mode = COMMAND_EXEC, - .usage = "
['bin'|'ihex'|'elf'|'s19'] " + .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " "[min_address] [max_length]", }, { .name = "dump_image", - .handler = &handle_dump_image_command, + .handler = handle_dump_image_command, .mode = COMMAND_EXEC, - .usage = "
", + .usage = "filename address size", }, { .name = "verify_image", - .handler = &handle_verify_image_command, + .handler = handle_verify_image_command, .mode = COMMAND_EXEC, - .usage = " [offset] [type]", + .usage = "filename [offset [type]]", }, { .name = "test_image", - .handler = &handle_test_image_command, + .handler = handle_test_image_command, .mode = COMMAND_EXEC, - .usage = " [offset] [type]", + .usage = "filename [offset [type]]", }, { - .name = "ocd_mem2array", + .name = "mem2array", .mode = COMMAND_EXEC, - .jim_handler = &jim_mem2array, - .help = "read memory and return as a TCL array " + .jim_handler = jim_mem2array, + .help = "read 8/16/32 bit memory and return as a TCL array " "for script processing", - .usage = "
", + .usage = "arrayname bitwidth address count", }, { - .name = "ocd_array2mem", + .name = "array2mem", .mode = COMMAND_EXEC, - .jim_handler = &jim_array2mem, + .jim_handler = jim_array2mem, .help = "convert a TCL array to memory locations " - "and write the values", - .usage = "
", + "and write the 8/16/32 bit values", + .usage = "arrayname bitwidth address count", + }, + { + .name = "reset_nag", + .handler = handle_target_reset_nag, + .mode = COMMAND_ANY, + .help = "Nag after each reset about options that could have been " + "enabled to improve performance. ", + .usage = "['enable'|'disable']", }, COMMAND_REGISTRATION_DONE }; -int target_register_user_commands(struct command_context *cmd_ctx) +static int target_register_user_commands(struct command_context *cmd_ctx) { int retval = ERROR_OK; if ((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK)