X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=ed6f655eac68607285030188b894db34141a4979;hp=a3230d2486fbccac84221cd2f6383669b9625400;hb=8457a1be10d1463b40c020867ad4dc2513c93a4b;hpb=17a052d6fe44fc265d48e94bdd3356d6f25ca064 diff --git a/src/target/target.c b/src/target/target.c index a3230d2486..ed6f655eac 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -41,6 +41,7 @@ #include "config.h" #endif +#include #include #include #include @@ -72,8 +73,6 @@ static int target_get_gdb_fileio_info_default(struct target *target, struct gdb_fileio_info *fileio_info); static int target_gdb_fileio_end_default(struct target *target, int retcode, int fileio_errno, bool ctrl_c); -static int target_profiling_default(struct target *target, uint32_t *samples, - uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); /* targets */ extern struct target_type arm7tdmi_target; @@ -94,6 +93,7 @@ extern struct target_type cortexr4_target; extern struct target_type arm11_target; extern struct target_type ls1_sap_target; extern struct target_type mips_m4k_target; +extern struct target_type mips_mips64_target; extern struct target_type avr_target; extern struct target_type dsp563xx_target; extern struct target_type dsp5680xx_target; @@ -110,6 +110,7 @@ extern struct target_type stm8_target; extern struct target_type riscv_target; extern struct target_type mem_ap_target; extern struct target_type esirisc_target; +extern struct target_type arcv2_target; static struct target_type *target_types[] = { &arm7tdmi_target, @@ -145,20 +146,21 @@ static struct target_type *target_types[] = { &riscv_target, &mem_ap_target, &esirisc_target, -#if BUILD_TARGET64 + &arcv2_target, &aarch64_target, -#endif + &mips_mips64_target, NULL, }; struct target *all_targets; static struct target_event_callback *target_event_callbacks; static struct target_timer_callback *target_timer_callbacks; -LIST_HEAD(target_reset_callback_list); -LIST_HEAD(target_trace_callback_list); -static const int polling_interval = 100; +static int64_t target_timer_next_event_value; +static LIST_HEAD(target_reset_callback_list); +static LIST_HEAD(target_trace_callback_list); +static const int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL; -static const Jim_Nvp nvp_assert[] = { +static const struct jim_nvp nvp_assert[] = { { .name = "assert", NVP_ASSERT }, { .name = "deassert", NVP_DEASSERT }, { .name = "T", NVP_ASSERT }, @@ -168,16 +170,16 @@ static const Jim_Nvp nvp_assert[] = { { .name = NULL, .value = -1 } }; -static const Jim_Nvp nvp_error_target[] = { +static const struct 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" }, { .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" }, { .value = ERROR_TARGET_FAILURE, .name = "err-failure" }, - { .value = ERROR_TARGET_UNALIGNED_ACCESS , .name = "err-unaligned-access" }, - { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" }, - { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" }, - { .value = ERROR_TARGET_TRANSLATION_FAULT , .name = "err-translation-fault" }, + { .value = ERROR_TARGET_UNALIGNED_ACCESS, .name = "err-unaligned-access" }, + { .value = ERROR_TARGET_DATA_ABORT, .name = "err-data-abort" }, + { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE, .name = "err-resource-not-available" }, + { .value = ERROR_TARGET_TRANSLATION_FAULT, .name = "err-translation-fault" }, { .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" }, { .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" }, { .value = -1, .name = NULL } @@ -185,22 +187,24 @@ static const Jim_Nvp nvp_error_target[] = { static const char *target_strerror_safe(int err) { - const Jim_Nvp *n; + const struct jim_nvp *n; - n = Jim_Nvp_value2name_simple(nvp_error_target, err); - if (n->name == NULL) + n = jim_nvp_value2name_simple(nvp_error_target, err); + if (!n->name) return "unknown"; else return n->name; } -static const Jim_Nvp nvp_target_event[] = { +static const struct jim_nvp nvp_target_event[] = { { .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" }, { .value = TARGET_EVENT_RESUME_END, .name = "resume-end" }, + { .value = TARGET_EVENT_STEP_START, .name = "step-start" }, + { .value = TARGET_EVENT_STEP_END, .name = "step-end" }, { .name = "gdb-start", .value = TARGET_EVENT_GDB_START }, { .name = "gdb-end", .value = TARGET_EVENT_GDB_END }, @@ -215,6 +219,7 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" }, + { .value = TARGET_EVENT_EXAMINE_FAIL, .name = "examine-fail" }, { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" }, { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" }, @@ -224,17 +229,17 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" }, { .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" }, - { .value = TARGET_EVENT_GDB_FLASH_WRITE_END , .name = "gdb-flash-write-end" }, + { .value = TARGET_EVENT_GDB_FLASH_WRITE_END, .name = "gdb-flash-write-end" }, { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" }, - { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" }, + { .value = TARGET_EVENT_GDB_FLASH_ERASE_END, .name = "gdb-flash-erase-end" }, { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" }, { .name = NULL, .value = -1 } }; -static const Jim_Nvp nvp_target_state[] = { +static const struct jim_nvp nvp_target_state[] = { { .name = "unknown", .value = TARGET_UNKNOWN }, { .name = "running", .value = TARGET_RUNNING }, { .name = "halted", .value = TARGET_HALTED }, @@ -243,19 +248,20 @@ static const Jim_Nvp nvp_target_state[] = { { .name = NULL, .value = -1 }, }; -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 }, +static const struct 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 }, { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT }, - { .name = "single-step" , .value = DBG_REASON_SINGLESTEP }, - { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED }, - { .name = "program-exit" , .value = DBG_REASON_EXIT }, - { .name = "undefined" , .value = DBG_REASON_UNDEFINED }, + { .name = "single-step", .value = DBG_REASON_SINGLESTEP }, + { .name = "target-not-halted", .value = DBG_REASON_NOTHALTED }, + { .name = "program-exit", .value = DBG_REASON_EXIT }, + { .name = "exception-catch", .value = DBG_REASON_EXC_CATCH }, + { .name = "undefined", .value = DBG_REASON_UNDEFINED }, { .name = NULL, .value = -1 }, }; -static const Jim_Nvp nvp_target_endian[] = { +static const struct jim_nvp nvp_target_endian[] = { { .name = "big", .value = TARGET_BIG_ENDIAN }, { .name = "little", .value = TARGET_LITTLE_ENDIAN }, { .name = "be", .value = TARGET_BIG_ENDIAN }, @@ -263,19 +269,19 @@ static const Jim_Nvp nvp_target_endian[] = { { .name = NULL, .value = -1 }, }; -static const Jim_Nvp nvp_reset_modes[] = { +static const struct jim_nvp nvp_reset_modes[] = { { .name = "unknown", .value = RESET_UNKNOWN }, - { .name = "run" , .value = RESET_RUN }, - { .name = "halt" , .value = RESET_HALT }, - { .name = "init" , .value = RESET_INIT }, - { .name = NULL , .value = -1 }, + { .name = "run", .value = RESET_RUN }, + { .name = "halt", .value = RESET_HALT }, + { .name = "init", .value = RESET_INIT }, + { .name = NULL, .value = -1 }, }; const char *debug_reason_name(struct target *t) { const char *cp; - cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason, + 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)); @@ -287,7 +293,7 @@ const char *debug_reason_name(struct target *t) const char *target_state_name(struct target *t) { const char *cp; - cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name; + cp = jim_nvp_value2name_simple(nvp_target_state, t->state)->name; if (!cp) { LOG_ERROR("Invalid target state: %d", (int)(t->state)); cp = "(*BUG*unknown*BUG*)"; @@ -302,7 +308,7 @@ const char *target_state_name(struct target *t) const char *target_event_name(enum target_event event) { const char *cp; - cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name; + cp = jim_nvp_value2name_simple(nvp_target_event, event)->name; if (!cp) { LOG_ERROR("Invalid target event: %d", (int)(event)); cp = "(*BUG*unknown*BUG*)"; @@ -313,7 +319,7 @@ const char *target_event_name(enum target_event event) const char *target_reset_mode_name(enum target_reset_mode reset_mode) { const char *cp; - cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name; + cp = jim_nvp_value2name_simple(nvp_reset_modes, reset_mode)->name; if (!cp) { LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode)); cp = "(*BUG*unknown*BUG*)"; @@ -338,6 +344,15 @@ static int new_target_number(void) return x + 1; } +static void append_to_list_all_targets(struct target *target) +{ + struct target **t = &all_targets; + + while (*t) + t = &((*t)->next); + *t = target; +} + /* read a uint64_t from a buffer in target memory endianness */ uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer) { @@ -374,12 +389,6 @@ uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer) return be_to_h_u16(buffer); } -/* read a uint8_t from a buffer in target memory endianness */ -static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) -{ - return *buffer & 0x0ff; -} - /* write a uint64_t to a buffer in target memory endianness */ void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value) { @@ -477,7 +486,7 @@ struct target *get_target(const char *id) /* try as tcltarget name */ for (target = all_targets; target; target = target->next) { - if (target_name(target) == NULL) + if (!target_name(target)) continue; if (strcmp(id, target_name(target)) == 0) return target; @@ -519,7 +528,7 @@ struct target *get_current_target(struct command_context *cmd_ctx) { struct target *target = get_current_target_or_null(cmd_ctx); - if (target == NULL) { + if (!target) { LOG_ERROR("BUG: current_target out of bounds"); exit(-1); } @@ -593,7 +602,7 @@ int target_halt(struct target *target) * @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 + * such a breakpoint, in which case it would be counterproductive 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. @@ -630,7 +639,18 @@ int target_resume(struct target *target, int current, target_addr_t address, * 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. */ + /* + * resume() triggers the event 'resumed'. The execution of TCL commands + * in the event handler causes the polling of targets. If the target has + * already halted for a breakpoint, polling will run the 'halted' event + * handler before the pending 'resumed' handler. + * Disable polling during resume() to guarantee the execution of handlers + * in the correct order. + */ + bool save_poll = jtag_poll_get_enabled(); + jtag_poll_set_enabled(false); retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution); + jtag_poll_set_enabled(save_poll); if (retval != ERROR_OK) return retval; @@ -639,13 +659,13 @@ int target_resume(struct target *target, int current, target_addr_t address, return retval; } -static int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) +static int target_process_reset(struct command_invocation *cmd, enum target_reset_mode reset_mode) { char buf[100]; int retval; - Jim_Nvp *n; - n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode); - if (n->name == NULL) { + struct jim_nvp *n; + n = jim_nvp_value2name_simple(nvp_reset_modes, reset_mode); + if (!n->name) { LOG_ERROR("invalid reset mode"); return ERROR_FAIL; } @@ -663,13 +683,13 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res jtag_poll_set_enabled(false); sprintf(buf, "ocd_process_reset %s", n->name); - retval = Jim_Eval(cmd_ctx->interp, buf); + retval = Jim_Eval(cmd->ctx->interp, buf); jtag_poll_set_enabled(save_poll); if (retval != JIM_OK) { - Jim_MakeErrorMessage(cmd_ctx->interp); - command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL)); + Jim_MakeErrorMessage(cmd->ctx->interp); + command_print(cmd, "%s", Jim_GetString(Jim_GetResult(cmd->ctx->interp), NULL)); return ERROR_FAIL; } @@ -697,6 +717,15 @@ static int no_mmu(struct target *target, int *enabled) return ERROR_OK; } +/** + * Reset the @c examined flag for the given target. + * Pure paranoia -- targets are zeroed on allocation. + */ +static inline void target_reset_examined(struct target *target) +{ + target->examined = false; +} + static int default_examine(struct target *target) { target_set_examined(target); @@ -709,14 +738,20 @@ static int default_check_reset(struct target *target) return ERROR_OK; } +/* Equivalent Tcl code arp_examine_one is in src/target/startup.tcl + * Keep in sync */ int target_examine_one(struct target *target) { target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); int retval = target->type->examine(target); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + target_reset_examined(target); + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_FAIL); return retval; + } + target_set_examined(target); target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); return ERROR_OK; @@ -755,9 +790,11 @@ int target_examine(void) if (target->defer_examine) continue; - retval = target_examine_one(target); - if (retval != ERROR_OK) - return retval; + int retval2 = target_examine_one(target); + if (retval2 != ERROR_OK) { + LOG_WARNING("target %s examination failed", target_name(target)); + retval = retval2; + } } return retval; } @@ -790,12 +827,19 @@ static int target_soft_reset_halt(struct target *target) * algorithm. * * @param target used to run the algorithm + * @param num_mem_params + * @param mem_params + * @param num_reg_params + * @param reg_param + * @param entry_point + * @param exit_point + * @param timeout_ms * @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, + target_addr_t entry_point, target_addr_t exit_point, int timeout_ms, void *arch_info) { int retval = ERROR_FAIL; @@ -825,12 +869,18 @@ done: * Executes a target-specific native code algorithm and leaves it running. * * @param target used to run the algorithm + * @param num_mem_params + * @param mem_params + * @param num_reg_params + * @param reg_params + * @param entry_point + * @param exit_point * @param arch_info target-specific description of the algorithm. */ int target_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, void *arch_info) { int retval = ERROR_FAIL; @@ -863,12 +913,18 @@ done: * Waits for an algorithm started with target_start_algorithm() to complete. * * @param target used to run the algorithm + * @param num_mem_params + * @param mem_params + * @param num_reg_params + * @param reg_params + * @param exit_point + * @param timeout_ms * @param arch_info target-specific description of the algorithm. */ int target_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t exit_point, int timeout_ms, + target_addr_t exit_point, int timeout_ms, void *arch_info) { int retval = ERROR_FAIL; @@ -934,6 +990,7 @@ done: * @param entry_point address on the target to execute to start the algorithm * @param exit_point address at which to set a breakpoint to catch the * end of the algorithm; can be 0 if target triggers a breakpoint itself + * @param arch_info */ int target_run_flash_async_algorithm(struct target *target, @@ -959,7 +1016,7 @@ int target_run_flash_async_algorithm(struct target *target, uint32_t rp = fifo_start_addr; /* validate block_size is 2^n */ - assert(!block_size || !(block_size & (block_size - 1))); + assert(IS_PWR_OF_2(block_size)); retval = target_write_u32(target, wp_addr, wp); if (retval != ERROR_OK) @@ -997,7 +1054,7 @@ int target_run_flash_async_algorithm(struct target *target, break; } - if (((rp - fifo_start_addr) & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) { + if (!IS_ALIGNED(rp - fifo_start_addr, block_size) || rp < fifo_start_addr || rp >= fifo_end_addr) { LOG_ERROR("corrupted fifo read pointer 0x%" PRIx32, rp); break; } @@ -1018,11 +1075,11 @@ int target_run_flash_async_algorithm(struct target *target, * programming. The exact delay shouldn't matter as long as it's * less than buffer size / flash speed. This is very unlikely to * run when using high latency connections such as USB. */ - alive_sleep(10); + alive_sleep(2); /* to stop an infinite loop on some targets check and increment a timeout * this issue was observed on a stellaris using the new ICDI interface */ - if (timeout++ >= 500) { + if (timeout++ >= 2500) { LOG_ERROR("timeout waiting for algorithm, a target reset is recommended"); return ERROR_FLASH_OPERATION_FAILED; } @@ -1036,6 +1093,10 @@ int target_run_flash_async_algorithm(struct target *target, if (thisrun_bytes > count * block_size) thisrun_bytes = count * block_size; + /* Force end of large blocks to be word aligned */ + if (thisrun_bytes >= 16) + thisrun_bytes -= (rp + thisrun_bytes) & 0x03; + /* Write data to fifo */ retval = target_write_buffer(target, wp, thisrun_bytes, buffer); if (retval != ERROR_OK) @@ -1085,6 +1146,156 @@ int target_run_flash_async_algorithm(struct target *target, return retval; } +int target_run_read_async_algorithm(struct target *target, + uint8_t *buffer, uint32_t count, int block_size, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t buffer_start, uint32_t buffer_size, + uint32_t entry_point, uint32_t exit_point, void *arch_info) +{ + int retval; + int timeout = 0; + + const uint8_t *buffer_orig = buffer; + + /* Set up working area. First word is write pointer, second word is read pointer, + * rest is fifo data area. */ + uint32_t wp_addr = buffer_start; + uint32_t rp_addr = buffer_start + 4; + uint32_t fifo_start_addr = buffer_start + 8; + uint32_t fifo_end_addr = buffer_start + buffer_size; + + uint32_t wp = fifo_start_addr; + uint32_t rp = fifo_start_addr; + + /* validate block_size is 2^n */ + assert(IS_PWR_OF_2(block_size)); + + retval = target_write_u32(target, wp_addr, wp); + if (retval != ERROR_OK) + return retval; + retval = target_write_u32(target, rp_addr, rp); + if (retval != ERROR_OK) + return retval; + + /* Start up algorithm on target */ + retval = target_start_algorithm(target, num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, + exit_point, + arch_info); + + if (retval != ERROR_OK) { + LOG_ERROR("error starting target flash read algorithm"); + return retval; + } + + while (count > 0) { + retval = target_read_u32(target, wp_addr, &wp); + if (retval != ERROR_OK) { + LOG_ERROR("failed to get write pointer"); + break; + } + + LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32, + (size_t)(buffer - buffer_orig), count, wp, rp); + + if (wp == 0) { + LOG_ERROR("flash read algorithm aborted by target"); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + if (!IS_ALIGNED(wp - fifo_start_addr, block_size) || wp < fifo_start_addr || wp >= fifo_end_addr) { + LOG_ERROR("corrupted fifo write pointer 0x%" PRIx32, wp); + break; + } + + /* Count the number of bytes available in the fifo without + * crossing the wrap around. */ + uint32_t thisrun_bytes; + if (wp >= rp) + thisrun_bytes = wp - rp; + else + thisrun_bytes = fifo_end_addr - rp; + + if (thisrun_bytes == 0) { + /* Throttle polling a bit if transfer is (much) faster than flash + * reading. The exact delay shouldn't matter as long as it's + * less than buffer size / flash speed. This is very unlikely to + * run when using high latency connections such as USB. */ + alive_sleep(2); + + /* to stop an infinite loop on some targets check and increment a timeout + * this issue was observed on a stellaris using the new ICDI interface */ + if (timeout++ >= 2500) { + LOG_ERROR("timeout waiting for algorithm, a target reset is recommended"); + return ERROR_FLASH_OPERATION_FAILED; + } + continue; + } + + /* Reset our timeout */ + timeout = 0; + + /* Limit to the amount of data we actually want to read */ + if (thisrun_bytes > count * block_size) + thisrun_bytes = count * block_size; + + /* Force end of large blocks to be word aligned */ + if (thisrun_bytes >= 16) + thisrun_bytes -= (rp + thisrun_bytes) & 0x03; + + /* Read data from fifo */ + retval = target_read_buffer(target, rp, thisrun_bytes, buffer); + if (retval != ERROR_OK) + break; + + /* Update counters and wrap write pointer */ + buffer += thisrun_bytes; + count -= thisrun_bytes / block_size; + rp += thisrun_bytes; + if (rp >= fifo_end_addr) + rp = fifo_start_addr; + + /* Store updated write pointer to target */ + retval = target_write_u32(target, rp_addr, rp); + if (retval != ERROR_OK) + break; + + /* Avoid GDB timeouts */ + keep_alive(); + + } + + if (retval != ERROR_OK) { + /* abort flash write algorithm on target */ + target_write_u32(target, rp_addr, 0); + } + + int retval2 = target_wait_algorithm(target, num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, + 10000, + arch_info); + + if (retval2 != ERROR_OK) { + LOG_ERROR("error waiting for target flash write algorithm"); + retval = retval2; + } + + if (retval == ERROR_OK) { + /* check if algorithm set wp = 0 after fifo writer loop finished */ + retval = target_read_u32(target, wp_addr, &wp); + if (retval == ERROR_OK && wp == 0) { + LOG_ERROR("flash read algorithm aborted by target"); + retval = ERROR_FLASH_OPERATION_FAILED; + } + } + + return retval; +} + int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { @@ -1199,7 +1410,7 @@ int target_hit_watchpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (target->type->hit_watchpoint == NULL) { + if (!target->type->hit_watchpoint) { /* For backward compatible, if hit_watchpoint is not implemented, * return ERROR_FAIL such that gdb_server will not take the nonsense * information. */ @@ -1211,7 +1422,7 @@ int target_hit_watchpoint(struct target *target, const char *target_get_gdb_arch(struct target *target) { - if (target->type->get_gdb_arch == NULL) + if (!target->type->get_gdb_arch) return NULL; return target->type->get_gdb_arch(target); } @@ -1220,22 +1431,58 @@ int target_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { - return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); + int result = ERROR_FAIL; + + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + goto done; + } + + result = target->type->get_gdb_reg_list(target, reg_list, + reg_list_size, reg_class); + +done: + if (result != ERROR_OK) { + *reg_list = NULL; + *reg_list_size = 0; + } + return result; +} + +int target_get_gdb_reg_list_noread(struct target *target, + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class) +{ + if (target->type->get_gdb_reg_list_noread && + target->type->get_gdb_reg_list_noread(target, reg_list, + reg_list_size, reg_class) == ERROR_OK) + return ERROR_OK; + return target_get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } bool target_supports_gdb_connection(struct target *target) { /* - * based on current code, we can simply exclude all the targets that - * don't provide get_gdb_reg_list; this could change with new targets. + * exclude all the targets that don't provide get_gdb_reg_list + * or that have explicit gdb_max_connection == 0 */ - return !!target->type->get_gdb_reg_list; + return !!target->type->get_gdb_reg_list && !!target->gdb_max_connections; } int target_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { - return target->type->step(target, current, address, handle_breakpoints); + int retval; + + target_call_event_callbacks(target, TARGET_EVENT_STEP_START); + + retval = target->type->step(target, current, address, handle_breakpoints); + if (retval != ERROR_OK) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_STEP_END); + + return retval; } int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) @@ -1256,24 +1503,34 @@ int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); } -int target_profiling(struct target *target, uint32_t *samples, - uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) +target_addr_t target_address_max(struct target *target) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted (profiling)", target->cmd_name); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->profiling(target, samples, max_num_samples, - num_samples, seconds); + unsigned bits = target_address_bits(target); + if (sizeof(target_addr_t) * 8 == bits) + return (target_addr_t) -1; + else + return (((target_addr_t) 1) << bits) - 1; } -/** - * Reset the @c examined flag for the given target. - * Pure paranoia -- targets are zeroed on allocation. - */ -static void target_reset_examined(struct target *target) +unsigned target_address_bits(struct target *target) { - target->examined = false; + if (target->type->address_bits) + return target->type->address_bits(target); + return 32; +} + +unsigned int target_data_bits(struct target *target) +{ + if (target->type->data_bits) + return target->type->data_bits(target); + return 32; +} + +static int target_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) +{ + return target->type->profiling(target, samples, max_num_samples, + num_samples, seconds); } static int handle_target(void *priv); @@ -1284,16 +1541,16 @@ static int target_init_one(struct command_context *cmd_ctx, target_reset_examined(target); struct target_type *type = target->type; - if (type->examine == NULL) + if (!type->examine) type->examine = default_examine; - if (type->check_reset == NULL) + if (!type->check_reset) type->check_reset = default_check_reset; - assert(type->init_target != NULL); + assert(type->init_target); int retval = type->init_target(cmd_ctx, target); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("target '%s' init failed", target_name(target)); return retval; } @@ -1302,7 +1559,7 @@ static int target_init_one(struct command_context *cmd_ctx, * implement it in stages, but warn if we need to do so. */ if (type->mmu) { - if (type->virt2phys == NULL) { + if (!type->virt2phys) { LOG_ERROR("type '%s' is missing virt2phys", type->name); type->virt2phys = identity_virt2phys; } @@ -1320,19 +1577,19 @@ static int target_init_one(struct command_context *cmd_ctx, type->virt2phys = identity_virt2phys; } - if (target->type->read_buffer == NULL) + if (!target->type->read_buffer) target->type->read_buffer = target_read_buffer_default; - if (target->type->write_buffer == NULL) + if (!target->type->write_buffer) target->type->write_buffer = target_write_buffer_default; - if (target->type->get_gdb_fileio_info == NULL) + if (!target->type->get_gdb_fileio_info) target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default; - if (target->type->gdb_fileio_end == NULL) + if (!target->type->gdb_fileio_end) target->type->gdb_fileio_end = target_gdb_fileio_end_default; - if (target->type->profiling == NULL) + if (!target->type->profiling) target->type->profiling = target_profiling_default; return ERROR_OK; @@ -1345,7 +1602,7 @@ static int target_init(struct command_context *cmd_ctx) for (target = all_targets; target; target = target->next) { retval = target_init_one(cmd_ctx, target); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; } @@ -1353,12 +1610,12 @@ static int target_init(struct command_context *cmd_ctx) return ERROR_OK; retval = target_register_user_commands(cmd_ctx); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; retval = target_register_timer_callback(&handle_target, - polling_interval, 1, cmd_ctx->interp); - if (ERROR_OK != retval) + polling_interval, TARGET_TIMER_TYPE_PERIODIC, cmd_ctx->interp); + if (retval != ERROR_OK) return retval; return ERROR_OK; @@ -1379,15 +1636,15 @@ COMMAND_HANDLER(handle_target_init_command) target_initialized = true; retval = command_run_line(CMD_CTX, "init_targets"); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; retval = command_run_line(CMD_CTX, "init_target_events"); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; retval = command_run_line(CMD_CTX, "init_board"); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; LOG_DEBUG("Initializing targets..."); @@ -1399,7 +1656,7 @@ int target_register_event_callback(int (*callback)(struct target *target, { struct target_event_callback **callbacks_p = &target_event_callbacks; - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; if (*callbacks_p) { @@ -1421,11 +1678,11 @@ int target_register_reset_callback(int (*callback)(struct target *target, { struct target_reset_callback *entry; - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; entry = malloc(sizeof(struct target_reset_callback)); - if (entry == NULL) { + if (!entry) { LOG_ERROR("error allocating buffer for reset callback entry"); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1443,11 +1700,11 @@ int target_register_trace_callback(int (*callback)(struct target *target, { struct target_trace_callback *entry; - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; entry = malloc(sizeof(struct target_trace_callback)); - if (entry == NULL) { + if (!entry) { LOG_ERROR("error allocating buffer for trace callback entry"); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1465,7 +1722,7 @@ int target_register_timer_callback(int (*callback)(void *priv), { struct target_timer_callback **callbacks_p = &target_timer_callbacks; - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; if (*callbacks_p) { @@ -1480,8 +1737,8 @@ int target_register_timer_callback(int (*callback)(void *priv), (*callbacks_p)->time_ms = time_ms; (*callbacks_p)->removed = false; - gettimeofday(&(*callbacks_p)->when, NULL); - timeval_add_time(&(*callbacks_p)->when, 0, time_ms * 1000); + (*callbacks_p)->when = timeval_ms() + time_ms; + target_timer_next_event_value = MIN(target_timer_next_event_value, (*callbacks_p)->when); (*callbacks_p)->priv = priv; (*callbacks_p)->next = NULL; @@ -1495,7 +1752,7 @@ int target_unregister_event_callback(int (*callback)(struct target *target, struct target_event_callback **p = &target_event_callbacks; struct target_event_callback *c = target_event_callbacks; - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; while (c) { @@ -1517,7 +1774,7 @@ int target_unregister_reset_callback(int (*callback)(struct target *target, { struct target_reset_callback *entry; - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; list_for_each_entry(entry, &target_reset_callback_list, list) { @@ -1536,7 +1793,7 @@ int target_unregister_trace_callback(int (*callback)(struct target *target, { struct target_trace_callback *entry; - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; list_for_each_entry(entry, &target_trace_callback_list, list) { @@ -1552,7 +1809,7 @@ int target_unregister_trace_callback(int (*callback)(struct target *target, int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) { - if (callback == NULL) + if (!callback) return ERROR_COMMAND_SYNTAX_ERROR; for (struct target_timer_callback *c = target_timer_callbacks; @@ -1576,8 +1833,9 @@ int target_call_event_callbacks(struct target *target, enum target_event event) target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } - LOG_DEBUG("target event %i (%s)", event, - Jim_Nvp_value2name_simple(nvp_target_event, event)->name); + LOG_DEBUG("target event %i (%s) for core %s", event, + jim_nvp_value2name_simple(nvp_target_event, event)->name, + target_name(target)); target_handle_event(target, event); @@ -1595,7 +1853,7 @@ int target_call_reset_callbacks(struct target *target, enum target_reset_mode re struct target_reset_callback *callback; LOG_DEBUG("target reset %i (%s)", reset_mode, - Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name); + jim_nvp_value2name_simple(nvp_reset_modes, reset_mode)->name); list_for_each_entry(callback, &target_reset_callback_list, list) callback->callback(target, reset_mode, callback->priv); @@ -1614,15 +1872,14 @@ int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data } static int target_timer_callback_periodic_restart( - struct target_timer_callback *cb, struct timeval *now) + struct target_timer_callback *cb, int64_t *now) { - cb->when = *now; - timeval_add_time(&cb->when, 0, cb->time_ms * 1000L); + cb->when = *now + cb->time_ms; return ERROR_OK; } static int target_call_timer_callback(struct target_timer_callback *cb, - struct timeval *now) + int64_t *now) { cb->callback(cb->priv); @@ -1644,14 +1901,18 @@ static int target_call_timer_callbacks_check_time(int checktime) keep_alive(); - struct timeval now; - gettimeofday(&now, NULL); + int64_t now = timeval_ms(); + + /* Initialize to a default value that's a ways into the future. + * The loop below will make it closer to now if there are + * callbacks that want to be called sooner. */ + target_timer_next_event_value = now + 1000; /* Store an address of the place containing a pointer to the * next item; initially, that's a standalone "root of the * list" variable. */ struct target_timer_callback **callback = &target_timer_callbacks; - while (*callback) { + while (callback && *callback) { if ((*callback)->removed) { struct target_timer_callback *p = *callback; *callback = (*callback)->next; @@ -1661,11 +1922,14 @@ static int target_call_timer_callbacks_check_time(int checktime) bool call_it = (*callback)->callback && ((!checktime && (*callback)->type == TARGET_TIMER_TYPE_PERIODIC) || - timeval_compare(&now, &(*callback)->when) >= 0); + now >= (*callback)->when); if (call_it) target_call_timer_callback(*callback, &now); + if (!(*callback)->removed && (*callback)->when < target_timer_next_event_value) + target_timer_next_event_value = (*callback)->when; + callback = &(*callback)->next; } @@ -1673,17 +1937,22 @@ static int target_call_timer_callbacks_check_time(int checktime) return ERROR_OK; } -int target_call_timer_callbacks(void) +int target_call_timer_callbacks() { return target_call_timer_callbacks_check_time(1); } /* invoke periodic callbacks immediately */ -int target_call_timer_callbacks_now(void) +int target_call_timer_callbacks_now() { return target_call_timer_callbacks_check_time(0); } +int64_t target_timer_next_event(void) +{ + return target_timer_next_event_value; +} + /* Prints the working area layout for debug purposes */ static void print_wa_layout(struct target *target) { @@ -1707,7 +1976,7 @@ static void target_split_working_area(struct working_area *area, uint32_t size) if (size < area->size) { struct working_area *new_wa = malloc(sizeof(*new_wa)); - if (new_wa == NULL) + if (!new_wa) return; new_wa->next = area->next; @@ -1722,10 +1991,8 @@ static void target_split_working_area(struct working_area *area, uint32_t size) /* If backup memory was allocated to this area, it has the wrong size * now so free it and it will be reallocated if/when needed */ - if (area->backup) { - free(area->backup); - area->backup = NULL; - } + free(area->backup); + area->backup = NULL; } } @@ -1745,16 +2012,13 @@ static void target_merge_working_areas(struct target *target) /* Remove the last */ struct working_area *to_be_freed = c->next; c->next = c->next->next; - if (to_be_freed->backup) - free(to_be_freed->backup); + free(to_be_freed->backup); free(to_be_freed); /* If backup memory was allocated to the remaining area, it's has * the wrong size now */ - if (c->backup) { - free(c->backup); - c->backup = NULL; - } + free(c->backup); + c->backup = NULL; } else { c = c->next; } @@ -1764,7 +2028,7 @@ static void target_merge_working_areas(struct target *target) int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area) { /* Reevaluate working area address based on MMU state*/ - if (target->working_areas == NULL) { + if (!target->working_areas) { int retval; int enabled; @@ -1823,7 +2087,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w c = c->next; } - if (c == NULL) + if (!c) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* Split the working area into the requested size */ @@ -1833,9 +2097,9 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w size, c->address); if (target->backup_working_area) { - if (c->backup == NULL) { + if (!c->backup) { c->backup = malloc(c->size); - if (c->backup == NULL) + if (!c->backup) return ERROR_FAIL; } @@ -1871,7 +2135,7 @@ static int target_restore_working_area(struct target *target, struct working_are { int retval = ERROR_OK; - if (target->backup_working_area && area->backup != NULL) { + if (target->backup_working_area && area->backup) { retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup); if (retval != ERROR_OK) LOG_ERROR("failed to restore %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT, @@ -1966,7 +2230,7 @@ uint32_t target_get_working_area_avail(struct target *target) struct working_area *c = target->working_areas; uint32_t max_size = 0; - if (c == NULL) + if (!c) return target->working_area_size; while (c) { @@ -1984,8 +2248,7 @@ static void target_destroy(struct target *target) if (target->type->deinit_target) target->type->deinit_target(target); - if (target->semihosting) - free(target->semihosting); + free(target->semihosting); jtag_unregister_event_callback(jtag_enable_callback, target); @@ -2002,7 +2265,7 @@ static void target_destroy(struct target *target) /* release the targets SMP list */ if (target->smp) { struct target_list *head = target->head; - while (head != NULL) { + while (head) { struct target_list *pos = head->next; head->target->smp = 0; free(head); @@ -2011,6 +2274,8 @@ static void target_destroy(struct target *target) target->smp = 0; } + rtos_destroy(target); + free(target->gdb_port_override); free(target->type); free(target->trace_info); @@ -2051,7 +2316,7 @@ void target_quit(void) int target_arch_state(struct target *target) { int retval; - if (target == NULL) { + if (!target) { LOG_WARNING("No target has been configured"); return ERROR_OK; } @@ -2079,7 +2344,7 @@ static int target_gdb_fileio_end_default(struct target *target, return ERROR_OK; } -static int target_profiling_default(struct target *target, uint32_t *samples, +int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { struct timeval timeout, now; @@ -2092,7 +2357,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples, uint32_t sample_count = 0; /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */ - struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); + struct reg *reg = register_get_by_name(target->reg_cache, "pc", true); int retval = ERROR_OK; for (;;) { @@ -2133,7 +2398,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples, */ int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { - LOG_DEBUG("writing buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, + LOG_DEBUG("writing buffer of %" PRIu32 " byte at " TARGET_ADDR_FMT, size, address); if (!target_was_examined(target)) { @@ -2159,10 +2424,13 @@ static int target_write_buffer_default(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; + unsigned int data_bytes = target_data_bits(target) / 8; - /* Align up to maximum 4 bytes. The loop condition makes sure the next pass + /* Align up to maximum bytes. The loop condition makes sure the next pass * will have something to do with the size we leave to it. */ - for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { + for (size = 1; + size < data_bytes && count >= size * 2 + (address & size); + size *= 2) { if (address & size) { int retval = target_write_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) @@ -2195,7 +2463,7 @@ static int target_write_buffer_default(struct target *target, */ int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) { - LOG_DEBUG("reading buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, + LOG_DEBUG("reading buffer of %" PRIu32 " byte at " TARGET_ADDR_FMT, size, address); if (!target_was_examined(target)) { @@ -2220,10 +2488,13 @@ int target_read_buffer(struct target *target, target_addr_t address, uint32_t si static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { uint32_t size; + unsigned int data_bytes = target_data_bits(target) / 8; - /* Align up to maximum 4 bytes. The loop condition makes sure the next pass + /* Align up to maximum bytes. The loop condition makes sure the next pass * will have something to do with the size we leave to it. */ - for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { + for (size = 1; + size < data_bytes && count >= size * 2 + (address & size); + size *= 2) { if (address & size) { int retval = target_read_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) @@ -2250,7 +2521,7 @@ static int target_read_buffer_default(struct target *target, target_addr_t addre return ERROR_OK; } -int target_checksum_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* crc) +int target_checksum_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t *crc) { uint8_t *buffer; int retval; @@ -2264,8 +2535,8 @@ int target_checksum_memory(struct target *target, target_addr_t address, uint32_ retval = target->type->checksum_memory(target, address, size, &checksum); if (retval != ERROR_OK) { buffer = malloc(size); - if (buffer == NULL) { - LOG_ERROR("error allocating buffer for section (%" PRId32 " bytes)", size); + if (!buffer) { + LOG_ERROR("error allocating buffer for section (%" PRIu32 " bytes)", size); return ERROR_COMMAND_SYNTAX_ERROR; } retval = target_read_buffer(target, address, size, buffer); @@ -2299,7 +2570,7 @@ int target_blank_check_memory(struct target *target, return ERROR_FAIL; } - if (target->type->blank_check_memory == NULL) + if (!target->type->blank_check_memory) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return target->type->blank_check_memory(target, blocks, num_blocks, erased_value); @@ -2561,23 +2832,23 @@ int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t v return retval; } -static int find_target(struct command_context *cmd_ctx, const char *name) +static int find_target(struct command_invocation *cmd, const char *name) { struct target *target = get_target(name); - if (target == NULL) { - LOG_ERROR("Target: %s is unknown, try one of:\n", name); + if (!target) { + command_print(cmd, "Target: %s is unknown, try one of:\n", name); return ERROR_FAIL; } if (!target->tap->enabled) { - LOG_USER("Target: TAP %s is disabled, " + command_print(cmd, "Target: TAP %s is disabled, " "can't be the current target\n", target->tap->dotted_name); return ERROR_FAIL; } - cmd_ctx->current_target = target; - if (cmd_ctx->current_target_override) - cmd_ctx->current_target_override = target; + cmd->ctx->current_target = target; + if (cmd->ctx->current_target_override) + cmd->ctx->current_target_override = target; return ERROR_OK; } @@ -2587,7 +2858,7 @@ COMMAND_HANDLER(handle_targets_command) { int retval = ERROR_OK; if (CMD_ARGC == 1) { - retval = find_target(CMD_CTX, CMD_ARGV[0]); + retval = find_target(CMD, CMD_ARGV[0]); if (retval == ERROR_OK) { /* we're done! */ return retval; @@ -2595,8 +2866,8 @@ COMMAND_HANDLER(handle_targets_command) } struct target *target = all_targets; - command_print(CMD_CTX, " TargetName Type Endian TapName State "); - command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------"); + command_print(CMD, " TargetName Type Endian TapName State "); + command_print(CMD, "-- ------------------ ---------- ------ ------------------ ------------"); while (target) { const char *state; char marker = ' '; @@ -2610,13 +2881,13 @@ COMMAND_HANDLER(handle_targets_command) marker = '*'; /* keep columns lined up to match the headers above */ - command_print(CMD_CTX, + command_print(CMD, "%2d%c %-18s %-10s %-6s %-18s %s", target->target_number, marker, target_name(target), target_type_name(target), - Jim_Nvp_value2name_simple(nvp_target_endian, + jim_nvp_value2name_simple(nvp_target_endian, target->endianness)->name, target->tap->dotted_name, state); @@ -2628,57 +2899,57 @@ COMMAND_HANDLER(handle_targets_command) /* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */ -static int powerDropout; -static int srstAsserted; +static int power_dropout; +static int srst_asserted; -static int runPowerRestore; -static int runPowerDropout; -static int runSrstAsserted; -static int runSrstDeasserted; +static int run_power_restore; +static int run_power_dropout; +static int run_srst_asserted; +static int run_srst_deasserted; static int sense_handler(void) { - static int prevSrstAsserted; - static int prevPowerdropout; + static int prev_srst_asserted; + static int prev_power_dropout; - int retval = jtag_power_dropout(&powerDropout); + int retval = jtag_power_dropout(&power_dropout); if (retval != ERROR_OK) return retval; - int powerRestored; - powerRestored = prevPowerdropout && !powerDropout; - if (powerRestored) - runPowerRestore = 1; + int power_restored; + power_restored = prev_power_dropout && !power_dropout; + if (power_restored) + run_power_restore = 1; int64_t current = timeval_ms(); - static int64_t lastPower; - bool waitMore = lastPower + 2000 > current; - if (powerDropout && !waitMore) { - runPowerDropout = 1; - lastPower = current; + static int64_t last_power; + bool wait_more = last_power + 2000 > current; + if (power_dropout && !wait_more) { + run_power_dropout = 1; + last_power = current; } - retval = jtag_srst_asserted(&srstAsserted); + retval = jtag_srst_asserted(&srst_asserted); if (retval != ERROR_OK) return retval; - int srstDeasserted; - srstDeasserted = prevSrstAsserted && !srstAsserted; + int srst_deasserted; + srst_deasserted = prev_srst_asserted && !srst_asserted; - static int64_t lastSrst; - waitMore = lastSrst + 2000 > current; - if (srstDeasserted && !waitMore) { - runSrstDeasserted = 1; - lastSrst = current; + static int64_t last_srst; + wait_more = last_srst + 2000 > current; + if (srst_deasserted && !wait_more) { + run_srst_deasserted = 1; + last_srst = current; } - if (!prevSrstAsserted && srstAsserted) - runSrstAsserted = 1; + if (!prev_srst_asserted && srst_asserted) + run_srst_asserted = 1; - prevSrstAsserted = srstAsserted; - prevPowerdropout = powerDropout; + prev_srst_asserted = srst_asserted; + prev_power_dropout = power_dropout; - if (srstDeasserted || powerRestored) { + if (srst_deasserted || power_restored) { /* Other than logging the event we can't do anything here. * Issuing a reset is a particularly bad idea as we might * be inside a reset already. @@ -2709,21 +2980,21 @@ static int handle_target(void *priv) * clearing the flags after running these events. */ int did_something = 0; - if (runSrstAsserted) { + if (run_srst_asserted) { LOG_INFO("srst asserted detected, running srst_asserted proc."); Jim_Eval(interp, "srst_asserted"); did_something = 1; } - if (runSrstDeasserted) { + if (run_srst_deasserted) { Jim_Eval(interp, "srst_deasserted"); did_something = 1; } - if (runPowerDropout) { + if (run_power_dropout) { LOG_INFO("Power dropout detected, running power_dropout proc."); Jim_Eval(interp, "power_dropout"); did_something = 1; } - if (runPowerRestore) { + if (run_power_restore) { Jim_Eval(interp, "power_restore"); did_something = 1; } @@ -2735,10 +3006,10 @@ static int handle_target(void *priv) /* clear action flags */ - runSrstAsserted = 0; - runSrstDeasserted = 0; - runPowerRestore = 0; - runPowerDropout = 0; + run_srst_asserted = 0; + run_srst_deasserted = 0; + run_power_restore = 0; + run_power_dropout = 0; recursive = 0; } @@ -2764,7 +3035,7 @@ static int handle_target(void *priv) target->backoff.count = 0; /* only poll target if we've got power and srst isn't asserted */ - if (!powerDropout && !srstAsserted) { + if (!power_dropout && !srst_asserted) { /* polling may fail silently until the target has been examined */ retval = target_poll(target); if (retval != ERROR_OK) { @@ -2786,7 +3057,7 @@ static int handle_target(void *priv) /* Target examination could have failed due to unstable connection, * but we set the examined flag anyway to repoll it later */ if (retval != ERROR_OK) { - target->examined = true; + target_set_examined(target); LOG_USER("Examination failed, GDB will be halted. Polling again in %dms", target->backoff.times * polling_interval); return retval; @@ -2803,35 +3074,31 @@ static int handle_target(void *priv) COMMAND_HANDLER(handle_reg_command) { - struct target *target; - struct reg *reg = NULL; - unsigned count = 0; - char *value; - LOG_DEBUG("-"); - target = get_current_target(CMD_CTX); + struct target *target = get_current_target(CMD_CTX); + struct reg *reg = NULL; /* list all available registers for the current target */ if (CMD_ARGC == 0) { struct reg_cache *cache = target->reg_cache; - count = 0; + unsigned int count = 0; while (cache) { unsigned i; - command_print(CMD_CTX, "===== %s", cache->name); + command_print(CMD, "===== %s", cache->name); for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) { - if (reg->exist == false) + if (reg->exist == false || reg->hidden) continue; /* only print cached values if they are valid */ if (reg->valid) { - value = buf_to_str(reg->value, - reg->size, 16); - command_print(CMD_CTX, + char *value = buf_to_hex_str(reg->value, + reg->size); + command_print(CMD, "(%i) %s (/%" PRIu32 "): 0x%s%s", count, reg->name, reg->size, value, @@ -2840,9 +3107,9 @@ COMMAND_HANDLER(handle_reg_command) : ""); free(value); } else { - command_print(CMD_CTX, "(%i) %s (/%" PRIu32 ")", + command_print(CMD, "(%i) %s (/%" PRIu32 ")", count, reg->name, - reg->size) ; + reg->size); } } cache = cache->next; @@ -2857,7 +3124,7 @@ COMMAND_HANDLER(handle_reg_command) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct reg_cache *cache = target->reg_cache; - count = 0; + unsigned int count = 0; while (cache) { unsigned i; for (i = 0; i < cache->num_regs; i++) { @@ -2872,19 +3139,19 @@ COMMAND_HANDLER(handle_reg_command) } if (!reg) { - command_print(CMD_CTX, "%i is out of bounds, the current target " + command_print(CMD, "%i is out of bounds, the current target " "has only %i registers (0 - %i)", num, count, count - 1); return ERROR_OK; } } else { /* access a single register by its name */ - reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1); + reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], true); if (!reg) goto not_found; } - assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ + assert(reg); /* give clang a hint that we *know* reg is != NULL here */ if (!reg->exist) goto not_found; @@ -2895,10 +3162,15 @@ COMMAND_HANDLER(handle_reg_command) if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0)) reg->valid = 0; - if (reg->valid == 0) - reg->type->get(reg); - value = buf_to_str(reg->value, reg->size, 16); - command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); + if (reg->valid == 0) { + int retval = reg->type->get(reg); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read register '%s'", reg->name); + return retval; + } + } + char *value = buf_to_hex_str(reg->value, reg->size); + command_print(CMD, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); free(value); return ERROR_OK; } @@ -2906,25 +3178,28 @@ COMMAND_HANDLER(handle_reg_command) /* set register value */ if (CMD_ARGC == 2) { uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); - if (buf == NULL) + if (!buf) return ERROR_FAIL; str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); - reg->type->set(reg, buf); - - value = buf_to_str(reg->value, reg->size, 16); - command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); - free(value); + int retval = reg->type->set(reg, buf); + if (retval != ERROR_OK) { + LOG_ERROR("Could not write to register '%s'", reg->name); + } else { + char *value = buf_to_hex_str(reg->value, reg->size); + command_print(CMD, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); + free(value); + } free(buf); - return ERROR_OK; + return retval; } return ERROR_COMMAND_SYNTAX_ERROR; not_found: - command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); + command_print(CMD, "register %s not found in current target", CMD_ARGV[0]); return ERROR_OK; } @@ -2934,9 +3209,9 @@ COMMAND_HANDLER(handle_poll_command) struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC == 0) { - command_print(CMD_CTX, "background polling: %s", + command_print(CMD, "background polling: %s", jtag_poll_get_enabled() ? "on" : "off"); - command_print(CMD_CTX, "TAP: %s (%s)", + command_print(CMD, "TAP: %s (%s)", target->tap->dotted_name, target->tap->enabled ? "enabled" : "disabled"); if (!target->tap->enabled) @@ -2965,7 +3240,7 @@ COMMAND_HANDLER(handle_wait_halt_command) unsigned ms = DEFAULT_HALT_TIMEOUT; if (1 == CMD_ARGC) { int retval = parse_uint(CMD_ARGV[0], &ms); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return ERROR_COMMAND_SYNTAX_ERROR; } @@ -2996,7 +3271,7 @@ int target_wait_state(struct target *target, enum target_state state, int ms) once = false; then = timeval_ms(); LOG_DEBUG("waiting for target %s...", - Jim_Nvp_value2name_simple(nvp_target_state, state)->name); + jim_nvp_value2name_simple(nvp_target_state, state)->name); } if (cur-then > 500) @@ -3004,7 +3279,7 @@ int target_wait_state(struct target *target, enum target_state state, int ms) if ((cur-then) > ms) { LOG_ERROR("timed out while waiting for target %s", - Jim_Nvp_value2name_simple(nvp_target_state, state)->name); + jim_nvp_value2name_simple(nvp_target_state, state)->name); return ERROR_FAIL; } } @@ -3021,13 +3296,13 @@ COMMAND_HANDLER(handle_halt_command) target->verbose_halt_msg = true; int retval = target_halt(target); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; if (CMD_ARGC == 1) { unsigned wait_local; retval = parse_uint(CMD_ARGV[0], &wait_local); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return ERROR_COMMAND_SYNTAX_ERROR; if (!wait_local) return ERROR_OK; @@ -3054,15 +3329,15 @@ COMMAND_HANDLER(handle_reset_command) enum target_reset_mode reset_mode = RESET_RUN; if (CMD_ARGC == 1) { - const Jim_Nvp *n; - n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]); - if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) + const struct jim_nvp *n; + n = jim_nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]); + if ((!n->name) || (n->value == RESET_UNKNOWN)) return ERROR_COMMAND_SYNTAX_ERROR; reset_mode = n->value; } /* reset *all* targets */ - return target_process_reset(CMD_CTX, reset_mode); + return target_process_reset(CMD, reset_mode); } @@ -3105,10 +3380,10 @@ COMMAND_HANDLER(handle_step_command) struct target *target = get_current_target(CMD_CTX); - return target->type->step(target, current_pc, addr, 1); + return target_step(target, current_pc, addr, 1); } -static void handle_md_output(struct command_context *cmd_ctx, +void target_handle_md_output(struct command_invocation *cmd, struct target *target, target_addr_t address, unsigned size, unsigned count, const uint8_t *buffer) { @@ -3166,7 +3441,7 @@ static void handle_md_output(struct command_context *cmd_ctx, value_fmt, value); if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) { - command_print(cmd_ctx, "%s", output); + command_print(cmd, "%s", output); output_len = 0; } } @@ -3215,15 +3490,15 @@ COMMAND_HANDLER(handle_md_command) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); uint8_t *buffer = calloc(count, size); - if (buffer == NULL) { + if (!buffer) { LOG_ERROR("Failed to allocate md read buffer"); return ERROR_FAIL; } 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); + if (retval == ERROR_OK) + target_handle_md_output(CMD, target, address, size, count, buffer); free(buffer); @@ -3246,7 +3521,7 @@ static int target_fill_mem(struct target *target, * 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) { + if (!target_buf) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } @@ -3307,8 +3582,8 @@ COMMAND_HANDLER(handle_mw_command) target_addr_t address; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); - target_addr_t value; - COMMAND_PARSE_ADDRESS(CMD_ARGV[1], value); + uint64_t value; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], value); unsigned count = 1; if (CMD_ARGC == 3) @@ -3336,7 +3611,7 @@ COMMAND_HANDLER(handle_mw_command) return target_fill_mem(target, address, fn, wordsize, value, count); } -static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, +static COMMAND_HELPER(parse_load_image_command, struct image *image, target_addr_t *min_address, target_addr_t *max_address) { if (CMD_ARGC < 1 || CMD_ARGC > 5) @@ -3348,11 +3623,11 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, target_addr_t addr; COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image->base_address = addr; - image->base_address_set = 1; + image->base_address_set = true; } else - image->base_address_set = 0; + image->base_address_set = false; - image->start_address_set = 0; + image->start_address_set = false; if (CMD_ARGC >= 4) COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address); @@ -3375,12 +3650,11 @@ COMMAND_HANDLER(handle_load_image_command) uint32_t image_size; target_addr_t min_address = 0; target_addr_t max_address = -1; - int i; struct image image; - int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, + int retval = CALL_COMMAND_HANDLER(parse_load_image_command, &image, &min_address, &max_address); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; struct target *target = get_current_target(CMD_CTX); @@ -3393,10 +3667,10 @@ COMMAND_HANDLER(handle_load_image_command) image_size = 0x0; retval = ERROR_OK; - for (i = 0; i < image.num_sections; i++) { + for (unsigned int i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); - if (buffer == NULL) { - command_print(CMD_CTX, + if (!buffer) { + command_print(CMD, "error allocating buffer for section (%d bytes)", (int)(image.sections[i].size)); retval = ERROR_FAIL; @@ -3412,7 +3686,7 @@ COMMAND_HANDLER(handle_load_image_command) uint32_t offset = 0; uint32_t length = buf_cnt; - /* DANGER!!! beware of unsigned comparision here!!! */ + /* DANGER!!! beware of unsigned comparison here!!! */ if ((image.sections[i].base_address + buf_cnt >= min_address) && (image.sections[i].base_address < max_address)) { @@ -3433,7 +3707,7 @@ COMMAND_HANDLER(handle_load_image_command) break; } image_size += length; - command_print(CMD_CTX, "%u bytes written at address " TARGET_ADDR_FMT "", + command_print(CMD, "%u bytes written at address " TARGET_ADDR_FMT "", (unsigned int)length, image.sections[i].base_address + offset); } @@ -3441,8 +3715,8 @@ COMMAND_HANDLER(handle_load_image_command) free(buffer); } - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(CMD_CTX, "downloaded %" PRIu32 " bytes " + if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) { + command_print(CMD, "downloaded %" PRIu32 " bytes " "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } @@ -3498,12 +3772,12 @@ COMMAND_HANDLER(handle_dump_image_command) free(buffer); - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) { size_t filesize; retval = fileio_size(fileio, &filesize); if (retval != ERROR_OK) return retval; - command_print(CMD_CTX, + command_print(CMD, "dumped %zu bytes in %fs (%0.3f KiB/s)", filesize, duration_elapsed(&bench), duration_kbps(&bench, filesize)); } @@ -3526,7 +3800,6 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver uint8_t *buffer; size_t buf_cnt; uint32_t image_size; - int i; int retval; uint32_t checksum = 0; uint32_t mem_checksum = 0; @@ -3550,13 +3823,13 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver target_addr_t addr; COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image.base_address = addr; - image.base_address_set = 1; + image.base_address_set = true; } else { - image.base_address_set = 0; + image.base_address_set = false; image.base_address = 0x0; } - image.start_address_set = 0; + image.start_address_set = false; retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); if (retval != ERROR_OK) @@ -3565,12 +3838,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver image_size = 0x0; int diffs = 0; retval = ERROR_OK; - for (i = 0; i < image.num_sections; i++) { + for (unsigned int i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); - if (buffer == NULL) { - command_print(CMD_CTX, - "error allocating buffer for section (%d bytes)", - (int)(image.sections[i].size)); + if (!buffer) { + command_print(CMD, + "error allocating buffer for section (%" PRIu32 " bytes)", + image.sections[i].size); break; } retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); @@ -3607,26 +3880,19 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver data = malloc(buf_cnt); - /* Can we use 32bit word accesses? */ - int size = 1; - int count = buf_cnt; - if ((count % 4) == 0) { - size *= 4; - count /= 4; - } - retval = target_read_memory(target, image.sections[i].base_address, size, count, data); + retval = target_read_buffer(target, image.sections[i].base_address, buf_cnt, data); if (retval == ERROR_OK) { uint32_t t; for (t = 0; t < buf_cnt; t++) { if (data[t] != buffer[t]) { - command_print(CMD_CTX, + command_print(CMD, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", diffs, (unsigned)(t + image.sections[i].base_address), data[t], buffer[t]); if (diffs++ >= 127) { - command_print(CMD_CTX, "More than 128 errors, the rest are not printed."); + command_print(CMD, "More than 128 errors, the rest are not printed."); free(data); free(buffer); goto done; @@ -3638,7 +3904,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver free(data); } } else { - command_print(CMD_CTX, "address " TARGET_ADDR_FMT " length 0x%08zx", + command_print(CMD, "address " TARGET_ADDR_FMT " length 0x%08zx", image.sections[i].base_address, buf_cnt); } @@ -3647,12 +3913,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver image_size += buf_cnt; } if (diffs > 0) - command_print(CMD_CTX, "No more differences found."); + command_print(CMD, "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 " + if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) { + command_print(CMD, "verified %" PRIu32 " bytes " "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } @@ -3677,32 +3943,32 @@ COMMAND_HANDLER(handle_test_image_command) return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_TEST); } -static int handle_bp_command_list(struct command_context *cmd_ctx) +static int handle_bp_command_list(struct command_invocation *cmd) { - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd->ctx); struct breakpoint *breakpoint = target->breakpoints; while (breakpoint) { if (breakpoint->type == BKPT_SOFT) { - char *buf = buf_to_str(breakpoint->orig_instr, - breakpoint->length, 16); - command_print(cmd_ctx, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s", + char *buf = buf_to_hex_str(breakpoint->orig_instr, + breakpoint->length); + command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf); free(buf); } else { if ((breakpoint->address == 0) && (breakpoint->asid != 0)) - command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", + command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", breakpoint->asid, breakpoint->length, breakpoint->set); else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - command_print(cmd_ctx, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", + command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); - command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, + command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32, breakpoint->asid); } else - command_print(cmd_ctx, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", + command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); } @@ -3712,37 +3978,37 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) return ERROR_OK; } -static int handle_bp_command_set(struct command_context *cmd_ctx, +static int handle_bp_command_set(struct command_invocation *cmd, target_addr_t addr, uint32_t asid, uint32_t length, int hw) { - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(cmd->ctx); int retval; if (asid == 0) { retval = breakpoint_add(target, addr, length, hw); /* error is always logged in breakpoint_add(), do not print it again */ - if (ERROR_OK == retval) - command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr); + if (retval == ERROR_OK) + command_print(cmd, "breakpoint set at " TARGET_ADDR_FMT "", addr); } else if (addr == 0) { - if (target->type->add_context_breakpoint == NULL) { + if (!target->type->add_context_breakpoint) { LOG_ERROR("Context breakpoint not available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = context_breakpoint_add(target, asid, length, hw); /* error is always logged in context_breakpoint_add(), do not print it again */ - if (ERROR_OK == retval) - command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); + if (retval == ERROR_OK) + command_print(cmd, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); } else { - if (target->type->add_hybrid_breakpoint == NULL) { + if (!target->type->add_hybrid_breakpoint) { LOG_ERROR("Hybrid breakpoint not available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = hybrid_breakpoint_add(target, addr, asid, length, hw); /* error is always logged in hybrid_breakpoint_add(), do not print it again */ - if (ERROR_OK == retval) - command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); + if (retval == ERROR_OK) + command_print(cmd, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); } return retval; } @@ -3756,13 +4022,13 @@ COMMAND_HANDLER(handle_bp_command) switch (CMD_ARGC) { case 0: - return handle_bp_command_list(CMD_CTX); + return handle_bp_command_list(CMD); case 2: asid = 0; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + return handle_bp_command_set(CMD, addr, asid, length, hw); case 3: if (strcmp(CMD_ARGV[2], "hw") == 0) { @@ -3770,13 +4036,13 @@ COMMAND_HANDLER(handle_bp_command) COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); asid = 0; - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + return handle_bp_command_set(CMD, addr, asid, length, hw); } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) { hw = BKPT_HARD; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); addr = 0; - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + return handle_bp_command_set(CMD, addr, asid, length, hw); } /* fallthrough */ case 4: @@ -3784,7 +4050,7 @@ COMMAND_HANDLER(handle_bp_command) COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + return handle_bp_command_set(CMD, addr, asid, length, hw); default: return ERROR_COMMAND_SYNTAX_ERROR; @@ -3796,11 +4062,16 @@ COMMAND_HANDLER(handle_rbp_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - target_addr_t addr; - COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - struct target *target = get_current_target(CMD_CTX); - breakpoint_remove(target, addr); + + if (!strcmp(CMD_ARGV[0], "all")) { + breakpoint_remove_all(target); + } else { + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + + breakpoint_remove(target, addr); + } return ERROR_OK; } @@ -3813,7 +4084,7 @@ COMMAND_HANDLER(handle_wp_command) struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { - command_print(CMD_CTX, "address: " TARGET_ADDR_FMT + command_print(CMD, "address: " TARGET_ADDR_FMT ", len: 0x%8.8" PRIx32 ", r/w/a: %i, value: 0x%8.8" PRIx32 ", mask: 0x%8.8" PRIx32, @@ -3828,7 +4099,7 @@ COMMAND_HANDLER(handle_wp_command) } enum watchpoint_rw type = WPT_ACCESS; - uint32_t addr = 0; + target_addr_t addr = 0; uint32_t length = 0; uint32_t data_value = 0x0; uint32_t data_mask = 0xffffffff; @@ -3858,7 +4129,7 @@ COMMAND_HANDLER(handle_wp_command) /* fall through */ case 2: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); break; default: @@ -3867,7 +4138,7 @@ COMMAND_HANDLER(handle_wp_command) int retval = watchpoint_add(target, addr, length, type, data_value, data_mask); - if (ERROR_OK != retval) + if (retval != ERROR_OK) LOG_ERROR("Failure setting watchpoints"); return retval; @@ -3878,8 +4149,8 @@ COMMAND_HANDLER(handle_rwp_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); struct target *target = get_current_target(CMD_CTX); watchpoint_remove(target, addr); @@ -3905,49 +4176,49 @@ COMMAND_HANDLER(handle_virt2phys_command) 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 " TARGET_ADDR_FMT "", pa); + command_print(CMD, "Physical address " TARGET_ADDR_FMT "", pa); return retval; } -static void writeData(FILE *f, const void *data, size_t len) +static void write_data(FILE *f, const void *data, size_t len) { size_t written = fwrite(data, 1, len, f); if (written != len) LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno)); } -static void writeLong(FILE *f, int l, struct target *target) +static void write_long(FILE *f, int l, struct target *target) { uint8_t val[4]; target_buffer_set_u32(target, val, l); - writeData(f, val, 4); + write_data(f, val, 4); } -static void writeString(FILE *f, char *s) +static void write_string(FILE *f, char *s) { - writeData(f, s, strlen(s)); + write_data(f, s, strlen(s)); } typedef unsigned char UNIT[2]; /* unit of profiling */ /* Dump a gmon.out histogram file. */ -static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range, +static void write_gmon(uint32_t *samples, uint32_t sample_num, const char *filename, bool with_range, uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms) { uint32_t i; FILE *f = fopen(filename, "w"); - if (f == NULL) + if (!f) return; - writeString(f, "gmon"); - writeLong(f, 0x00000001, target); /* Version */ - writeLong(f, 0, target); /* padding */ - writeLong(f, 0, target); /* padding */ - writeLong(f, 0, target); /* padding */ + write_string(f, "gmon"); + write_long(f, 0x00000001, target); /* Version */ + write_long(f, 0, target); /* padding */ + write_long(f, 0, target); /* padding */ + write_long(f, 0, target); /* padding */ uint8_t zero = 0; /* GMON_TAG_TIME_HIST */ - writeData(f, &zero, 1); + write_data(f, &zero, 1); /* figure out bucket size */ uint32_t min; @@ -3958,7 +4229,7 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena } else { min = samples[0]; max = samples[0]; - for (i = 0; i < sampleNum; i++) { + for (i = 0; i < sample_num; i++) { if (min > samples[i]) min = samples[i]; if (max < samples[i]) @@ -3970,50 +4241,50 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena max++; } - int addressSpace = max - min; - assert(addressSpace >= 2); + int address_space = max - min; + assert(address_space >= 2); /* FIXME: What is the reasonable number of buckets? * The profiling result will be more accurate if there are enough buckets. */ - static const uint32_t maxBuckets = 128 * 1024; /* maximum buckets. */ - uint32_t numBuckets = addressSpace / sizeof(UNIT); - if (numBuckets > maxBuckets) - numBuckets = maxBuckets; - int *buckets = malloc(sizeof(int) * numBuckets); - if (buckets == NULL) { + static const uint32_t max_buckets = 128 * 1024; /* maximum buckets. */ + uint32_t num_buckets = address_space / sizeof(UNIT); + if (num_buckets > max_buckets) + num_buckets = max_buckets; + int *buckets = malloc(sizeof(int) * num_buckets); + if (!buckets) { fclose(f); return; } - memset(buckets, 0, sizeof(int) * numBuckets); - for (i = 0; i < sampleNum; i++) { + memset(buckets, 0, sizeof(int) * num_buckets); + for (i = 0; i < sample_num; i++) { uint32_t address = samples[i]; if ((address < min) || (max <= address)) continue; long long a = address - min; - long long b = numBuckets; - long long c = addressSpace; + long long b = num_buckets; + long long c = address_space; 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)) */ - writeLong(f, min, target); /* low_pc */ - writeLong(f, max, target); /* high_pc */ - writeLong(f, numBuckets, target); /* # of buckets */ - float sample_rate = sampleNum / (duration_ms / 1000.0); - writeLong(f, sample_rate, target); - writeString(f, "seconds"); + write_long(f, min, target); /* low_pc */ + write_long(f, max, target); /* high_pc */ + write_long(f, num_buckets, target); /* # of buckets */ + float sample_rate = sample_num / (duration_ms / 1000.0); + write_long(f, sample_rate, target); + write_string(f, "seconds"); for (i = 0; i < (15-strlen("seconds")); i++) - writeData(f, &zero, 1); - writeString(f, "s"); + write_data(f, &zero, 1); + write_string(f, "s"); /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ - char *data = malloc(2 * numBuckets); - if (data != NULL) { - for (i = 0; i < numBuckets; i++) { + char *data = malloc(2 * num_buckets); + if (data) { + for (i = 0; i < num_buckets; i++) { int val; val = buckets[i]; if (val > 65535) @@ -4022,7 +4293,7 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena data[i * 2 + 1] = (val >> 8) & 0xff; } free(buckets); - writeData(f, data, numBuckets * 2); + write_data(f, data, num_buckets * 2); free(data); } else free(buckets); @@ -4043,11 +4314,12 @@ COMMAND_HANDLER(handle_profile_command) uint32_t offset; uint32_t num_of_samples; int retval = ERROR_OK; + bool halted_before_profiling = target->state == TARGET_HALTED; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset); uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM); - if (samples == NULL) { + if (!samples) { LOG_ERROR("No memory to store samples."); return ERROR_FAIL; } @@ -4073,12 +4345,23 @@ COMMAND_HANDLER(handle_profile_command) free(samples); return retval; } - if (target->state == TARGET_RUNNING) { + + if (target->state == TARGET_RUNNING && halted_before_profiling) { + /* The target was halted before we started and is running now. Halt it, + * for consistency. */ retval = target_halt(target); if (retval != ERROR_OK) { free(samples); return retval; } + } else if (target->state == TARGET_HALTED && !halted_before_profiling) { + /* The target was running before we started and is halted now. Resume + * it, for consistency. */ + retval = target_resume(target, 1, 0, 0, 0); + if (retval != ERROR_OK) { + free(samples); + return retval; + } } retval = target_poll(target); @@ -4098,34 +4381,35 @@ COMMAND_HANDLER(handle_profile_command) write_gmon(samples, num_of_samples, CMD_ARGV[1], with_range, start_address, end_address, target, duration_ms); - command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]); + command_print(CMD, "Wrote %s", CMD_ARGV[1]); free(samples); return retval; } -static int new_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t val) +static int new_u64_array_element(Jim_Interp *interp, const char *varname, int idx, uint64_t val) { char *namebuf; - Jim_Obj *nameObjPtr, *valObjPtr; + Jim_Obj *obj_name, *obj_val; int result; namebuf = alloc_printf("%s(%d)", varname, idx); if (!namebuf) return JIM_ERR; - nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); - valObjPtr = Jim_NewIntObj(interp, val); - if (!nameObjPtr || !valObjPtr) { + obj_name = Jim_NewStringObj(interp, namebuf, -1); + jim_wide wide_val = val; + obj_val = Jim_NewWideObj(interp, wide_val); + if (!obj_name || !obj_val) { free(namebuf); return JIM_ERR; } - Jim_IncrRefCount(nameObjPtr); - Jim_IncrRefCount(valObjPtr); - result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); - Jim_DecrRefCount(interp, nameObjPtr); - Jim_DecrRefCount(interp, valObjPtr); + Jim_IncrRefCount(obj_name); + Jim_IncrRefCount(obj_val); + result = Jim_SetVariable(interp, obj_name, obj_val); + Jim_DecrRefCount(interp, obj_name); + Jim_DecrRefCount(interp, obj_val); free(namebuf); /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ return result; @@ -4137,10 +4421,10 @@ static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct target *target; context = current_command_context(interp); - assert(context != NULL); + assert(context); target = get_current_target(context); - if (target == NULL) { + if (!target) { LOG_ERROR("mem2array: no current target"); return JIM_ERR; } @@ -4150,67 +4434,65 @@ static int jim_mem2array(Jim_Interp *interp, 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; - int len; - uint32_t addr; - uint32_t count; - uint32_t v; - const char *varname; - const char *phys; - bool is_phys; - int n, e, retval; - uint32_t i; + int e; - /* argv[1] = name of array to receive the data - * argv[2] = desired width - * argv[3] = memory address - * argv[4] = count of times to read + /* argv[0] = name of array to receive the data + * argv[1] = desired element width in bits + * argv[2] = memory address + * argv[3] = count of times to read + * argv[4] = optional "phys" */ - if (argc < 4 || argc > 5) { Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); return JIM_ERR; } - varname = Jim_GetString(argv[0], &len); - /* given "foo" get space for worse case "foo(%d)" .. add 20 */ + /* Arg 0: Name of the array variable */ + const char *varname = Jim_GetString(argv[0], NULL); + + /* Arg 1: Bit width of one element */ + long l; e = Jim_GetLong(interp, argv[1], &l); - width = l; if (e != JIM_OK) return e; + const unsigned int width_bits = l; + + if (width_bits != 8 && + width_bits != 16 && + width_bits != 32 && + width_bits != 64) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "Invalid width param. Must be one of: 8, 16, 32 or 64.", NULL); + return JIM_ERR; + } + const unsigned int width = width_bits / 8; - e = Jim_GetLong(interp, argv[2], &l); - addr = l; + /* Arg 2: Memory address */ + jim_wide wide_addr; + e = Jim_GetWide(interp, argv[2], &wide_addr); if (e != JIM_OK) return e; + target_addr_t addr = (target_addr_t)wide_addr; + + /* Arg 3: Number of elements to read */ e = Jim_GetLong(interp, argv[3], &l); - len = l; if (e != JIM_OK) return e; - is_phys = false; + size_t len = l; + + /* Arg 4: phys */ + bool is_phys = false; if (argc > 4) { - phys = Jim_GetString(argv[4], &n); - if (!strncmp(phys, "phys", n)) + int str_len = 0; + const char *phys = Jim_GetString(argv[4], &str_len); + if (!strncmp(phys, "phys", str_len)) is_phys = true; else return JIM_ERR; } - switch (width) { - case 8: - width = 1; - break; - case 16: - width = 2; - break; - case 32: - width = 4; - break; - default: - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL); - return JIM_ERR; - } + + /* Argument checks */ if (len == 0) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); @@ -4221,21 +4503,22 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); return JIM_ERR; } - /* absurd transfer size? */ if (len > 65536) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "mem2array: too large read request, exceeds 64K items", NULL); return JIM_ERR; } if ((width == 1) || ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0))) { - /* all is well */ + ((width == 4) && ((addr & 3) == 0)) || + ((width == 8) && ((addr & 7) == 0))) { + /* alignment correct */ } else { char buf[100]; Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", + sprintf(buf, "mem2array address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", addr, width); Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); @@ -4245,40 +4528,42 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, /* Transfer loop */ /* index counter */ - n = 0; + size_t idx = 0; - size_t buffersize = 4096; + const size_t buffersize = 4096; uint8_t *buffer = malloc(buffersize); - if (buffer == NULL) + if (!buffer) return JIM_ERR; /* assume ok */ e = JIM_OK; while (len) { /* Slurp... in buffer size chunks */ + const unsigned int max_chunk_len = buffersize / width; + const size_t chunk_len = MIN(len, max_chunk_len); /* in elements.. */ - count = len; /* in objects.. */ - if (count > (buffersize / width)) - count = (buffersize / width); - + int retval; if (is_phys) - retval = target_read_phys_memory(target, addr, width, count, buffer); + retval = target_read_phys_memory(target, addr, width, chunk_len, buffer); else - retval = target_read_memory(target, addr, width, count, buffer); + retval = target_read_memory(target, addr, width, chunk_len, buffer); if (retval != ERROR_OK) { /* BOO !*/ - LOG_ERROR("mem2array: Read @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + LOG_ERROR("mem2array: Read @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", addr, width, - count); + chunk_len); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); e = JIM_ERR; break; } else { - v = 0; /* shut up gcc */ - for (i = 0; i < count ; i++, n++) { + for (size_t i = 0; i < chunk_len ; i++, idx++) { + uint64_t v = 0; switch (width) { + case 8: + v = target_buffer_get_u64(target, &buffer[i*width]); + break; case 4: v = target_buffer_get_u32(target, &buffer[i*width]); break; @@ -4289,10 +4574,10 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, v = buffer[i] & 0x0ff; break; } - new_int_array_element(interp, varname, n, v); + new_u64_array_element(interp, varname, idx, v); } - len -= count; - addr += count * width; + len -= chunk_len; + addr += chunk_len * width; } } @@ -4303,33 +4588,28 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, return e; } -static int get_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t *val) +static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t idx, uint64_t *val) { - char *namebuf; - Jim_Obj *nameObjPtr, *valObjPtr; - int result; - long l; - - namebuf = alloc_printf("%s(%d)", varname, idx); + char *namebuf = alloc_printf("%s(%zu)", varname, idx); if (!namebuf) return JIM_ERR; - nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); - if (!nameObjPtr) { + Jim_Obj *obj_name = Jim_NewStringObj(interp, namebuf, -1); + if (!obj_name) { free(namebuf); return JIM_ERR; } - Jim_IncrRefCount(nameObjPtr); - valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG); - Jim_DecrRefCount(interp, nameObjPtr); + Jim_IncrRefCount(obj_name); + Jim_Obj *obj_val = Jim_GetVariable(interp, obj_name, JIM_ERRMSG); + Jim_DecrRefCount(interp, obj_name); free(namebuf); - if (valObjPtr == NULL) + if (!obj_val) return JIM_ERR; - result = Jim_GetLong(interp, valObjPtr, &l); - /* printf("%s(%d) => 0%08x\n", varname, idx, val); */ - *val = l; + jim_wide wide_val; + int result = Jim_GetWide(interp, obj_val, &wide_val); + *val = wide_val; return result; } @@ -4339,10 +4619,10 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct target *target; context = current_command_context(interp); - assert(context != NULL); + assert(context); target = get_current_target(context); - if (target == NULL) { + if (!target) { LOG_ERROR("array2mem: no current target"); return JIM_ERR; } @@ -4353,95 +4633,95 @@ static int jim_array2mem(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) { - long l; - uint32_t width; - int len; - uint32_t addr; - uint32_t count; - uint32_t v; - const char *varname; - const char *phys; - bool is_phys; - int n, e, retval; - uint32_t i; + int e; - /* argv[1] = name of array to get the data - * argv[2] = desired width - * argv[3] = memory address - * argv[4] = count to write + /* argv[0] = name of array from which to read the data + * argv[1] = desired element width in bits + * argv[2] = memory address + * argv[3] = number of elements to write + * argv[4] = optional "phys" */ if (argc < 4 || argc > 5) { Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); return JIM_ERR; } - varname = Jim_GetString(argv[0], &len); - /* given "foo" get space for worse case "foo(%d)" .. add 20 */ + /* Arg 0: Name of the array variable */ + const char *varname = Jim_GetString(argv[0], NULL); + + /* Arg 1: Bit width of one element */ + long l; e = Jim_GetLong(interp, argv[1], &l); - width = l; if (e != JIM_OK) return e; + const unsigned int width_bits = l; - e = Jim_GetLong(interp, argv[2], &l); - addr = l; + if (width_bits != 8 && + width_bits != 16 && + width_bits != 32 && + width_bits != 64) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "Invalid width param. Must be one of: 8, 16, 32 or 64.", NULL); + return JIM_ERR; + } + const unsigned int width = width_bits / 8; + + /* Arg 2: Memory address */ + jim_wide wide_addr; + e = Jim_GetWide(interp, argv[2], &wide_addr); if (e != JIM_OK) return e; + target_addr_t addr = (target_addr_t)wide_addr; + + /* Arg 3: Number of elements to write */ e = Jim_GetLong(interp, argv[3], &l); - len = l; if (e != JIM_OK) return e; - is_phys = false; + size_t len = l; + + /* Arg 4: Phys */ + bool is_phys = false; if (argc > 4) { - phys = Jim_GetString(argv[4], &n); - if (!strncmp(phys, "phys", n)) + int str_len = 0; + const char *phys = Jim_GetString(argv[4], &str_len); + if (!strncmp(phys, "phys", str_len)) is_phys = true; else return JIM_ERR; } - switch (width) { - case 8: - width = 1; - break; - case 16: - width = 2; - break; - case 32: - width = 4; - break; - default: - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "Invalid width param, must be 8/16/32", NULL); - return JIM_ERR; - } + + /* Argument checks */ if (len == 0) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL); return JIM_ERR; } + if ((addr + (len * width)) < addr) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL); return JIM_ERR; } - /* absurd transfer size? */ + if (len > 65536) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: absurd > 64K item request", NULL); + "array2mem: too large memory write request, exceeds 64K items", NULL); return JIM_ERR; } if ((width == 1) || ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0))) { - /* all is well */ + ((width == 4) && ((addr & 3) == 0)) || + ((width == 8) && ((addr & 7) == 0))) { + /* alignment correct */ } else { char buf[100]; Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "array2mem address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", + sprintf(buf, "array2mem address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", addr, width); Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); @@ -4450,27 +4730,34 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, /* Transfer loop */ - /* index counter */ - n = 0; /* assume ok */ e = JIM_OK; - size_t buffersize = 4096; + const size_t buffersize = 4096; uint8_t *buffer = malloc(buffersize); - if (buffer == NULL) + if (!buffer) return JIM_ERR; + /* index counter */ + size_t idx = 0; + while (len) { /* Slurp... in buffer size chunks */ + const unsigned int max_chunk_len = buffersize / width; - count = len; /* in objects.. */ - if (count > (buffersize / width)) - count = (buffersize / width); + const size_t chunk_len = MIN(len, max_chunk_len); /* in elements.. */ - v = 0; /* shut up gcc */ - for (i = 0; i < count; i++, n++) { - get_int_array_element(interp, varname, n, &v); + /* Fill the buffer */ + for (size_t i = 0; i < chunk_len; i++, idx++) { + uint64_t v = 0; + if (get_u64_array_element(interp, varname, idx, &v) != JIM_OK) { + free(buffer); + return JIM_ERR; + } switch (width) { + case 8: + target_buffer_set_u64(target, &buffer[i * width], v); + break; case 4: target_buffer_set_u32(target, &buffer[i * width], v); break; @@ -4482,24 +4769,26 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, break; } } - len -= count; + len -= chunk_len; + /* Write the buffer to memory */ + int retval; if (is_phys) - retval = target_write_phys_memory(target, addr, width, count, buffer); + retval = target_write_phys_memory(target, addr, width, chunk_len, buffer); else - retval = target_write_memory(target, addr, width, count, buffer); + retval = target_write_memory(target, addr, width, chunk_len, buffer); if (retval != ERROR_OK) { /* BOO !*/ - LOG_ERROR("array2mem: Write @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + LOG_ERROR("array2mem: Write @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", addr, width, - count); + chunk_len); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); e = JIM_ERR; break; } - addr += count * width; + addr += chunk_len * width; } free(buffer); @@ -4515,15 +4804,16 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, void target_handle_event(struct target *target, enum target_event e) { struct target_event_action *teap; + int retval; - for (teap = target->event_action; teap != NULL; teap = teap->next) { + for (teap = target->event_action; teap; teap = teap->next) { if (teap->event == e) { LOG_DEBUG("target(%d): %s (%s) event: %d (%s) action: %s", target->target_number, target_name(target), target_type_name(target), e, - Jim_Nvp_value2name_simple(nvp_target_event, e)->name, + jim_nvp_value2name_simple(nvp_target_event, e)->name, Jim_GetString(teap->body, NULL)); /* Override current target by the target an event @@ -4534,12 +4824,25 @@ void target_handle_event(struct target *target, enum target_event e) struct target *saved_target_override = cmd_ctx->current_target_override; cmd_ctx->current_target_override = target; - if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) { - Jim_MakeErrorMessage(teap->interp); - command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL)); - } + retval = Jim_EvalObj(teap->interp, teap->body); cmd_ctx->current_target_override = saved_target_override; + + if (retval == ERROR_COMMAND_CLOSE_CONNECTION) + return; + + if (retval == JIM_RETURN) + retval = teap->interp->returnCode; + + if (retval != JIM_OK) { + Jim_MakeErrorMessage(teap->interp); + LOG_USER("Error executing event %s on target %s:\n%s", + jim_nvp_value2name_simple(nvp_target_event, e)->name, + target_name(target), + Jim_GetString(Jim_GetResult(teap->interp), NULL)); + /* clean both error code and stacktrace before return */ + Jim_Eval(teap->interp, "error \"\" \"\""); + } } } } @@ -4551,7 +4854,7 @@ 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) { + for (teap = target->event_action; teap; teap = teap->next) { if (teap->event == event) return true; } @@ -4572,28 +4875,30 @@ enum target_cfg_param { TCFG_RTOS, TCFG_DEFER_EXAMINE, TCFG_GDB_PORT, + TCFG_GDB_MAX_CONNECTIONS, }; -static Jim_Nvp nvp_config_opts[] = { +static struct jim_nvp nvp_config_opts[] = { { .name = "-type", .value = TCFG_TYPE }, { .name = "-event", .value = TCFG_EVENT }, { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT }, { .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS }, { .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE }, { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP }, - { .name = "-endian" , .value = TCFG_ENDIAN }, + { .name = "-endian", .value = TCFG_ENDIAN }, { .name = "-coreid", .value = TCFG_COREID }, { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, { .name = "-dbgbase", .value = TCFG_DBGBASE }, { .name = "-rtos", .value = TCFG_RTOS }, { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, { .name = "-gdb-port", .value = TCFG_GDB_PORT }, + { .name = "-gdb-max-connections", .value = TCFG_GDB_MAX_CONNECTIONS }, { .name = NULL, .value = -1 } }; -static int target_configure(Jim_GetOptInfo *goi, struct target *target) +static int target_configure(struct jim_getopt_info *goi, struct target *target) { - Jim_Nvp *n; + struct jim_nvp *n; Jim_Obj *o; jim_wide w; int e; @@ -4601,7 +4906,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) /* parse config or cget options ... */ while (goi->argc > 0) { Jim_SetEmptyResult(goi->interp); - /* Jim_GetOpt_Debug(goi); */ + /* jim_getopt_debug(goi); */ if (target->type->target_jim_configure) { /* target defines a configure function */ @@ -4617,14 +4922,14 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) } /* otherwise we 'continue' below */ } - e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); + e = jim_getopt_nvp(goi, nvp_config_opts, &n); if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0); + jim_getopt_nvp_unknown(goi, nvp_config_opts, 0); return e; } switch (n->value) { case TCFG_TYPE: - /* not setable */ + /* not settable */ if (goi->isconfigure) { Jim_SetResultFormatted(goi->interp, "not settable: %s", n->name); @@ -4648,9 +4953,9 @@ no_params: return JIM_ERR; } - e = Jim_GetOpt_Nvp(goi, nvp_target_event, &n); + e = jim_getopt_nvp(goi, nvp_target_event, &n); if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(goi, nvp_target_event, 1); + jim_getopt_nvp_unknown(goi, nvp_target_event, 1); return e; } @@ -4678,15 +4983,20 @@ no_params: } if (goi->isconfigure) { + /* START_DEPRECATED_TPIU */ + if (n->value == TARGET_EVENT_TRACE_CONFIG) + LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); + /* END_DEPRECATED_TPIU */ + bool replace = true; - if (teap == NULL) { + if (!teap) { /* create new */ teap = calloc(1, sizeof(*teap)); replace = false; } teap->event = n->value; teap->interp = goi->interp; - Jim_GetOpt_Obj(goi, &o); + jim_getopt_obj(goi, &o); if (teap->body) Jim_DecrRefCount(teap->interp, teap->body); teap->body = Jim_DuplicateObj(goi->interp, o); @@ -4710,7 +5020,7 @@ no_params: Jim_SetEmptyResult(goi->interp); } else { /* get */ - if (teap == NULL) + if (!teap) Jim_SetEmptyResult(goi->interp); else Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); @@ -4722,7 +5032,7 @@ no_params: case TCFG_WORK_AREA_VIRT: if (goi->isconfigure) { target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); + e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; target->working_area_virt = w; @@ -4738,7 +5048,7 @@ no_params: case TCFG_WORK_AREA_PHYS: if (goi->isconfigure) { target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); + e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; target->working_area_phys = w; @@ -4754,7 +5064,7 @@ no_params: case TCFG_WORK_AREA_SIZE: if (goi->isconfigure) { target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); + e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; target->working_area_size = w; @@ -4769,7 +5079,7 @@ no_params: case TCFG_WORK_AREA_BACKUP: if (goi->isconfigure) { target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); + e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; /* make this exactly 1 or 0 */ @@ -4785,9 +5095,9 @@ no_params: case TCFG_ENDIAN: if (goi->isconfigure) { - e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n); + e = jim_getopt_nvp(goi, nvp_target_endian, &n); if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(goi, nvp_target_endian, 1); + jim_getopt_nvp_unknown(goi, nvp_target_endian, 1); return e; } target->endianness = n->value; @@ -4795,10 +5105,10 @@ no_params: if (goi->argc != 0) goto no_params; } - n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); - if (n->name == NULL) { + n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness); + if (!n->name) { target->endianness = TARGET_LITTLE_ENDIAN; - n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); + n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness); } Jim_SetResultString(goi->interp, n->name, -1); /* loop for more */ @@ -4806,7 +5116,7 @@ no_params: case TCFG_COREID: if (goi->isconfigure) { - e = Jim_GetOpt_Wide(goi, &w); + e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; target->coreid = (int32_t)w; @@ -4814,7 +5124,7 @@ no_params: if (goi->argc != 0) goto no_params; } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->coreid)); /* loop for more */ break; @@ -4830,11 +5140,11 @@ no_params: } target_free_all_working_areas(target); - e = Jim_GetOpt_Obj(goi, &o_t); + e = jim_getopt_obj(goi, &o_t); if (e != JIM_OK) return e; tap = jtag_tap_by_jim_obj(goi->interp, o_t); - if (tap == NULL) + if (!tap) return JIM_ERR; target->tap = tap; target->tap_configured = true; @@ -4847,7 +5157,7 @@ no_params: break; case TCFG_DBGBASE: if (goi->isconfigure) { - e = Jim_GetOpt_Wide(goi, &w); + e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; target->dbgbase = (uint32_t)w; @@ -4877,18 +5187,44 @@ no_params: case TCFG_GDB_PORT: if (goi->isconfigure) { + struct command_context *cmd_ctx = current_command_context(goi->interp); + if (cmd_ctx->mode != COMMAND_CONFIG) { + Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1); + return JIM_ERR; + } + const char *s; - e = Jim_GetOpt_String(goi, &s, NULL); + e = jim_getopt_string(goi, &s, NULL); if (e != JIM_OK) return e; + free(target->gdb_port_override); target->gdb_port_override = strdup(s); } else { if (goi->argc != 0) goto no_params; } - Jim_SetResultString(goi->interp, target->gdb_port_override ? : "undefined", -1); + Jim_SetResultString(goi->interp, target->gdb_port_override ? target->gdb_port_override : "undefined", -1); /* loop for more */ break; + + case TCFG_GDB_MAX_CONNECTIONS: + if (goi->isconfigure) { + struct command_context *cmd_ctx = current_command_context(goi->interp); + if (cmd_ctx->mode != COMMAND_CONFIG) { + Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1); + return JIM_ERR; + } + + e = jim_getopt_wide(goi, &w); + if (e != JIM_OK) + return e; + target->gdb_max_connections = (w < 0) ? CONNECTION_LIMIT_UNLIMITED : (int)w; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->gdb_max_connections)); + break; } } /* while (goi->argc) */ @@ -4899,252 +5235,37 @@ no_params: static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - Jim_GetOptInfo goi; + struct command *c = jim_to_command(interp); + struct jim_getopt_info goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); + goi.isconfigure = !strcmp(c->name, "configure"); if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option ..."); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(goi.interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target_configure(&goi, target); } -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); - - if (goi.argc < 2 || goi.argc > 4) { - Jim_SetResultFormatted(goi.interp, - "usage: %s [phys]
[]", cmd_name); - return JIM_ERR; - } - - target_write_fn fn; - fn = target_write_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_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; - } - - /* all args must be consumed */ - if (goi.argc != 0) - 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; - } - - return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR; -} - -/** -* @brief Reads an array of words/halfwords/bytes from target memory starting at specified address. -* -* Usage: mdw [phys]
[] - for 32 bit reads -* mdh [phys]
[] - for 16 bit reads -* mdb [phys]
[] - for 8 bit reads -* -* Count defaults to 1. -* -* Calls target_read_memory or target_read_phys_memory depending on -* the presence of the "phys" argument -* Reads the target memory in blocks of max. 32 bytes, and returns an array of ints formatted -* to int representation in base16. -* Also outputs read data in a human readable form using command_print -* -* @param phys if present target_read_phys_memory will be used instead of target_read_memory -* @param address address where to start the read. May be specified in decimal or hex using the standard "0x" prefix -* @param count optional count parameter to read an array of values. If not specified, defaults to 1. -* @returns: JIM_ERR on error or JIM_OK on success and sets the result string to an array of ascii formatted numbers -* on success, with [] number of elements. -* -* In case of little endian target: -* Example1: "mdw 0x00000000" returns "10123456" -* Exmaple2: "mdh 0x00000000 1" returns "3456" -* Example3: "mdb 0x00000000" returns "56" -* Example4: "mdh 0x00000000 2" returns "3456 1012" -* Example5: "mdb 0x00000000 3" returns "56 34 12" -**/ -static int jim_target_md(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); - - if ((goi.argc < 1) || (goi.argc > 3)) { - Jim_SetResultFormatted(goi.interp, - "usage: %s [phys]
[]", cmd_name); - return JIM_ERR; - } - - int (*fn)(struct target *target, - target_addr_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; - } - - /* Read address parameter */ - jim_wide addr; - e = Jim_GetOpt_Wide(&goi, &addr); - if (e != JIM_OK) - return JIM_ERR; - - /* If next parameter exists, read it out as the count parameter, if not, set it to 1 (default) */ - jim_wide count; - if (goi.argc == 1) { - e = Jim_GetOpt_Wide(&goi, &count); - if (e != JIM_OK) - return JIM_ERR; - } else - count = 1; - - /* all args must be consumed */ - if (goi.argc != 0) - return JIM_ERR; - - jim_wide dwidth = 1; /* shut up gcc */ - if (strcasecmp(cmd_name, "mdw") == 0) - dwidth = 4; - else if (strcasecmp(cmd_name, "mdh") == 0) - dwidth = 2; - else if (strcasecmp(cmd_name, "mdb") == 0) - dwidth = 1; - else { - LOG_ERROR("command '%s' unknown: ", cmd_name); - return JIM_ERR; - } - - /* convert count to "bytes" */ - int bytes = count * dwidth; - - struct target *target = Jim_CmdPrivData(goi.interp); - uint8_t target_buf[32]; - jim_wide x, y, z; - while (bytes > 0) { - y = (bytes < 16) ? bytes : 16; /* y = min(bytes, 16); */ - - /* Try to read out next block */ - e = fn(target, addr, dwidth, y / dwidth, target_buf); - - if (e != ERROR_OK) { - Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr); - return JIM_ERR; - } - - command_print_sameline(NULL, "0x%08x ", (int)(addr)); - switch (dwidth) { - case 4: - for (x = 0; x < 16 && x < y; x += 4) { - z = target_buffer_get_u32(target, &(target_buf[x])); - command_print_sameline(NULL, "%08x ", (int)(z)); - } - for (; (x < 16) ; x += 4) - command_print_sameline(NULL, " "); - break; - case 2: - for (x = 0; x < 16 && x < y; x += 2) { - z = target_buffer_get_u16(target, &(target_buf[x])); - command_print_sameline(NULL, "%04x ", (int)(z)); - } - for (; (x < 16) ; x += 2) - command_print_sameline(NULL, " "); - break; - case 1: - default: - for (x = 0 ; (x < 16) && (x < y) ; x += 1) { - z = target_buffer_get_u8(target, &(target_buf[x])); - command_print_sameline(NULL, "%02x ", (int)(z)); - } - for (; (x < 16) ; x += 1) - command_print_sameline(NULL, " "); - break; - } - /* 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] = '.'; - } - } - /* space pad */ - while (x < 16) { - target_buf[x] = ' '; - x++; - } - /* terminate */ - target_buf[16] = 0; - /* print - with a newline */ - command_print_sameline(NULL, "%s\n", target_buf); - /* NEXT... */ - bytes -= 16; - addr += 16; - } - return JIM_OK; -} - static int jim_target_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target_mem2array(interp, target, argc - 1, argv + 1); } static int jim_target_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); return target_array2mem(interp, target, argc - 1, argv + 1); } @@ -5158,8 +5279,8 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv { bool allow_defer = false; - Jim_GetOptInfo goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + struct jim_getopt_info 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, @@ -5169,14 +5290,16 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv if (goi.argc > 0 && strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) { /* consume it */ - struct Jim_Obj *obj; - int e = Jim_GetOpt_Obj(&goi, &obj); + Jim_Obj *obj; + int e = jim_getopt_obj(&goi, &obj); if (e != JIM_OK) return e; allow_defer = true; } - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5187,14 +5310,21 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv } int e = target->type->examine(target); - if (e != ERROR_OK) + if (e != ERROR_OK) { + target_reset_examined(target); return JIM_ERR; + } + + target_set_examined(target); + return JIM_OK; } static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); Jim_SetResultBool(interp, target_was_examined(target)); return JIM_OK; @@ -5202,7 +5332,9 @@ static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); Jim_SetResultBool(interp, target->defer_examine); return JIM_OK; @@ -5214,7 +5346,9 @@ static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *arg Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) return JIM_ERR; @@ -5228,7 +5362,9 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5244,8 +5380,8 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 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); + struct jim_getopt_info goi; + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); if (goi.argc != 2) { Jim_WrongNumArgs(interp, 0, argv, @@ -5253,19 +5389,21 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_ERR; } - Jim_Nvp *n; - int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n); + struct jim_nvp *n; + int e = jim_getopt_nvp(&goi, nvp_assert, &n); if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1); + jim_getopt_nvp_unknown(&goi, nvp_assert, 1); return e; } /* the halt or not param */ jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); + e = jim_getopt_wide(&goi, &a); if (e != JIM_OK) return e; - struct target *target = Jim_CmdPrivData(goi.interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); @@ -5280,7 +5418,7 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) target_reset_examined(target); /* determine if we should halt or not. */ - target->reset_halt = !!a; + target->reset_halt = (a != 0); /* When this happens - all workareas are invalid. */ target_free_all_working_areas_restore(target, 0); @@ -5298,7 +5436,9 @@ static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); if (!target->tap->enabled) return jim_target_tap_disabled(interp); int e = target->type->halt(target); @@ -5307,8 +5447,8 @@ static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 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); + struct jim_getopt_info goi; + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); /* params: statename timeoutmsecs */ if (goi.argc != 2) { @@ -5318,28 +5458,29 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a return JIM_ERR; } - Jim_Nvp *n; - int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n); + struct 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); + jim_getopt_nvp_unknown(&goi, nvp_target_state, 1); return e; } jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); + e = jim_getopt_wide(&goi, &a); if (e != JIM_OK) return e; - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); 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_Obj *obj = 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); + obj, target_strerror_safe(e)); return JIM_ERR; } return JIM_OK; @@ -5347,27 +5488,25 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a /* List for human, Events defined for this target. * scripts/programs should use 'name cget -event NAME' */ -static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +COMMAND_HANDLER(handle_target_event_list) { - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx != NULL); - - struct target *target = Jim_CmdPrivData(interp); + struct target *target = get_current_target(CMD_CTX); struct target_event_action *teap = target->event_action; - command_print(cmd_ctx, "Event actions for target (%d) %s\n", + + command_print(CMD, "Event actions for target (%d) %s\n", target->target_number, target_name(target)); - command_print(cmd_ctx, "%-25s | Body", "Event"); - command_print(cmd_ctx, "------------------------- | " + command_print(CMD, "%-25s | Body", "Event"); + command_print(CMD, "------------------------- | " "----------------------------------------"); while (teap) { - Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event); - command_print(cmd_ctx, "%-25s | %s", + struct jim_nvp *opt = jim_nvp_value2name_simple(nvp_target_event, teap->event); + command_print(CMD, "%-25s | %s", opt->name, Jim_GetString(teap->body, NULL)); teap = teap->next; } - command_print(cmd_ctx, "***END***"); - return JIM_OK; + command_print(CMD, "***END***"); + return ERROR_OK; } static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { @@ -5375,26 +5514,30 @@ static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); 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); + struct jim_getopt_info 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); + struct 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); + jim_getopt_nvp_unknown(&goi, nvp_target_event, 1); return e; } - struct target *target = Jim_CmdPrivData(interp); + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + struct target *target = get_current_target(cmd_ctx); target_handle_event(target, n->value); return JIM_OK; } @@ -5402,7 +5545,7 @@ static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const static const struct command_registration target_instance_command_handlers[] = { { .name = "configure", - .mode = COMMAND_CONFIG, + .mode = COMMAND_ANY, .jim_handler = jim_target_configure, .help = "configure a new target for use", .usage = "[target_attribute ...]", @@ -5414,45 +5557,59 @@ static const struct command_registration target_instance_command_handlers[] = { .help = "returns the specified target attribute", .usage = "target_attribute", }, + { + .name = "mwd", + .handler = handle_mw_command, + .mode = COMMAND_EXEC, + .help = "Write 64-bit word(s) to target memory", + .usage = "address data [count]", + }, { .name = "mww", + .handler = handle_mw_command, .mode = COMMAND_EXEC, - .jim_handler = jim_target_mw, .help = "Write 32-bit word(s) to target memory", .usage = "address data [count]", }, { .name = "mwh", + .handler = handle_mw_command, .mode = COMMAND_EXEC, - .jim_handler = jim_target_mw, .help = "Write 16-bit half-word(s) to target memory", .usage = "address data [count]", }, { .name = "mwb", + .handler = handle_mw_command, .mode = COMMAND_EXEC, - .jim_handler = jim_target_mw, .help = "Write byte(s) to target memory", .usage = "address data [count]", }, + { + .name = "mdd", + .handler = handle_md_command, + .mode = COMMAND_EXEC, + .help = "Display target memory as 64-bit words", + .usage = "address [count]", + }, { .name = "mdw", + .handler = handle_md_command, .mode = COMMAND_EXEC, - .jim_handler = jim_target_md, .help = "Display target memory as 32-bit words", .usage = "address [count]", }, { .name = "mdh", + .handler = handle_md_command, .mode = COMMAND_EXEC, - .jim_handler = jim_target_md, .help = "Display target memory as 16-bit half-words", .usage = "address [count]", }, { .name = "mdb", + .handler = handle_md_command, .mode = COMMAND_EXEC, - .jim_handler = jim_target_md, .help = "Display target memory as 8-bit bytes", .usage = "address [count]", }, @@ -5474,9 +5631,10 @@ static const struct command_registration target_instance_command_handlers[] = { }, { .name = "eventlist", + .handler = handle_target_event_list, .mode = COMMAND_EXEC, - .jim_handler = jim_target_event_list, .help = "displays a table of events defined for this target", + .usage = "", }, { .name = "curstate", @@ -5543,7 +5701,7 @@ static const struct command_registration target_instance_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static int target_create(Jim_GetOptInfo *goi) +static int target_create(struct jim_getopt_info *goi) { Jim_Obj *new_cmd; Jim_Cmd *cmd; @@ -5554,7 +5712,7 @@ static int target_create(Jim_GetOptInfo *goi) struct command_context *cmd_ctx; cmd_ctx = current_command_context(goi->interp); - assert(cmd_ctx != NULL); + assert(cmd_ctx); if (goi->argc < 3) { Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options..."); @@ -5562,9 +5720,9 @@ static int target_create(Jim_GetOptInfo *goi) } /* COMMAND */ - Jim_GetOpt_Obj(goi, &new_cmd); + jim_getopt_obj(goi, &new_cmd); /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); + cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE); if (cmd) { cp = Jim_GetString(new_cmd, NULL); Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); @@ -5572,7 +5730,7 @@ static int target_create(Jim_GetOptInfo *goi) } /* TYPE */ - e = Jim_GetOpt_String(goi, &cp, NULL); + e = jim_getopt_string(goi, &cp, NULL); if (e != JIM_OK) return e; struct transport *tr = get_current_transport(); @@ -5586,21 +5744,12 @@ static int target_create(Jim_GetOptInfo *goi) } /* now does target type exist */ for (x = 0 ; target_types[x] ; x++) { - if (0 == strcmp(cp, target_types[x]->name)) { + if (strcmp(cp, target_types[x]->name) == 0) { /* found */ break; } - - /* check for deprecated name */ - if (target_types[x]->deprecated_name) { - if (0 == strcmp(cp, target_types[x]->deprecated_name)) { - /* found */ - LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name); - break; - } - } } - if (target_types[x] == NULL) { + if (!target_types[x]) { Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); for (x = 0 ; target_types[x] ; x++) { if (target_types[x + 1]) { @@ -5620,18 +5769,24 @@ static int target_create(Jim_GetOptInfo *goi) /* Create it */ target = calloc(1, sizeof(struct target)); + if (!target) { + LOG_ERROR("Out of memory"); + return JIM_ERR; + } + /* set target number */ target->target_number = new_target_number(); - cmd_ctx->current_target = target; /* allocate memory for each unique target type */ - target->type = calloc(1, sizeof(struct target_type)); + target->type = malloc(sizeof(struct target_type)); + if (!target->type) { + LOG_ERROR("Out of memory"); + free(target); + return JIM_ERR; + } memcpy(target->type, target_types[x], sizeof(struct target_type)); - /* will be set by "-endian" */ - target->endianness = TARGET_ENDIAN_UNKNOWN; - /* default to first core, override with -coreid */ target->coreid = 0; @@ -5654,6 +5809,12 @@ static int target_create(Jim_GetOptInfo *goi) /* initialize trace information */ target->trace_info = calloc(1, sizeof(struct trace)); + if (!target->trace_info) { + LOG_ERROR("Out of memory"); + free(target->type); + free(target); + return JIM_ERR; + } target->dbgmsg = NULL; target->dbg_msg_enabled = 0; @@ -5664,6 +5825,7 @@ static int target_create(Jim_GetOptInfo *goi) target->rtos_auto_detect = false; target->gdb_port_override = NULL; + target->gdb_max_connections = 1; /* Do the rest as "configure" options */ goi->isconfigure = 1; @@ -5682,12 +5844,14 @@ static int target_create(Jim_GetOptInfo *goi) } } /* tap must be set after target was configured */ - if (target->tap == NULL) + if (!target->tap) e = JIM_ERR; } if (e != JIM_OK) { + rtos_destroy(target); free(target->gdb_port_override); + free(target->trace_info); free(target->type); free(target); return e; @@ -5700,14 +5864,25 @@ static int target_create(Jim_GetOptInfo *goi) cp = Jim_GetString(new_cmd, NULL); target->cmd_name = strdup(cp); + if (!target->cmd_name) { + LOG_ERROR("Out of memory"); + rtos_destroy(target); + free(target->gdb_port_override); + free(target->trace_info); + free(target->type); + free(target); + return JIM_ERR; + } if (target->type->target_create) { e = (*(target->type->target_create))(target, goi->interp); if (e != ERROR_OK) { LOG_DEBUG("target_create failed"); + free(target->cmd_name); + rtos_destroy(target); free(target->gdb_port_override); + free(target->trace_info); free(target->type); - free(target->cmd_name); free(target); return JIM_ERR; } @@ -5716,19 +5891,10 @@ static int target_create(Jim_GetOptInfo *goi) /* create the target specific commands */ if (target->type->commands) { e = register_commands(cmd_ctx, NULL, target->type->commands); - if (ERROR_OK != e) + if (e != ERROR_OK) LOG_ERROR("unable to register '%s' commands", cp); } - /* append to end of list */ - { - struct target **tpp; - tpp = &(all_targets); - while (*tpp) - tpp = &((*tpp)->next); - *tpp = target; - } - /* now - create the new target name command */ const struct command_registration target_subcommands[] = { { @@ -5749,15 +5915,24 @@ static int target_create(Jim_GetOptInfo *goi) }, COMMAND_REGISTRATION_DONE }; - e = register_commands(cmd_ctx, NULL, target_commands); - if (ERROR_OK != e) + e = register_commands_override_target(cmd_ctx, NULL, target_commands, target); + if (e != ERROR_OK) { + if (target->type->deinit_target) + target->type->deinit_target(target); + free(target->cmd_name); + rtos_destroy(target); + free(target->gdb_port_override); + free(target->trace_info); + free(target->type); + free(target); return JIM_ERR; + } - struct command *c = command_find_in_context(cmd_ctx, cp); - assert(c); - command_set_handler_data(c, target); + /* append to end of list */ + append_to_list_all_targets(target); - return (ERROR_OK == e) ? JIM_OK : JIM_ERR; + cmd_ctx->current_target = target; + return JIM_OK; } static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv) @@ -5767,9 +5942,11 @@ static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv return JIM_ERR; } struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx != NULL); + assert(cmd_ctx); - Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1); + struct target *target = get_current_target_or_null(cmd_ctx); + if (target) + Jim_SetResultString(interp, target_name(target), -1); return JIM_OK; } @@ -5780,7 +5957,7 @@ static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_ERR; } Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); - for (unsigned x = 0; NULL != target_types[x]; x++) { + for (unsigned x = 0; target_types[x]; x++) { Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, target_types[x]->name, -1)); } @@ -5808,15 +5985,15 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int i; const char *targetname; int retval, len; - struct target *target = (struct target *) NULL; + struct target *target = NULL; struct target_list *head, *curr, *new; - curr = (struct target_list *) NULL; - head = (struct target_list *) NULL; + curr = NULL; + head = NULL; retval = 0; LOG_DEBUG("%d", argc); /* argv[1] = target to associate in smp - * argv[2] = target to assoicate in smp + * argv[2] = target to associate in smp * argv[3] ... */ @@ -5828,8 +6005,8 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (target) { new = malloc(sizeof(struct target_list)); new->target = target; - new->next = (struct target_list *)NULL; - if (head == (struct target_list *)NULL) { + new->next = NULL; + if (!head) { head = new; curr = head; } else { @@ -5841,7 +6018,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* now parse the list of cpu and put the target in smp mode*/ curr = head; - while (curr != (struct target_list *)NULL) { + while (curr) { target = curr->target; target->smp = 1; target->head = head; @@ -5857,8 +6034,8 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 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); + struct jim_getopt_info goi; + jim_getopt_setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 3) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, " [ ...]"); @@ -5873,6 +6050,7 @@ static const struct command_registration target_subcommand_handlers[] = { .mode = COMMAND_CONFIG, .handler = handle_target_init_command, .help = "initialize targets", + .usage = "", }, { .name = "create", @@ -5911,7 +6089,7 @@ static const struct command_registration target_subcommand_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct FastLoad { +struct fast_load { target_addr_t address; uint8_t *data; int length; @@ -5919,16 +6097,13 @@ struct FastLoad { }; static int fastload_num; -static struct FastLoad *fastload; +static struct fast_load *fastload; static void free_fastload(void) { - if (fastload != NULL) { - int i; - for (i = 0; i < fastload_num; i++) { - if (fastload[i].data) - free(fastload[i].data); - } + if (fastload) { + for (int i = 0; i < fastload_num; i++) + free(fastload[i].data); free(fastload); fastload = NULL; } @@ -5941,13 +6116,12 @@ COMMAND_HANDLER(handle_fast_load_image_command) uint32_t image_size; target_addr_t min_address = 0; target_addr_t max_address = -1; - int i; struct image image; - int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, + int retval = CALL_COMMAND_HANDLER(parse_load_image_command, &image, &min_address, &max_address); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; struct duration bench; @@ -5960,17 +6134,17 @@ COMMAND_HANDLER(handle_fast_load_image_command) image_size = 0x0; retval = ERROR_OK; fastload_num = image.num_sections; - fastload = malloc(sizeof(struct FastLoad)*image.num_sections); - if (fastload == NULL) { - command_print(CMD_CTX, "out of memory"); + fastload = malloc(sizeof(struct fast_load)*image.num_sections); + if (!fastload) { + command_print(CMD, "out of memory"); image_close(&image); return ERROR_FAIL; } - memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections); - for (i = 0; i < image.num_sections; i++) { + memset(fastload, 0, sizeof(struct fast_load)*image.num_sections); + for (unsigned int i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); - if (buffer == NULL) { - command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", + if (!buffer) { + command_print(CMD, "error allocating buffer for section (%d bytes)", (int)(image.sections[i].size)); retval = ERROR_FAIL; break; @@ -5985,7 +6159,7 @@ COMMAND_HANDLER(handle_fast_load_image_command) uint32_t offset = 0; uint32_t length = buf_cnt; - /* DANGER!!! beware of unsigned comparision here!!! */ + /* DANGER!!! beware of unsigned comparison here!!! */ if ((image.sections[i].base_address + buf_cnt >= min_address) && (image.sections[i].base_address < max_address)) { @@ -6000,9 +6174,9 @@ COMMAND_HANDLER(handle_fast_load_image_command) fastload[i].address = image.sections[i].base_address + offset; fastload[i].data = malloc(length); - if (fastload[i].data == NULL) { + if (!fastload[i].data) { free(buffer); - command_print(CMD_CTX, "error allocating buffer for section (%" PRIu32 " bytes)", + command_print(CMD, "error allocating buffer for section (%" PRIu32 " bytes)", length); retval = ERROR_FAIL; break; @@ -6011,7 +6185,7 @@ COMMAND_HANDLER(handle_fast_load_image_command) fastload[i].length = length; image_size += length; - command_print(CMD_CTX, "%u bytes written at address 0x%8.8x", + command_print(CMD, "%u bytes written at address 0x%8.8x", (unsigned int)length, ((unsigned int)(image.sections[i].base_address + offset))); } @@ -6019,12 +6193,12 @@ COMMAND_HANDLER(handle_fast_load_image_command) free(buffer); } - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(CMD_CTX, "Loaded %" PRIu32 " bytes " + if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) { + command_print(CMD, "Loaded %" PRIu32 " bytes " "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); - command_print(CMD_CTX, + command_print(CMD, "WARNING: image has not been loaded to target!" "You can issue a 'fast_load' to finish loading."); } @@ -6041,7 +6215,7 @@ COMMAND_HANDLER(handle_fast_load_command) { if (CMD_ARGC > 0) return ERROR_COMMAND_SYNTAX_ERROR; - if (fastload == NULL) { + if (!fastload) { LOG_ERROR("No image in memory"); return ERROR_FAIL; } @@ -6051,7 +6225,7 @@ COMMAND_HANDLER(handle_fast_load_command) int retval = ERROR_OK; for (i = 0; i < fastload_num; i++) { struct target *target = get_current_target(CMD_CTX); - command_print(CMD_CTX, "Write to 0x%08x, length 0x%08x", + command_print(CMD, "Write to 0x%08x, length 0x%08x", (unsigned int)(fastload[i].address), (unsigned int)(fastload[i].length)); retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data); @@ -6061,7 +6235,7 @@ COMMAND_HANDLER(handle_fast_load_command) } if (retval == ERROR_OK) { int64_t after = timeval_ms(); - command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0)); + command_print(CMD, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0)); } return retval; } @@ -6079,8 +6253,8 @@ static const struct command_registration target_command_handlers[] = { .name = "target", .mode = COMMAND_CONFIG, .help = "configure target", - .chain = target_subcommand_handlers, + .usage = "", }, COMMAND_REGISTRATION_DONE }; @@ -6116,7 +6290,7 @@ COMMAND_HANDLER(handle_ps_command) if ((target->rtos) && (target->rtos->type) && (target->rtos->type->ps_command)) { display = target->rtos->type->ps_command(target); - command_print(CMD_CTX, "%s", display); + command_print(CMD, "%s", display); free(display); return ERROR_OK; } else { @@ -6125,13 +6299,13 @@ COMMAND_HANDLER(handle_ps_command) } } -static void binprint(struct command_context *cmd_ctx, const char *text, const uint8_t *buf, int size) +static void binprint(struct command_invocation *cmd, const char *text, const uint8_t *buf, int size) { - if (text != NULL) - command_print_sameline(cmd_ctx, "%s", text); + if (text) + command_print_sameline(cmd, "%s", text); for (int i = 0; i < size; i++) - command_print_sameline(cmd_ctx, " %02x", buf[i]); - command_print(cmd_ctx, " "); + command_print_sameline(cmd, " %02x", buf[i]); + command_print(cmd, " "); } COMMAND_HANDLER(handle_test_mem_access_command) @@ -6183,7 +6357,7 @@ COMMAND_HANDLER(handle_test_mem_access_command) read_ref[i] = rand(); read_buf[i] = read_ref[i]; } - command_print_sameline(CMD_CTX, + command_print_sameline(CMD, "Test read %" PRIu32 " x %d @ %d to %saligned buffer: ", count, size, offset, host_offset ? "un" : ""); @@ -6196,10 +6370,10 @@ COMMAND_HANDLER(handle_test_mem_access_command) duration_measure(&bench); if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { - command_print(CMD_CTX, "Unsupported alignment"); + command_print(CMD, "Unsupported alignment"); goto next; } else if (retval != ERROR_OK) { - command_print(CMD_CTX, "Memory read failed"); + command_print(CMD, "Memory read failed"); goto next; } @@ -6209,13 +6383,13 @@ COMMAND_HANDLER(handle_test_mem_access_command) /* check result */ int result = memcmp(read_ref, read_buf, host_bufsiz); if (result == 0) { - command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", + command_print(CMD, "Pass in %fs (%0.3f KiB/s)", duration_elapsed(&bench), duration_kbps(&bench, count * size)); } else { - command_print(CMD_CTX, "Compare failed"); - binprint(CMD_CTX, "ref:", read_ref, host_bufsiz); - binprint(CMD_CTX, "buf:", read_buf, host_bufsiz); + command_print(CMD, "Compare failed"); + binprint(CMD, "ref:", read_ref, host_bufsiz); + binprint(CMD, "buf:", read_buf, host_bufsiz); } next: free(read_ref); @@ -6227,7 +6401,7 @@ next: out: free(test_pattern); - if (wa != NULL) + if (wa) target_free_working_area(target, wa); /* Test writes */ @@ -6255,13 +6429,13 @@ out: for (size_t i = 0; i < host_bufsiz; i++) write_buf[i] = rand(); - command_print_sameline(CMD_CTX, + command_print_sameline(CMD, "Test write %" PRIu32 " x %d @ %d from %saligned buffer: ", count, size, offset, host_offset ? "un" : ""); retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern); if (retval != ERROR_OK) { - command_print(CMD_CTX, "Test pattern write failed"); + command_print(CMD, "Test pattern write failed"); goto nextw; } @@ -6278,30 +6452,30 @@ out: duration_measure(&bench); if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { - command_print(CMD_CTX, "Unsupported alignment"); + command_print(CMD, "Unsupported alignment"); goto nextw; } else if (retval != ERROR_OK) { - command_print(CMD_CTX, "Memory write failed"); + command_print(CMD, "Memory write failed"); goto nextw; } /* read back */ retval = target_read_memory(target, wa->address, 1, num_bytes, read_buf); if (retval != ERROR_OK) { - command_print(CMD_CTX, "Test pattern write failed"); + command_print(CMD, "Test pattern write failed"); goto nextw; } /* check result */ int result = memcmp(read_ref, read_buf, num_bytes); if (result == 0) { - command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", + command_print(CMD, "Pass in %fs (%0.3f KiB/s)", duration_elapsed(&bench), duration_kbps(&bench, count * size)); } else { - command_print(CMD_CTX, "Compare failed"); - binprint(CMD_CTX, "ref:", read_ref, num_bytes); - binprint(CMD_CTX, "buf:", read_buf, num_bytes); + command_print(CMD, "Compare failed"); + binprint(CMD, "ref:", read_ref, num_bytes); + binprint(CMD, "buf:", read_buf, num_bytes); } nextw: free(read_ref); @@ -6312,7 +6486,7 @@ nextw: free(test_pattern); - if (wa != NULL) + if (wa) target_free_working_area(target, wa); return retval; } @@ -6377,7 +6551,7 @@ static const struct command_registration target_exec_command_handlers[] = { .name = "halt", .handler = handle_halt_command, .mode = COMMAND_EXEC, - .help = "request target to halt, then wait up to the specified" + .help = "request target to halt, then wait up to the specified " "number of milliseconds (default 5000) for it to complete", .usage = "[milliseconds]", }, @@ -6393,7 +6567,7 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_reset_command, .mode = COMMAND_EXEC, .usage = "[run|halt|init]", - .help = "Reset all targets into the specified mode." + .help = "Reset all targets into the specified mode. " "Default reset mode is run, if not given.", }, { @@ -6414,7 +6588,7 @@ static const struct command_registration target_exec_command_handlers[] = { .name = "mdd", .handler = handle_md_command, .mode = COMMAND_EXEC, - .help = "display memory words", + .help = "display memory double-words", .usage = "['phys'] address [count]", }, { @@ -6442,7 +6616,7 @@ static const struct command_registration target_exec_command_handlers[] = { .name = "mwd", .handler = handle_mw_command, .mode = COMMAND_EXEC, - .help = "write memory word", + .help = "write memory double-word", .usage = "['phys'] address value [count]", }, { @@ -6471,14 +6645,14 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_bp_command, .mode = COMMAND_EXEC, .help = "list or set hardware or software breakpoint", - .usage = "
[] ['hw'|'hw_ctx']", + .usage = "[
[] ['hw'|'hw_ctx']]", }, { .name = "rbp", .handler = handle_rbp_command, .mode = COMMAND_EXEC, .help = "remove breakpoint", - .usage = "address", + .usage = "'all' | address", }, { .name = "wp", @@ -6546,15 +6720,15 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_target_reset_nag, .mode = COMMAND_ANY, .help = "Nag after each reset about options that could have been " - "enabled to improve performance. ", + "enabled to improve performance.", .usage = "['enable'|'disable']", }, { .name = "ps", .handler = handle_ps_command, .mode = COMMAND_EXEC, - .help = "list all tasks ", - .usage = " ", + .help = "list all tasks", + .usage = "", }, { .name = "test_mem_access",