X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=cc8d500f0ccbc1c889da65c1079072f7c03f56df;hp=d21944860284e70921f06a9f16d313804fd7593e;hb=ab3bdfb2cb7b0c16800195951e4ee549cf8e86a5;hpb=d11c8e3c8e09e0c2c48a75e9e912f756e99a9f67 diff --git a/src/target/target.c b/src/target/target.c index d219448602..cc8d500f0c 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,2008 Øyvind Harboe * + * Copyright (C) 2007-2009 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008, Duane Ellis * @@ -43,55 +43,29 @@ #include "jtag.h" -static int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); - -static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc); -static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); - -static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv); -static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv); -static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv); - -static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv); -static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv); +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); /* targets */ -extern target_type_t arm7tdmi_target; -extern target_type_t arm720t_target; -extern target_type_t arm9tdmi_target; -extern target_type_t arm920t_target; -extern target_type_t arm966e_target; -extern target_type_t arm926ejs_target; -extern target_type_t fa526_target; -extern target_type_t feroceon_target; -extern target_type_t xscale_target; -extern target_type_t cortexm3_target; -extern target_type_t cortexa8_target; -extern target_type_t arm11_target; -extern target_type_t mips_m4k_target; -extern target_type_t avr_target; - -target_type_t *target_types[] = +extern struct target_type arm7tdmi_target; +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 arm926ejs_target; +extern struct target_type fa526_target; +extern struct target_type feroceon_target; +extern struct target_type dragonite_target; +extern struct target_type xscale_target; +extern struct target_type cortexm3_target; +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; + +struct target_type *target_types[] = { &arm7tdmi_target, &arm9tdmi_target, @@ -101,6 +75,7 @@ target_type_t *target_types[] = &arm926ejs_target, &fa526_target, &feroceon_target, + &dragonite_target, &xscale_target, &cortexm3_target, &cortexa8_target, @@ -110,9 +85,9 @@ target_type_t *target_types[] = NULL, }; -target_t *all_targets = NULL; -target_event_callback_t *target_event_callbacks = NULL; -target_timer_callback_t *target_timer_callbacks = NULL; +struct target *all_targets = NULL; +struct target_event_callback *target_event_callbacks = NULL; +struct target_timer_callback *target_timer_callbacks = NULL; const Jim_Nvp nvp_assert[] = { { .name = "assert", NVP_ASSERT }, @@ -155,7 +130,7 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" }, { .value = TARGET_EVENT_OLD_pre_resume , .name = "old-pre_resume" }, - { .value = TARGET_EVENT_EARLY_HALTED, .name = "early-halted" }, + { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" }, { .value = TARGET_EVENT_HALTED, .name = "halted" }, { .value = TARGET_EVENT_RESUMED, .name = "resumed" }, { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" }, @@ -238,7 +213,7 @@ const Jim_Nvp nvp_reset_modes[] = { }; const char * -target_state_name( target_t *t ) +target_state_name( struct target *t ) { const char *cp; cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name; @@ -249,26 +224,10 @@ target_state_name( target_t *t ) return cp; } -static int max_target_number(void) -{ - target_t *t; - int x; - - x = -1; - t = all_targets; - while (t) { - if (x < t->target_number) { - x = (t->target_number) + 1; - } - t = t->next; - } - return x; -} - /* determine the number of the new target */ static int new_target_number(void) { - target_t *t; + struct target *t; int x; /* number is 0 based */ @@ -283,10 +242,8 @@ static int new_target_number(void) return x + 1; } -static int target_continuous_poll = 1; - /* read a uint32_t from a buffer in target memory endianness */ -uint32_t target_buffer_get_u32(target_t *target, const uint8_t *buffer) +uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer) { if (target->endianness == TARGET_LITTLE_ENDIAN) return le_to_h_u32(buffer); @@ -295,7 +252,7 @@ uint32_t target_buffer_get_u32(target_t *target, const uint8_t *buffer) } /* read a uint16_t from a buffer in target memory endianness */ -uint16_t target_buffer_get_u16(target_t *target, const uint8_t *buffer) +uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer) { if (target->endianness == TARGET_LITTLE_ENDIAN) return le_to_h_u16(buffer); @@ -304,13 +261,13 @@ uint16_t target_buffer_get_u16(target_t *target, const uint8_t *buffer) } /* read a uint8_t from a buffer in target memory endianness */ -uint8_t target_buffer_get_u8(target_t *target, const uint8_t *buffer) +uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) { return *buffer & 0x0ff; } /* write a uint32_t to a buffer in target memory endianness */ -void target_buffer_set_u32(target_t *target, uint8_t *buffer, uint32_t value) +void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value) { if (target->endianness == TARGET_LITTLE_ENDIAN) h_u32_to_le(buffer, value); @@ -319,7 +276,7 @@ void target_buffer_set_u32(target_t *target, uint8_t *buffer, uint32_t value) } /* write a uint16_t to a buffer in target memory endianness */ -void target_buffer_set_u16(target_t *target, uint8_t *buffer, uint16_t value) +void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value) { if (target->endianness == TARGET_LITTLE_ENDIAN) h_u16_to_le(buffer, value); @@ -328,15 +285,15 @@ void target_buffer_set_u16(target_t *target, uint8_t *buffer, uint16_t value) } /* write a uint8_t to a buffer in target memory endianness */ -void target_buffer_set_u8(target_t *target, uint8_t *buffer, uint8_t value) +void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value) { *buffer = value; } /* return a pointer to a configured target; id is name or number */ -target_t *get_target(const char *id) +struct target *get_target(const char *id) { - target_t *target; + struct target *target; /* try as tcltarget name */ for (target = all_targets; target; target = target->next) { @@ -346,23 +303,28 @@ target_t *get_target(const char *id) return target; } + /* It's OK to remove this fallback sometime after August 2010 or so */ + /* no match, try as number */ unsigned num; if (parse_uint(id, &num) != ERROR_OK) return NULL; for (target = all_targets; target; target = target->next) { - if (target->target_number == (int)num) + if (target->target_number == (int)num) { + LOG_WARNING("use '%s' as target identifier, not '%u'", + target->cmd_name, num); return target; + } } return NULL; } /* returns a pointer to the n-th configured target */ -static target_t *get_target_by_num(int num) +static struct target *get_target_by_num(int num) { - target_t *target = all_targets; + struct target *target = all_targets; while (target) { if (target->target_number == num) { @@ -374,14 +336,9 @@ static target_t *get_target_by_num(int num) return NULL; } -int get_num_by_target(target_t *query_target) +struct target* get_current_target(struct command_context *cmd_ctx) { - return query_target->target_number; -} - -target_t* get_current_target(command_context_t *cmd_ctx) -{ - target_t *target = get_target_by_num(cmd_ctx->current_target); + struct target *target = get_target_by_num(cmd_ctx->current_target); if (target == NULL) { @@ -392,29 +349,62 @@ target_t* get_current_target(command_context_t *cmd_ctx) return target; } -int target_poll(struct target_s *target) +int target_poll(struct target *target) { + int retval; + /* We can't poll until after examine */ if (!target_was_examined(target)) { /* Fail silently lest we pollute the log */ return ERROR_FAIL; } - return target->type->poll(target); + + retval = target->type->poll(target); + if (retval != ERROR_OK) + return retval; + + if (target->halt_issued) + { + if (target->state == TARGET_HALTED) + { + target->halt_issued = false; + } else + { + long long t = timeval_ms() - target->halt_issued_time; + if (t>1000) + { + target->halt_issued = false; + LOG_INFO("Halt timed out, wake up GDB."); + target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); + } + } + } + + return ERROR_OK; } -int target_halt(struct target_s *target) +int target_halt(struct target *target) { + int retval; /* We can't poll until after examine */ if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } - return target->type->halt(target); + + retval = target->type->halt(target); + if (retval != ERROR_OK) + return retval; + + target->halt_issued = true; + target->halt_issued_time = timeval_ms(); + + return ERROR_OK; } -int target_resume(struct target_s *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) +int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int retval; @@ -435,7 +425,7 @@ int target_resume(struct target_s *target, int current, uint32_t address, int ha return retval; } -int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode) +int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) { char buf[100]; int retval; @@ -450,13 +440,14 @@ int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mo * more predictable, i.e. dr/irscan & pathmove in events will * not have JTAG operations injected into the middle of a sequence. */ - int save_poll = target_continuous_poll; - target_continuous_poll = 0; + bool save_poll = jtag_poll_get_enabled(); + + jtag_poll_set_enabled(false); sprintf(buf, "ocd_process_reset %s", n->name); retval = Jim_Eval(interp, buf); - target_continuous_poll = save_poll; + jtag_poll_set_enabled(save_poll); if (retval != JIM_OK) { Jim_PrintErrorMessage(interp); @@ -469,32 +460,33 @@ int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mo return retval; } -static int default_virt2phys(struct target_s *target, uint32_t virtual, uint32_t *physical) +static int identity_virt2phys(struct target *target, + uint32_t virtual, uint32_t *physical) { *physical = virtual; return ERROR_OK; } -static int default_mmu(struct target_s *target, int *enabled) +static int no_mmu(struct target *target, int *enabled) { *enabled = 0; return ERROR_OK; } -static int default_examine(struct target_s *target) +static int default_examine(struct target *target) { target_set_examined(target); return ERROR_OK; } -int target_examine_one(struct target_s *target) +int target_examine_one(struct target *target) { return target->type->examine(target); } static int jtag_enable_callback(enum jtag_event event, void *priv) { - target_t *target = priv; + struct target *target = priv; if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled) return ERROR_OK; @@ -512,7 +504,7 @@ static int jtag_enable_callback(enum jtag_event event, void *priv) int target_examine(void) { int retval = ERROR_OK; - target_t *target; + struct target *target; for (target = all_targets; target; target = target->next) { @@ -527,12 +519,12 @@ int target_examine(void) } return retval; } -const char *target_get_name(struct target_s *target) +const char *target_get_name(struct target *target) { return target->type->name; } -static int target_write_memory_imp(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { @@ -542,7 +534,7 @@ static int target_write_memory_imp(struct target_s *target, uint32_t address, ui return target->type->write_memory_imp(target, address, size, count, buffer); } -static int target_read_memory_imp(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +static int target_read_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { @@ -552,17 +544,22 @@ static int target_read_memory_imp(struct target_s *target, uint32_t address, uin return target->type->read_memory_imp(target, address, size, count, buffer); } -static int target_soft_reset_halt_imp(struct target_s *target) +static int target_soft_reset_halt_imp(struct target *target) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } + if (!target->type->soft_reset_halt_imp) { + LOG_ERROR("Target %s does not support soft_reset_halt", + target->cmd_name); + return ERROR_FAIL; + } return target->type->soft_reset_halt_imp(target); } -static int target_run_algorithm_imp(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) +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) { if (!target_was_examined(target)) { @@ -572,60 +569,73 @@ static int target_run_algorithm_imp(struct target_s *target, int num_mem_params, 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); } -int target_read_memory(struct target_s *target, +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_write_memory(struct target_s *target, +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); +} + +int target_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return target->type->write_memory(target, address, size, count, buffer); } -int target_bulk_write_memory(struct target_s *target, + +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); +} + +int target_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) { return target->type->bulk_write_memory(target, address, count, buffer); } -int target_add_breakpoint(struct target_s *target, - struct breakpoint_s *breakpoint) +int target_add_breakpoint(struct target *target, + struct breakpoint *breakpoint) { return target->type->add_breakpoint(target, breakpoint); } -int target_remove_breakpoint(struct target_s *target, - struct breakpoint_s *breakpoint) +int target_remove_breakpoint(struct target *target, + struct breakpoint *breakpoint) { return target->type->remove_breakpoint(target, breakpoint); } -int target_add_watchpoint(struct target_s *target, - struct watchpoint_s *watchpoint) +int target_add_watchpoint(struct target *target, + struct watchpoint *watchpoint) { return target->type->add_watchpoint(target, watchpoint); } -int target_remove_watchpoint(struct target_s *target, - struct watchpoint_s *watchpoint) +int target_remove_watchpoint(struct target *target, + struct watchpoint *watchpoint) { return target->type->remove_watchpoint(target, watchpoint); } -int target_get_gdb_reg_list(struct target_s *target, - struct reg_s **reg_list[], int *reg_list_size) +int target_get_gdb_reg_list(struct target *target, + struct reg **reg_list[], int *reg_list_size) { return target->type->get_gdb_reg_list(target, reg_list, reg_list_size); } -int target_step(struct target_s *target, +int target_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { return target->type->step(target, current, address, handle_breakpoints); } -int target_run_algorithm(struct target_s *target, - int num_mem_params, mem_param_t *mem_params, - int num_reg_params, reg_param_t *reg_param, +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) { @@ -635,29 +645,123 @@ int target_run_algorithm(struct target_s *target, } /// @returns @c true if the target has been examined. -bool target_was_examined(struct target_s *target) +bool target_was_examined(struct target *target) { return target->type->examined; } /// Sets the @c examined flag for the given target. -void target_set_examined(struct target_s *target) +void target_set_examined(struct target *target) { target->type->examined = true; } // Reset the @c examined flag for the given target. -void target_reset_examined(struct target_s *target) +void target_reset_examined(struct target *target) { target->type->examined = false; } -int target_init(struct command_context_s *cmd_ctx) + +static int default_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value) { - target_t *target = all_targets; - int retval; + LOG_ERROR("Not implemented: %s", __func__); + return ERROR_FAIL; +} - while (target) +static int default_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value) +{ + 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) +{ + /* basic check */ + if (!target_was_examined(target)) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if ((cpnum <0) || (cpnum > 15)) + { + LOG_ERROR("Illegal co-processor %d", cpnum); + return ERROR_FAIL; + } + + if (op1 > 7) + { + LOG_ERROR("Illegal op1"); + return ERROR_FAIL; + } + + if (op2 > 7) + { + LOG_ERROR("Illegal op2"); + return ERROR_FAIL; + } + + if (CRn > 15) + { + LOG_ERROR("Illegal CRn"); + return ERROR_FAIL; + } + + if (CRm > 15) { + LOG_ERROR("Illegal CRm"); + return ERROR_FAIL; + } + + 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) +{ + 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); +} + +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; + + retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm); + if (retval != ERROR_OK) + 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; +} + +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; +} + +int target_init(struct command_context *cmd_ctx) +{ + 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) { @@ -670,12 +774,38 @@ int target_init(struct command_context_s *cmd_ctx) return retval; } - /* Set up default functions if none are provided by target */ - if (target->type->virt2phys == NULL) + /** + * @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->virt2phys = default_virt2phys; + target->type->mcr = default_mcr; + } else + { + /* FIX! multiple targets will generally register global commands + * multiple times. Only register this one if *one* of the + * targets need the command. Hmm... make it a command on the + * Jim Tcl target object? + */ + register_jim(cmd_ctx, "mcr", jim_mcrmrc, "write coprocessor "); } - target->type->virt2phys = default_virt2phys; + + if (target->type->mrc == NULL) + { + target->type->mrc = default_mrc; + } else + { + register_jim(cmd_ctx, "mrc", jim_mcrmrc, "read coprocessor "); + } + + + /** + * @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 */ @@ -688,11 +818,45 @@ int target_init(struct command_context_s *cmd_ctx) target->type->run_algorithm_imp = target->type->run_algorithm; target->type->run_algorithm = target_run_algorithm_imp; - if (target->type->mmu == NULL) - { - target->type->mmu = default_mmu; + /* 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; } - target = target->next; } if (all_targets) @@ -706,9 +870,9 @@ int target_init(struct command_context_s *cmd_ctx) return ERROR_OK; } -int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv) +int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv) { - target_event_callback_t **callbacks_p = &target_event_callbacks; + struct target_event_callback **callbacks_p = &target_event_callbacks; if (callback == NULL) { @@ -722,7 +886,7 @@ int target_register_event_callback(int (*callback)(struct target_s *target, enum callbacks_p = &((*callbacks_p)->next); } - (*callbacks_p) = malloc(sizeof(target_event_callback_t)); + (*callbacks_p) = malloc(sizeof(struct target_event_callback)); (*callbacks_p)->callback = callback; (*callbacks_p)->priv = priv; (*callbacks_p)->next = NULL; @@ -732,7 +896,7 @@ int target_register_event_callback(int (*callback)(struct target_s *target, enum int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv) { - target_timer_callback_t **callbacks_p = &target_timer_callbacks; + struct target_timer_callback **callbacks_p = &target_timer_callbacks; struct timeval now; if (callback == NULL) @@ -747,7 +911,7 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int callbacks_p = &((*callbacks_p)->next); } - (*callbacks_p) = malloc(sizeof(target_timer_callback_t)); + (*callbacks_p) = malloc(sizeof(struct target_timer_callback)); (*callbacks_p)->callback = callback; (*callbacks_p)->periodic = periodic; (*callbacks_p)->time_ms = time_ms; @@ -768,10 +932,10 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int return ERROR_OK; } -int target_unregister_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv) +int target_unregister_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv) { - target_event_callback_t **p = &target_event_callbacks; - target_event_callback_t *c = target_event_callbacks; + struct target_event_callback **p = &target_event_callbacks; + struct target_event_callback *c = target_event_callbacks; if (callback == NULL) { @@ -780,7 +944,7 @@ int target_unregister_event_callback(int (*callback)(struct target_s *target, en while (c) { - target_event_callback_t *next = c->next; + struct target_event_callback *next = c->next; if ((c->callback == callback) && (c->priv == priv)) { *p = next; @@ -797,8 +961,8 @@ int target_unregister_event_callback(int (*callback)(struct target_s *target, en int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) { - target_timer_callback_t **p = &target_timer_callbacks; - target_timer_callback_t *c = target_timer_callbacks; + struct target_timer_callback **p = &target_timer_callbacks; + struct target_timer_callback *c = target_timer_callbacks; if (callback == NULL) { @@ -807,7 +971,7 @@ int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) while (c) { - target_timer_callback_t *next = c->next; + struct target_timer_callback *next = c->next; if ((c->callback == callback) && (c->priv == priv)) { *p = next; @@ -822,15 +986,15 @@ int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) return ERROR_OK; } -int target_call_event_callbacks(target_t *target, enum target_event event) +int target_call_event_callbacks(struct target *target, enum target_event event) { - target_event_callback_t *callback = target_event_callbacks; - target_event_callback_t *next_callback; + struct target_event_callback *callback = target_event_callbacks; + struct target_event_callback *next_callback; if (event == TARGET_EVENT_HALTED) { /* execute early halted first */ - target_call_event_callbacks(target, TARGET_EVENT_EARLY_HALTED); + target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } LOG_DEBUG("target event %i (%s)", @@ -850,7 +1014,7 @@ int target_call_event_callbacks(target_t *target, enum target_event event) } static int target_timer_callback_periodic_restart( - target_timer_callback_t *cb, struct timeval *now) + struct target_timer_callback *cb, struct timeval *now) { int time_ms = cb->time_ms; cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000; @@ -864,7 +1028,7 @@ static int target_timer_callback_periodic_restart( return ERROR_OK; } -static int target_call_timer_callback(target_timer_callback_t *cb, +static int target_call_timer_callback(struct target_timer_callback *cb, struct timeval *now) { cb->callback(cb->priv); @@ -882,11 +1046,11 @@ static int target_call_timer_callbacks_check_time(int checktime) struct timeval now; gettimeofday(&now, NULL); - target_timer_callback_t *callback = target_timer_callbacks; + struct target_timer_callback *callback = target_timer_callbacks; while (callback) { // cleaning up may unregister and free this callback - target_timer_callback_t *next_callback = callback->next; + struct target_timer_callback *next_callback = callback->next; bool call_it = callback->callback && ((!checktime && callback->periodic) || @@ -918,28 +1082,45 @@ int target_call_timer_callbacks_now(void) return target_call_timer_callbacks_check_time(0); } -int target_alloc_working_area(struct target_s *target, uint32_t size, working_area_t **area) +int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area) { - working_area_t *c = target->working_areas; - working_area_t *new_wa = NULL; + struct working_area *c = target->working_areas; + struct working_area *new_wa = NULL; /* Reevaluate working area address based on MMU state*/ if (target->working_areas == NULL) { int retval; int enabled; + retval = target->type->mmu(target, &enabled); if (retval != ERROR_OK) { return retval; } - if (enabled) - { - target->working_area = target->working_area_virt; - } - else - { - target->working_area = target->working_area_phys; + + if (!enabled) { + if (target->working_area_phys_spec) { + LOG_DEBUG("MMU disabled, using physical " + "address for working memory 0x%08x", + (unsigned)target->working_area_phys); + target->working_area = target->working_area_phys; + } else { + LOG_ERROR("No working memory available. " + "Specify -work-area-phys to target."); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + } else { + if (target->working_area_virt_spec) { + LOG_DEBUG("MMU enabled, using virtual " + "address for working memory 0x%08x", + (unsigned)target->working_area_virt); + target->working_area = target->working_area_virt; + } else { + LOG_ERROR("No working memory available. " + "Specify -work-area-virt to target."); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } } } @@ -964,12 +1145,10 @@ int target_alloc_working_area(struct target_s *target, uint32_t size, working_ar /* if not, allocate a new one */ if (!new_wa) { - working_area_t **p = &target->working_areas; + struct working_area **p = &target->working_areas; uint32_t first_free = target->working_area; uint32_t free_size = target->working_area_size; - LOG_DEBUG("allocating new working area"); - c = target->working_areas; while (c) { @@ -986,7 +1165,9 @@ int target_alloc_working_area(struct target_s *target, uint32_t size, working_ar return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - new_wa = malloc(sizeof(working_area_t)); + LOG_DEBUG("allocated new working area at address 0x%08x", (unsigned)first_free); + + new_wa = malloc(sizeof(struct working_area)); new_wa->next = NULL; new_wa->size = size; new_wa->address = first_free; @@ -1021,7 +1202,7 @@ int target_alloc_working_area(struct target_s *target, uint32_t size, working_ar return ERROR_OK; } -int target_free_working_area_restore(struct target_s *target, working_area_t *area, int restore) +int target_free_working_area_restore(struct target *target, struct working_area *area, int restore) { if (area->free) return ERROR_OK; @@ -1042,7 +1223,7 @@ int target_free_working_area_restore(struct target_s *target, working_area_t *ar return ERROR_OK; } -int target_free_working_area(struct target_s *target, working_area_t *area) +int target_free_working_area(struct target *target, struct working_area *area) { return target_free_working_area_restore(target, area, 1); } @@ -1050,13 +1231,13 @@ int target_free_working_area(struct target_s *target, working_area_t *area) /* free resources and restore memory, if restoring memory fails, * free up resources anyway */ -void target_free_all_working_areas_restore(struct target_s *target, int restore) +void target_free_all_working_areas_restore(struct target *target, int restore) { - working_area_t *c = target->working_areas; + struct working_area *c = target->working_areas; while (c) { - working_area_t *next = c->next; + struct working_area *next = c->next; target_free_working_area_restore(target, c, restore); if (c->backup) @@ -1070,25 +1251,12 @@ void target_free_all_working_areas_restore(struct target_s *target, int restore) target->working_areas = NULL; } -void target_free_all_working_areas(struct target_s *target) +void target_free_all_working_areas(struct target *target) { target_free_all_working_areas_restore(target, 1); } -int target_register_commands(struct command_context_s *cmd_ctx) -{ - - register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, "change the current command line target (one parameter) or lists targets (with no parameter)"); - - - - - register_jim(cmd_ctx, "target", jim_target, "configure target"); - - return ERROR_OK; -} - -int target_arch_state(struct target_s *target) +int target_arch_state(struct target *target) { int retval; if (target == NULL) @@ -1110,7 +1278,7 @@ int target_arch_state(struct target_s *target) * mode respectively, otherwise data is handled as quickly as * possible */ -int target_write_buffer(struct target_s *target, uint32_t address, uint32_t size, uint8_t *buffer) +int target_write_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { int retval; LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", @@ -1192,7 +1360,7 @@ int target_write_buffer(struct target_s *target, uint32_t address, uint32_t size * mode respectively, otherwise data is handled as quickly as * possible */ -int target_read_buffer(struct target_s *target, uint32_t address, uint32_t size, uint8_t *buffer) +int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { int retval; LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", @@ -1251,6 +1419,18 @@ int target_read_buffer(struct target_s *target, uint32_t address, uint32_t size, size -= aligned; } + /*prevent byte access when possible (avoid AHB access limitations in some cases)*/ + if(size >=2) + { + int aligned = size - (size%2); + retval = target_read_memory(target, address, 2, aligned / 2, buffer); + if (retval != ERROR_OK) + return retval; + + buffer += aligned; + address += aligned; + size -= aligned; + } /* handle tail writes of less than 4 bytes */ if (size > 0) { @@ -1261,7 +1441,7 @@ int target_read_buffer(struct target_s *target, uint32_t address, uint32_t size, return ERROR_OK; } -int target_checksum_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t* crc) +int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc) { uint8_t *buffer; int retval; @@ -1306,7 +1486,7 @@ int target_checksum_memory(struct target_s *target, uint32_t address, uint32_t s return retval; } -int target_blank_check_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t* blank) +int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank) { int retval; if (!target_was_examined(target)) @@ -1323,7 +1503,7 @@ int target_blank_check_memory(struct target_s *target, uint32_t address, uint32_ return retval; } -int target_read_u32(struct target_s *target, uint32_t address, uint32_t *value) +int target_read_u32(struct target *target, uint32_t address, uint32_t *value) { uint8_t value_buf[4]; if (!target_was_examined(target)) @@ -1351,7 +1531,7 @@ int target_read_u32(struct target_s *target, uint32_t address, uint32_t *value) return retval; } -int target_read_u16(struct target_s *target, uint32_t address, uint16_t *value) +int target_read_u16(struct target *target, uint32_t address, uint16_t *value) { uint8_t value_buf[2]; if (!target_was_examined(target)) @@ -1379,7 +1559,7 @@ int target_read_u16(struct target_s *target, uint32_t address, uint16_t *value) return retval; } -int target_read_u8(struct target_s *target, uint32_t address, uint8_t *value) +int target_read_u8(struct target *target, uint32_t address, uint8_t *value) { int retval = target_read_memory(target, address, 1, 1, value); if (!target_was_examined(target)) @@ -1404,7 +1584,7 @@ int target_read_u8(struct target_s *target, uint32_t address, uint8_t *value) return retval; } -int target_write_u32(struct target_s *target, uint32_t address, uint32_t value) +int target_write_u32(struct target *target, uint32_t address, uint32_t value) { int retval; uint8_t value_buf[4]; @@ -1427,7 +1607,7 @@ int target_write_u32(struct target_s *target, uint32_t address, uint32_t value) return retval; } -int target_write_u16(struct target_s *target, uint32_t address, uint16_t value) +int target_write_u16(struct target *target, uint32_t address, uint16_t value) { int retval; uint8_t value_buf[2]; @@ -1450,7 +1630,7 @@ int target_write_u16(struct target_s *target, uint32_t address, uint16_t value) return retval; } -int target_write_u8(struct target_s *target, uint32_t address, uint8_t value) +int target_write_u8(struct target *target, uint32_t address, uint8_t value) { int retval; if (!target_was_examined(target)) @@ -1470,71 +1650,9 @@ int target_write_u8(struct target_s *target, uint32_t address, uint8_t value) return retval; } -int target_register_user_commands(struct command_context_s *cmd_ctx) -{ - int retval = ERROR_OK; - - - /* script procedures */ - register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "profiling samples the CPU PC"); - register_jim(cmd_ctx, "ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing
"); - register_jim(cmd_ctx, "ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values
"); - - register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY, - "same args as load_image, image stored in memory - mainly for profiling purposes"); - - register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY, - "loads active fast load image to current target - mainly for profiling purposes"); - - - register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "translate a virtual address into a physical address"); - register_command(cmd_ctx, NULL, "reg", handle_reg_command, COMMAND_EXEC, "display or set a register"); - register_command(cmd_ctx, NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state"); - register_command(cmd_ctx, NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]"); - register_command(cmd_ctx, NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target"); - register_command(cmd_ctx, NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]"); - register_command(cmd_ctx, NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]"); - register_command(cmd_ctx, NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run | halt | init] - default is run"); - register_command(cmd_ctx, NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset"); - - register_command(cmd_ctx, NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words [count]"); - register_command(cmd_ctx, NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words [count]"); - register_command(cmd_ctx, NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes [count]"); - - register_command(cmd_ctx, NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word [count]"); - register_command(cmd_ctx, NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word [count]"); - register_command(cmd_ctx, NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte [count]"); - - register_command(cmd_ctx, NULL, "bp", - handle_bp_command, COMMAND_EXEC, - "list or set breakpoint [
[hw]]"); - register_command(cmd_ctx, NULL, "rbp", - handle_rbp_command, COMMAND_EXEC, - "remove breakpoint
"); - register_command(cmd_ctx, NULL, "wp", - handle_wp_command, COMMAND_EXEC, - "list or set watchpoint " - "[
[value] [mask]]"); - register_command(cmd_ctx, NULL, "rwp", - handle_rwp_command, COMMAND_EXEC, - "remove watchpoint
"); - - register_command(cmd_ctx, NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image
['bin'|'ihex'|'elf'|'s19'] [min_address] [max_length]"); - register_command(cmd_ctx, NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image
"); - register_command(cmd_ctx, NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image [offset] [type]"); - register_command(cmd_ctx, NULL, "test_image", handle_test_image_command, COMMAND_EXEC, "test_image [offset] [type]"); - - if ((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK) - return retval; - if ((retval = trace_register_commands(cmd_ctx)) != ERROR_OK) - return retval; - - return retval; -} - -static int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_targets_command) { - target_t *target = all_targets; + struct target *target = all_targets; if (argc == 1) { @@ -1655,6 +1773,15 @@ 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; + } +} + /* process target state changes */ int handle_target(void *priv) { @@ -1673,6 +1800,7 @@ int handle_target(void *priv) int did_something = 0; if (runSrstAsserted) { + target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); Jim_Eval(interp, "srst_asserted"); did_something = 1; } @@ -1683,6 +1811,7 @@ int handle_target(void *priv) } if (runPowerDropout) { + target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); Jim_Eval(interp, "power_dropout"); did_something = 1; } @@ -1711,8 +1840,8 @@ int handle_target(void *priv) /* Poll targets for state changes unless that's globally disabled. * Skip targets that are currently disabled. */ - for (target_t *target = all_targets; - target_continuous_poll && target; + for (struct target *target = all_targets; + is_jtag_poll_safe() && target; target = target->next) { if (!target->tap->enabled) @@ -1723,17 +1852,20 @@ int handle_target(void *priv) { /* polling may fail silently until the target has been examined */ if ((retval = target_poll(target)) != ERROR_OK) + { + target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); return retval; + } } } return retval; } -static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_reg_command) { - target_t *target; - reg_t *reg = NULL; + struct target *target; + struct reg *reg = NULL; int count = 0; char *value; @@ -1744,13 +1876,15 @@ static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char /* list all available registers for the current target */ if (argc == 0) { - reg_cache_t *cache = target->reg_cache; + struct reg_cache *cache = target->reg_cache; count = 0; while (cache) { int i; + command_print(cmd_ctx, "===== %s", cache->name); + for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) @@ -1783,11 +1917,9 @@ static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char if ((args[0][0] >= '0') && (args[0][0] <= '9')) { unsigned num; - int retval = parse_uint(args[0], &num); - if (ERROR_OK != retval) - return ERROR_COMMAND_SYNTAX_ERROR; + COMMAND_PARSE_NUMBER(uint, args[0], num); - reg_cache_t *cache = target->reg_cache; + struct reg_cache *cache = target->reg_cache; count = 0; while (cache) { @@ -1829,7 +1961,7 @@ static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char if (reg->valid == 0) { - reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type); + struct reg_arch_type *arch_type = register_get_arch_type(reg->arch_type); arch_type->get(reg); } value = buf_to_str(reg->value, reg->size, 16); @@ -1844,7 +1976,7 @@ static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char uint8_t *buf = malloc(CEIL(reg->size, 8)); str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0); - reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type); + struct reg_arch_type *arch_type = register_get_arch_type(reg->arch_type); arch_type->set(reg, buf); value = buf_to_str(reg->value, reg->size, 16); @@ -1861,15 +1993,15 @@ static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char return ERROR_OK; } -static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_poll_command) { int retval = ERROR_OK; - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (argc == 0) { command_print(cmd_ctx, "background polling: %s", - target_continuous_poll ? "on" : "off"); + jtag_poll_get_enabled() ? "on" : "off"); command_print(cmd_ctx, "TAP: %s (%s)", target->tap->dotted_name, target->tap->enabled ? "enabled" : "disabled"); @@ -1885,11 +2017,11 @@ static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, cha { if (strcmp(args[0], "on") == 0) { - target_continuous_poll = 1; + jtag_poll_set_enabled(true); } else if (strcmp(args[0], "off") == 0) { - target_continuous_poll = 0; + jtag_poll_set_enabled(false); } else { @@ -1903,7 +2035,7 @@ static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, cha return retval; } -static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_wait_halt_command) { if (argc > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -1914,14 +2046,14 @@ static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd int retval = parse_uint(args[0], &ms); if (ERROR_OK != retval) { - command_print(cmd_ctx, "usage: %s [seconds]", cmd); + command_print(cmd_ctx, "usage: %s [seconds]", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } // convert seconds (given) to milliseconds (needed) ms *= 1000; } - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target_wait_state(target, TARGET_HALTED, ms); } @@ -1931,7 +2063,7 @@ static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd * * After 500ms, keep_alive() is invoked */ -int target_wait_state(target_t *target, enum target_state state, int ms) +int target_wait_state(struct target *target, enum target_state state, int ms) { int retval; long long then = 0, cur; @@ -1970,11 +2102,11 @@ int target_wait_state(target_t *target, enum target_state state, int ms) return ERROR_OK; } -static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_halt_command) { LOG_DEBUG("-"); - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); int retval = target_halt(target); if (ERROR_OK != retval) return retval; @@ -1989,12 +2121,12 @@ static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, cha return ERROR_OK; } - return handle_wait_halt_command(cmd_ctx, cmd, args, argc); + return CALL_COMMAND_HANDLER(handle_wait_halt_command); } -static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_soft_reset_halt_command) { - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); LOG_USER("requesting target halt and executing a soft reset"); @@ -2003,7 +2135,7 @@ static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, cha return ERROR_OK; } -static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_reset_command) { if (argc > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -2024,13 +2156,13 @@ static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, ch } -static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_resume_command) { int current = 1; if (argc > 1) return ERROR_COMMAND_SYNTAX_ERROR; - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); target_handle_event(target, TARGET_EVENT_OLD_pre_resume); /* with no args, resume from current pc, addr = 0, @@ -2039,16 +2171,14 @@ static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, c uint32_t addr = 0; if (argc == 1) { - int retval = parse_u32(args[0], &addr); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[0], addr); current = 0; } return target_resume(target, current, addr, 1, 0); } -static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_step_command) { if (argc > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -2062,19 +2192,17 @@ static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, cha int current_pc = 1; if (argc == 1) { - int retval = parse_u32(args[0], &addr); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[0], addr); current_pc = 0; } - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target->type->step(target, current_pc, addr, 1); } -static void handle_md_output(struct command_context_s *cmd_ctx, - struct target_s *target, uint32_t address, unsigned size, +static void handle_md_output(struct command_context *cmd_ctx, + struct target *target, uint32_t address, unsigned size, unsigned count, const uint8_t *buffer) { const unsigned line_bytecnt = 32; @@ -2122,37 +2250,47 @@ static void handle_md_output(struct command_context_s *cmd_ctx, } } -static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_md_command) { if (argc < 1) return ERROR_COMMAND_SYNTAX_ERROR; unsigned size = 0; - switch (cmd[2]) { + switch (CMD_NAME[2]) { case 'w': size = 4; break; case 'h': size = 2; break; case 'b': size = 1; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } + bool physical=strcmp(args[0], "phys")==0; + int (*fn)(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + if (physical) + { + argc--; + args++; + fn=target_read_phys_memory; + } else + { + fn=target_read_memory; + } + if ((argc < 1) || (argc > 2)) + { + return ERROR_COMMAND_SYNTAX_ERROR; + } + uint32_t address; - int retval = parse_u32(args[0], &address); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[0], address); unsigned count = 1; if (argc == 2) - { - retval = parse_uint(args[1], &count); - if (ERROR_OK != retval) - return retval; - } + COMMAND_PARSE_NUMBER(uint, args[1], count); uint8_t *buffer = calloc(count, size); - target_t *target = get_current_target(cmd_ctx); - retval = target_read_memory(target, - address, size, count, buffer); + struct target *target = get_current_target(cmd_ctx); + int retval = fn(target, address, size, count, buffer); if (ERROR_OK == retval) handle_md_output(cmd_ctx, target, address, size, count, buffer); @@ -2161,33 +2299,41 @@ static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char return retval; } -static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_mw_command) { - if ((argc < 2) || (argc > 3)) + if (argc < 2) + { + return ERROR_COMMAND_SYNTAX_ERROR; + } + bool physical=strcmp(args[0], "phys")==0; + int (*fn)(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + if (physical) + { + argc--; + args++; + fn=target_write_phys_memory; + } else + { + fn=target_write_memory; + } + if ((argc < 2) || (argc > 3)) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t address; - int retval = parse_u32(args[0], &address); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[0], address); uint32_t value; - retval = parse_u32(args[1], &value); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[1], value); unsigned count = 1; if (argc == 3) - { - retval = parse_uint(args[2], &count); - if (ERROR_OK != retval) - return retval; - } + COMMAND_PARSE_NUMBER(uint, args[2], count); - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); unsigned wordsize; uint8_t value_buf[4]; - switch (cmd[2]) + switch (CMD_NAME[2]) { case 'w': wordsize = 4; @@ -2206,7 +2352,7 @@ static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char } for (unsigned i = 0; i < count; i++) { - retval = target_write_memory(target, + int retval = fn(target, address + i * wordsize, wordsize, 1, value_buf); if (ERROR_OK != retval) return retval; @@ -2217,8 +2363,8 @@ static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char } -static int parse_load_image_command_args(char **args, int argc, - image_t *image, uint32_t *min_address, uint32_t *max_address) +static COMMAND_HELPER(parse_load_image_command_args, struct image *image, + uint32_t *min_address, uint32_t *max_address) { if (argc < 1 || argc > 5) return ERROR_COMMAND_SYNTAX_ERROR; @@ -2228,9 +2374,7 @@ static int parse_load_image_command_args(char **args, int argc, if (argc >= 2) { uint32_t addr; - int retval = parse_u32(args[1], &addr); - if (ERROR_OK != retval) - return ERROR_COMMAND_SYNTAX_ERROR; + COMMAND_PARSE_NUMBER(u32, args[1], addr); image->base_address = addr; image->base_address_set = 1; } @@ -2241,15 +2385,11 @@ static int parse_load_image_command_args(char **args, int argc, if (argc >= 4) { - int retval = parse_u32(args[3], min_address); - if (ERROR_OK != retval) - return ERROR_COMMAND_SYNTAX_ERROR; + COMMAND_PARSE_NUMBER(u32, args[3], *min_address); } if (argc == 5) { - int retval = parse_u32(args[4], max_address); - if (ERROR_OK != retval) - return ERROR_COMMAND_SYNTAX_ERROR; + COMMAND_PARSE_NUMBER(u32, args[4], *max_address); // use size (given) to find max (required) *max_address += *min_address; } @@ -2260,7 +2400,7 @@ static int parse_load_image_command_args(char **args, int argc, return ERROR_OK; } -static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_load_image_command) { uint8_t *buffer; uint32_t buf_cnt; @@ -2268,20 +2408,17 @@ static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cm uint32_t min_address = 0; uint32_t max_address = 0xffffffff; int i; - int retvaltemp; + struct image image; - image_t image; - - duration_t duration; - char *duration_text; - - int retval = parse_load_image_command_args(args, argc, + int retval = CALL_COMMAND_HANDLER(parse_load_image_command_args, &image, &min_address, &max_address); if (ERROR_OK != retval) return retval; - target_t *target = get_current_target(cmd_ctx); - duration_start_measure(&duration); + struct target *target = get_current_target(cmd_ctx); + + struct duration bench; + duration_start(&bench); if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK) { @@ -2333,7 +2470,7 @@ static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cm break; } image_size += length; - command_print(cmd_ctx, "%u byte written at address 0x%8.8" PRIx32 "", + command_print(cmd_ctx, "%u bytes written at address 0x%8.8" PRIx32 "", (unsigned int)length, image.sections[i].base_address + offset); } @@ -2341,37 +2478,28 @@ static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cm free(buffer); } - if ((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK) + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - image_close(&image); - return retvaltemp; + command_print(cmd_ctx, "downloaded %" PRIu32 " bytes " + "in %fs (%0.3f kb/s)", image_size, + duration_elapsed(&bench), duration_kbps(&bench, image_size)); } - if (retval == ERROR_OK) - { - command_print(cmd_ctx, "downloaded %u byte in %s", - (unsigned int)image_size, - duration_text); - } - free(duration_text); - image_close(&image); return retval; } -static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_dump_image_command) { - fileio_t fileio; + struct fileio fileio; uint8_t buffer[560]; int retvaltemp; - duration_t duration; - char *duration_text; - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (argc != 3) { @@ -2380,27 +2508,23 @@ static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cm } uint32_t address; - int retval = parse_u32(args[1], &address); - if (ERROR_OK != retval) - return retval; - + COMMAND_PARSE_NUMBER(u32, args[1], address); uint32_t size; - retval = parse_u32(args[2], &size); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[2], size); if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) { return ERROR_OK; } - duration_start_measure(&duration); + struct duration bench; + duration_start(&bench); + int retval = ERROR_OK; while (size > 0) { uint32_t size_written; uint32_t this_run_size = (size > 560) ? 560 : size; - retval = target_read_buffer(target, address, this_run_size, buffer); if (retval != ERROR_OK) { @@ -2420,35 +2544,29 @@ static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cm if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK) return retvaltemp; - if ((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK) - return retvaltemp; - - if (retval == ERROR_OK) + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(cmd_ctx, "dumped %lld byte in %s", - fileio.size, duration_text); - free(duration_text); + command_print(cmd_ctx, + "dumped %lld bytes in %fs (%0.3f kb/s)", fileio.size, + duration_elapsed(&bench), duration_kbps(&bench, fileio.size)); } return retval; } -static int handle_verify_image_command_internal(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, int verify) +static COMMAND_HELPER(handle_verify_image_command_internal, int verify) { uint8_t *buffer; uint32_t buf_cnt; uint32_t image_size; int i; - int retval, retvaltemp; + int retval; uint32_t checksum = 0; uint32_t mem_checksum = 0; - image_t image; + struct image image; - duration_t duration; - char *duration_text; - - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (argc < 1) { @@ -2461,14 +2579,13 @@ static int handle_verify_image_command_internal(struct command_context_s *cmd_ct return ERROR_FAIL; } - duration_start_measure(&duration); + struct duration bench; + duration_start(&bench); if (argc >= 2) { uint32_t addr; - retval = parse_u32(args[1], &addr); - if (ERROR_OK != retval) - return ERROR_COMMAND_SYNTAX_ERROR; + COMMAND_PARSE_NUMBER(u32, args[1], addr); image.base_address = addr; image.base_address_set = 1; } @@ -2570,40 +2687,32 @@ static int handle_verify_image_command_internal(struct command_context_s *cmd_ct image_size += buf_cnt; } done: - - if ((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK) - { - image_close(&image); - return retvaltemp; - } - - if (retval == ERROR_OK) + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(cmd_ctx, "verified %u bytes in %s", - (unsigned int)image_size, - duration_text); + command_print(cmd_ctx, "verified %" PRIu32 " bytes " + "in %fs (%0.3f kb/s)", image_size, + duration_elapsed(&bench), duration_kbps(&bench, image_size)); } - free(duration_text); image_close(&image); return retval; } -static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_verify_image_command) { - return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 1); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1); } -static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_test_image_command) { - return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 0); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0); } -static int handle_bp_command_list(struct command_context_s *cmd_ctx) +static int handle_bp_command_list(struct command_context *cmd_ctx) { - target_t *target = get_current_target(cmd_ctx); - breakpoint_t *breakpoint = target->breakpoints; + struct target *target = get_current_target(cmd_ctx); + struct breakpoint *breakpoint = target->breakpoints; while (breakpoint) { if (breakpoint->type == BKPT_SOFT) @@ -2628,10 +2737,10 @@ static int handle_bp_command_list(struct command_context_s *cmd_ctx) return ERROR_OK; } -static int handle_bp_command_set(struct command_context_s *cmd_ctx, +static int handle_bp_command_set(struct command_context *cmd_ctx, uint32_t addr, uint32_t length, int hw) { - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); int retval = breakpoint_add(target, addr, length, hw); if (ERROR_OK == retval) command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); @@ -2640,8 +2749,7 @@ static int handle_bp_command_set(struct command_context_s *cmd_ctx, return retval; } -static int handle_bp_command(struct command_context_s *cmd_ctx, - char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_bp_command) { if (argc == 0) return handle_bp_command_list(cmd_ctx); @@ -2653,14 +2761,9 @@ static int handle_bp_command(struct command_context_s *cmd_ctx, } uint32_t addr; - int retval = parse_u32(args[0], &addr); - if (ERROR_OK != retval) - return retval; - + COMMAND_PARSE_NUMBER(u32, args[0], addr); uint32_t length; - retval = parse_u32(args[1], &length); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[1], length); int hw = BKPT_SOFT; if (argc == 3) @@ -2674,39 +2777,39 @@ static int handle_bp_command(struct command_context_s *cmd_ctx, return handle_bp_command_set(cmd_ctx, addr, length, hw); } -static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_rbp_command) { if (argc != 1) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t addr; - int retval = parse_u32(args[0], &addr); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[0], addr); - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); breakpoint_remove(target, addr); return ERROR_OK; } -static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_wp_command) { - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (argc == 0) { - watchpoint_t *watchpoint = target->watchpoints; + struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { - command_print(cmd_ctx, - "address: 0x%8.8" PRIx32 ", len: 0x%8.8x, r/w/a: %i, value: 0x%8.8" PRIx32 ", mask: 0x%8.8" PRIx32 "", - watchpoint->address, - watchpoint->length, - (int)(watchpoint->rw), - watchpoint->value, - watchpoint->mask); + command_print(cmd_ctx, "address: 0x%8.8" PRIx32 + ", len: 0x%8.8" PRIx32 + ", r/w/a: %i, value: 0x%8.8" PRIx32 + ", mask: 0x%8.8" PRIx32, + watchpoint->address, + watchpoint->length, + (int)watchpoint->rw, + watchpoint->value, + watchpoint->mask); watchpoint = watchpoint->next; } return ERROR_OK; @@ -2717,19 +2820,14 @@ static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char uint32_t length = 0; uint32_t data_value = 0x0; uint32_t data_mask = 0xffffffff; - int retval; switch (argc) { case 5: - retval = parse_u32(args[4], &data_mask); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[4], data_mask); // fall through case 4: - retval = parse_u32(args[3], &data_value); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[3], data_value); // fall through case 3: switch (args[2][0]) @@ -2749,20 +2847,17 @@ static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char } // fall through case 2: - retval = parse_u32(args[1], &length); - if (ERROR_OK != retval) - return retval; - retval = parse_u32(args[0], &addr); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[1], length); + COMMAND_PARSE_NUMBER(u32, args[0], addr); break; default: - command_print(cmd_ctx, "usage: wp
[r/w/a] [value] [mask]"); + command_print(cmd_ctx, "usage: wp [address length " + "[(r|w|a) [value [mask]]]]"); return ERROR_COMMAND_SYNTAX_ERROR; } - retval = watchpoint_add(target, addr, length, type, + int retval = watchpoint_add(target, addr, length, type, data_value, data_mask); if (ERROR_OK != retval) LOG_ERROR("Failure setting watchpoints"); @@ -2770,17 +2865,15 @@ static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char return retval; } -static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_rwp_command) { if (argc != 1) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t addr; - int retval = parse_u32(args[0], &addr); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[0], addr); - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); watchpoint_remove(target, addr); return ERROR_OK; @@ -2793,20 +2886,17 @@ static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char * The low-level target implementation must have logged a detailed error * which is forwarded to telnet/GDB session. */ -static int handle_virt2phys_command(command_context_t *cmd_ctx, - char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_virt2phys_command) { if (argc != 1) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t va; - int retval = parse_u32(args[0], &va); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(u32, args[0], va); uint32_t pa; - target_t *target = get_current_target(cmd_ctx); - retval = target->type->virt2phys(target, va, &pa); + struct target *target = get_current_target(cmd_ctx); + int retval = target->type->virt2phys(target, va, &pa); if (retval == ERROR_OK) command_print(cmd_ctx, "Physical address 0x%08" PRIx32 "", pa); @@ -2837,7 +2927,7 @@ static void writeString(FILE *f, char *s) } /* Dump a gmon.out histogram file. */ -static void writeGmon(uint32_t *samples, uint32_t sampleNum, char *filename) +static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filename) { uint32_t i; FILE *f = fopen(filename, "w"); @@ -2930,9 +3020,9 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, char *filename) } /* profiling samples the CPU PC as quickly as OpenOCD is able, which will be used as a random sampling of PC */ -static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_profile_command) { - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); struct timeval timeout, now; gettimeofday(&timeout, NULL); @@ -2941,9 +3031,7 @@ static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, return ERROR_COMMAND_SYNTAX_ERROR; } unsigned offset; - int retval = parse_uint(args[0], &offset); - if (ERROR_OK != retval) - return retval; + COMMAND_PARSE_NUMBER(uint, args[0], offset); timeval_add_time(&timeout, offset, 0); @@ -2956,10 +3044,11 @@ static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, int numSamples = 0; /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */ - reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1); + struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); for (;;) { + int retval; target_poll(target); if (target->state == TARGET_HALTED) { @@ -3045,8 +3134,8 @@ static int new_int_array_element(Jim_Interp * interp, const char *varname, int i static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - command_context_t *context; - target_t *target; + struct command_context *context; + struct target *target; context = Jim_GetAssocData(interp, "context"); if (context == NULL) @@ -3064,7 +3153,7 @@ static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return target_mem2array(interp, target, argc-1, argv + 1); } -static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv) +static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) { long l; uint32_t width; @@ -3234,8 +3323,8 @@ static int get_int_array_element(Jim_Interp * interp, const char *varname, int i static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - command_context_t *context; - target_t *target; + struct command_context *context; + struct target *target; context = Jim_GetAssocData(interp, "context"); if (context == NULL) { @@ -3250,8 +3339,7 @@ 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, target_t *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; @@ -3390,7 +3478,7 @@ static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_ void target_all_handle_event(enum target_event e) { - target_t *target; + struct target *target; LOG_DEBUG("**all*targets: event: %d, %s", (int)e, @@ -3403,17 +3491,16 @@ void target_all_handle_event(enum target_event e) } } -void target_handle_event(target_t *target, enum target_event e) -{ - target_event_action_t *teap; - int done; - teap = target->event_action; +/* FIX? should we propagate errors here rather than printing them + * and continuing? + */ +void target_handle_event(struct target *target, enum target_event e) +{ + struct target_event_action *teap; - done = 0; - while (teap) { + for (teap = target->event_action; teap != NULL; teap = teap->next) { if (teap->event == e) { - done = 1; LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s", target->target_number, target->cmd_name, @@ -3426,12 +3513,6 @@ void target_handle_event(target_t *target, enum target_event e) Jim_PrintErrorMessage(interp); } } - teap = teap->next; - } - if (!done) { - LOG_DEBUG("event: %d %s - no action", - e, - Jim_Nvp_value2name_simple(nvp_target_event, e)->name); } } @@ -3461,7 +3542,7 @@ static Jim_Nvp nvp_config_opts[] = { { .name = NULL, .value = -1 } }; -static int target_configure(Jim_GetOptInfo *goi, target_t *target) +static int target_configure(Jim_GetOptInfo *goi, struct target *target) { Jim_Nvp *n; Jim_Obj *o; @@ -3534,7 +3615,7 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target) } { - target_event_action_t *teap; + struct target_event_action *teap; teap = target->event_action; /* replace existing? */ @@ -3546,9 +3627,11 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target) } if (goi->isconfigure) { + bool replace = true; if (teap == NULL) { /* create new */ teap = calloc(1, sizeof(*teap)); + replace = false; } teap->event = n->value; Jim_GetOpt_Obj(goi, &o); @@ -3568,9 +3651,12 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target) */ Jim_IncrRefCount(teap->body); - /* add to head of event list */ - teap->next = target->event_action; - target->event_action = teap; + if (!replace) + { + /* add to head of event list */ + teap->next = target->event_action; + target->event_action = teap; + } Jim_SetEmptyResult(goi->interp); } else { /* get */ @@ -3592,6 +3678,7 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target) return e; } target->working_area_virt = w; + target->working_area_virt_spec = true; } else { if (goi->argc != 0) { goto no_params; @@ -3609,6 +3696,7 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target) return e; } target->working_area_phys = w; + target->working_area_phys_spec = true; } else { if (goi->argc != 0) { goto no_params; @@ -3699,7 +3787,7 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target) case TCFG_CHAIN_POSITION: if (goi->isconfigure) { Jim_Obj *o; - jtag_tap_t *tap; + struct jtag_tap *tap; target_free_all_working_areas(target); e = Jim_GetOpt_Obj(goi, &o); if (e != JIM_OK) { @@ -3735,8 +3823,8 @@ static int tcl_target_func(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int x,y,z; uint8_t target_buf[32]; Jim_Nvp *n; - target_t *target; - struct command_context_s *cmd_ctx; + struct target *target; + struct command_context *cmd_ctx; int e; enum { @@ -4020,7 +4108,8 @@ static int tcl_target_func(Jim_Interp *interp, int argc, Jim_Obj *const *argv) break; case TS_CMD_RESET: if (goi.argc != 2) { - Jim_WrongNumArgs(interp, 2, argv, "t | f|assert | deassert BOOL"); + Jim_WrongNumArgs(interp, 2, argv, + "([tT]|[fF]|assert|deassert) BOOL"); return JIM_ERR; } e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n); @@ -4035,6 +4124,13 @@ static int tcl_target_func(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } 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. */ @@ -4042,11 +4138,11 @@ static int tcl_target_func(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* do the assert */ if (n->value == NVP_ASSERT) { - target->type->assert_reset(target); + e = target->type->assert_reset(target); } else { - target->type->deassert_reset(target); + e = target->type->deassert_reset(target); } - return JIM_OK; + return (e == ERROR_OK) ? JIM_OK : JIM_ERR; case TS_CMD_HALT: if (goi.argc) { Jim_WrongNumArgs(goi.interp, 0, argv, "halt [no parameters]"); @@ -4054,8 +4150,8 @@ static int tcl_target_func(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } if (!target->tap->enabled) goto err_tap_disabled; - target->type->halt(target); - return JIM_OK; + e = target->type->halt(target); + return (e == ERROR_OK) ? JIM_OK : JIM_ERR; case TS_CMD_WAITSTATE: /* params: statename timeoutmsecs */ if (goi.argc != 2) { @@ -4089,7 +4185,7 @@ static int tcl_target_func(Jim_Interp *interp, int argc, Jim_Obj *const *argv) * scripts/programs should use 'name cget -event NAME' */ { - target_event_action_t *teap; + struct target_event_action *teap; teap = target->event_action; command_print(cmd_ctx, "Event actions for target (%d) %s\n", target->target_number, @@ -4143,8 +4239,8 @@ static int target_create(Jim_GetOptInfo *goi) char *cp2; int e; int x; - target_t *target; - struct command_context_s *cmd_ctx; + struct target *target; + struct command_context *cmd_ctx; cmd_ctx = Jim_GetAssocData(goi->interp, "context"); if (goi->argc < 3) { @@ -4191,14 +4287,14 @@ static int target_create(Jim_GetOptInfo *goi) } /* Create it */ - target = calloc(1,sizeof(target_t)); + target = calloc(1,sizeof(struct target)); /* set target number */ target->target_number = new_target_number(); /* allocate memory for each unique target type */ - target->type = (target_type_t*)calloc(1,sizeof(target_type_t)); + target->type = (struct target_type*)calloc(1,sizeof(struct target_type)); - memcpy(target->type, target_types[x], sizeof(target_type_t)); + memcpy(target->type, target_types[x], sizeof(struct target_type)); /* will be set by "-endian" */ target->endianness = TARGET_ENDIAN_UNKNOWN; @@ -4218,8 +4314,10 @@ static int target_create(Jim_GetOptInfo *goi) target->display = 1; + target->halt_issued = false; + /* initialize trace information */ - target->trace_info = malloc(sizeof(trace_t)); + target->trace_info = malloc(sizeof(struct trace)); target->trace_info->num_trace_points = 0; target->trace_info->trace_points_size = 0; target->trace_info->trace_points = NULL; @@ -4268,7 +4366,7 @@ static int target_create(Jim_GetOptInfo *goi) /* append to end of list */ { - target_t **tpp; + struct target **tpp; tpp = &(all_targets); while (*tpp) { tpp = &((*tpp)->next); @@ -4294,8 +4392,8 @@ static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int x,r,e; jim_wide w; - struct command_context_s *cmd_ctx; - target_t *target; + struct command_context *cmd_ctx; + struct target *target; Jim_GetOptInfo goi; enum tcmd { /* TG = target generic */ @@ -4375,6 +4473,8 @@ static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 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; @@ -4383,23 +4483,25 @@ static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (e != JIM_OK) { return JIM_ERR; } - { - target_t *t; - t = get_target_by_num(w); - if (t == NULL) { - Jim_SetResult_sprintf(goi.interp,"Target: number %d does not exist", (int)(w)); - return JIM_ERR; - } - Jim_SetResultString(goi.interp, t->cmd_name, -1); - return JIM_OK; + 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; } - Jim_SetResult(goi.interp, - Jim_NewIntObj(goi.interp, max_target_number())); + for (x = 0, target = all_targets; target; target = target->next, x++) + continue; + Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, x)); return JIM_OK; } @@ -4436,7 +4538,7 @@ static void free_fastload(void) -static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_fast_load_image_command) { uint8_t *buffer; uint32_t buf_cnt; @@ -4445,17 +4547,15 @@ static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, cha uint32_t max_address = 0xffffffff; int i; - image_t image; + struct image image; - duration_t duration; - char *duration_text; - - int retval = parse_load_image_command_args(args, argc, + int retval = CALL_COMMAND_HANDLER(parse_load_image_command_args, &image, &min_address, &max_address); if (ERROR_OK != retval) return retval; - duration_start_measure(&duration); + struct duration bench; + duration_start(&bench); if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK) { @@ -4520,7 +4620,7 @@ static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, cha fastload[i].length = length; image_size += length; - command_print(cmd_ctx, "%u byte written at address 0x%8.8x", + command_print(cmd_ctx, "%u bytes written at address 0x%8.8x", (unsigned int)length, ((unsigned int)(image.sections[i].base_address + offset))); } @@ -4528,13 +4628,16 @@ static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, cha free(buffer); } - duration_stop_measure(&duration, &duration_text); - if (retval == ERROR_OK) + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(cmd_ctx, "Loaded %u bytes in %s", (unsigned int)image_size, duration_text); - command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so."); + command_print(cmd_ctx, "Loaded %" PRIu32 " bytes " + "in %fs (%0.3f kb/s)", image_size, + duration_elapsed(&bench), duration_kbps(&bench, image_size)); + + command_print(cmd_ctx, + "WARNING: image has not been loaded to target!" + "You can issue a 'fast_load' to finish loading."); } - free(duration_text); image_close(&image); @@ -4546,7 +4649,7 @@ static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, cha return retval; } -static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_fast_load_command) { if (argc > 0) return ERROR_COMMAND_SYNTAX_ERROR; @@ -4561,7 +4664,7 @@ static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd int retval = ERROR_OK; for (i = 0; i < fastload_num;i++) { - target_t *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); command_print(cmd_ctx, "Write to 0x%08x, length 0x%08x", (unsigned int)(fastload[i].address), (unsigned int)(fastload[i].length)); @@ -4576,10 +4679,216 @@ static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd return retval; } +static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct command_context *context; + struct target *target; + int retval; -/* - * Local Variables: - * c-basic-offset: 4 - * tab-width: 4 - * End: - */ + 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; +} + +int target_register_commands(struct command_context *cmd_ctx) +{ + + register_command(cmd_ctx, NULL, "targets", + handle_targets_command, COMMAND_EXEC, + "change current command line target (one parameter) " + "or list targets (no parameters)"); + + register_jim(cmd_ctx, "target", jim_target, "configure target"); + + return ERROR_OK; +} + +int target_register_user_commands(struct command_context *cmd_ctx) +{ + int retval = ERROR_OK; + if ((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK) + return retval; + + if ((retval = trace_register_commands(cmd_ctx)) != ERROR_OK) + return retval; + + register_command(cmd_ctx, NULL, "profile", + handle_profile_command, COMMAND_EXEC, + "profiling samples the CPU PC"); + + register_jim(cmd_ctx, "ocd_mem2array", jim_mem2array, + "read memory and return as a TCL array for script processing " + "
"); + + register_jim(cmd_ctx, "ocd_array2mem", jim_array2mem, + "convert a TCL array to memory locations and write the values " + "
"); + + register_command(cmd_ctx, NULL, "fast_load_image", + handle_fast_load_image_command, COMMAND_ANY, + "same args as load_image, image stored in memory " + "- mainly for profiling purposes"); + + register_command(cmd_ctx, NULL, "fast_load", + handle_fast_load_command, COMMAND_ANY, + "loads active fast load image to current target " + "- mainly for profiling purposes"); + + /** @todo don't register virt2phys() unless target supports it */ + register_command(cmd_ctx, NULL, "virt2phys", + handle_virt2phys_command, COMMAND_ANY, + "translate a virtual address into a physical address"); + + register_command(cmd_ctx, NULL, "reg", + handle_reg_command, COMMAND_EXEC, + "display or set a register"); + + register_command(cmd_ctx, NULL, "poll", + handle_poll_command, COMMAND_EXEC, + "poll target state"); + register_command(cmd_ctx, NULL, "wait_halt", + handle_wait_halt_command, COMMAND_EXEC, + "wait for target halt [time (s)]"); + register_command(cmd_ctx, NULL, "halt", + handle_halt_command, COMMAND_EXEC, + "halt target"); + register_command(cmd_ctx, NULL, "resume", + handle_resume_command, COMMAND_EXEC, + "resume target [addr]"); + register_command(cmd_ctx, NULL, "reset", + handle_reset_command, COMMAND_EXEC, + "reset target [run | halt | init] - default is run"); + register_command(cmd_ctx, NULL, "soft_reset_halt", + handle_soft_reset_halt_command, COMMAND_EXEC, + "halt the target and do a soft reset"); + + register_command(cmd_ctx, NULL, "step", + handle_step_command, COMMAND_EXEC, + "step one instruction from current PC or [addr]"); + + register_command(cmd_ctx, NULL, "mdw", + handle_md_command, COMMAND_EXEC, + "display memory words [phys] [count]"); + register_command(cmd_ctx, NULL, "mdh", + handle_md_command, COMMAND_EXEC, + "display memory half-words [phys] [count]"); + register_command(cmd_ctx, NULL, "mdb", + handle_md_command, COMMAND_EXEC, + "display memory bytes [phys] [count]"); + + register_command(cmd_ctx, NULL, "mww", + handle_mw_command, COMMAND_EXEC, + "write memory word [phys] [count]"); + register_command(cmd_ctx, NULL, "mwh", + handle_mw_command, COMMAND_EXEC, + "write memory half-word [phys] [count]"); + register_command(cmd_ctx, NULL, "mwb", + handle_mw_command, COMMAND_EXEC, + "write memory byte [phys] [count]"); + + register_command(cmd_ctx, NULL, "bp", + handle_bp_command, COMMAND_EXEC, + "list or set breakpoint [
[hw]]"); + register_command(cmd_ctx, NULL, "rbp", + handle_rbp_command, COMMAND_EXEC, + "remove breakpoint
"); + + register_command(cmd_ctx, NULL, "wp", + handle_wp_command, COMMAND_EXEC, + "list or set watchpoint " + "[
[value] [mask]]"); + register_command(cmd_ctx, NULL, "rwp", + handle_rwp_command, COMMAND_EXEC, + "remove watchpoint
"); + + register_command(cmd_ctx, NULL, "load_image", + handle_load_image_command, COMMAND_EXEC, + "load_image
" + "['bin'|'ihex'|'elf'|'s19'] [min_address] [max_length]"); + register_command(cmd_ctx, NULL, "dump_image", + handle_dump_image_command, COMMAND_EXEC, + "dump_image
"); + register_command(cmd_ctx, NULL, "verify_image", + handle_verify_image_command, COMMAND_EXEC, + "verify_image [offset] [type]"); + register_command(cmd_ctx, NULL, "test_image", + handle_test_image_command, COMMAND_EXEC, + "test_image [offset] [type]"); + + return ERROR_OK; +}