X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=d200ebc98427b2a3a71c0ed466ab9453eca9b1f6;hp=ff5aef34c9bd0dd6fd31427284eb5abdb4a9161c;hb=559d08c19ed838f7bb2a77ce56a5a274641111f8;hpb=bc088b302bd0bb43cc9097a9f0b2e7369b0e04e2 diff --git a/src/target/target.c b/src/target/target.c index ff5aef34c9..d200ebc984 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2,7 +2,7 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * - * Copyright (C) 2007-2009 Øyvind Harboe * + * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008, Duane Ellis * @@ -35,6 +35,7 @@ #include #include +#include #include "target.h" #include "target_type.h" @@ -49,6 +50,7 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv); static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv); +static int target_register_user_commands(struct command_context *cmd_ctx); /* targets */ extern struct target_type arm7tdmi_target; @@ -68,8 +70,9 @@ extern struct target_type mips_m4k_target; extern struct target_type avr_target; extern struct target_type dsp563xx_target; extern struct target_type testee_target; +extern struct target_type avr32_ap7k_target; -struct target_type *target_types[] = +static struct target_type *target_types[] = { &arm7tdmi_target, &arm9tdmi_target, @@ -88,12 +91,14 @@ struct target_type *target_types[] = &avr_target, &dsp563xx_target, &testee_target, + &avr32_ap7k_target, NULL, }; struct target *all_targets = NULL; -struct target_event_callback *target_event_callbacks = NULL; -struct target_timer_callback *target_timer_callbacks = NULL; +static struct target_event_callback *target_event_callbacks = NULL; +static struct target_timer_callback *target_timer_callbacks = NULL; +static const int polling_interval = 100; static const Jim_Nvp nvp_assert[] = { { .name = "assert", NVP_ASSERT }, @@ -120,7 +125,7 @@ static const Jim_Nvp nvp_error_target[] = { { .value = -1, .name = NULL } }; -const char *target_strerror_safe(int err) +static const char *target_strerror_safe(int err) { const Jim_Nvp *n; @@ -281,7 +286,7 @@ uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer) } /* read a uint8_t from a buffer in target memory endianness */ -uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) +static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) { return *buffer & 0x0ff; } @@ -305,7 +310,7 @@ void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t valu } /* write a uint8_t to a buffer in target memory endianness */ -void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value) +static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value) { *buffer = value; } @@ -424,6 +429,36 @@ int target_halt(struct target *target) return ERROR_OK; } +/** + * Make the target (re)start executing using its saved execution + * context (possibly with some modifications). + * + * @param target Which target should start executing. + * @param current True to use the target's saved program counter instead + * of the address parameter + * @param address Optionally used as the program counter. + * @param handle_breakpoints True iff breakpoints at the resumption PC + * should be skipped. (For example, maybe execution was stopped by + * such a breakpoint, in which case it would be counterprodutive to + * let it re-trigger. + * @param debug_execution False if all working areas allocated by OpenOCD + * should be released and/or restored to their original contents. + * (This would for example be true to run some downloaded "helper" + * algorithm code, which resides in one such working buffer and uses + * another for data storage.) + * + * @todo Resolve the ambiguity about what the "debug_execution" flag + * signifies. For example, Target implementations don't agree on how + * it relates to invalidation of the register cache, or to whether + * breakpoints and watchpoints should be enabled. (It would seem wrong + * to enable breakpoints when running downloaded "helper" algorithms + * (debug_execution true), since the breakpoints would be set to match + * target firmware being debugged, not the helper algorithm.... and + * enabling them could cause such helpers to malfunction (for example, + * by overwriting data with a breakpoint instruction. On the other + * hand the infrastructure for running such helpers might use this + * procedure but rely on hardware breakpoint to detect termination.) + */ int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { int retval; @@ -435,9 +470,9 @@ int target_resume(struct target *target, int current, uint32_t address, int hand return ERROR_FAIL; } - /* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can - * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?) - * the application. + /* note that resume *must* be asynchronous. The CPU can halt before + * we poll. The CPU can even halt at the current PC as a result of + * a software breakpoint being inserted by (a bug?) the application. */ if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK) return retval; @@ -445,7 +480,7 @@ int target_resume(struct target *target, int current, uint32_t address, int hand return retval; } -int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) +static int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) { char buf[100]; int retval; @@ -470,7 +505,8 @@ int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode jtag_poll_set_enabled(save_poll); if (retval != JIM_OK) { - Jim_PrintErrorMessage(cmd_ctx->interp); + Jim_MakeErrorMessage(cmd_ctx->interp); + command_print(NULL,"%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL)); return ERROR_FAIL; } @@ -590,23 +626,55 @@ static int target_soft_reset_halt_imp(struct target *target) return target->type->soft_reset_halt_imp(target); } -static int target_run_algorithm_imp(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) +/** + * Downloads a target-specific native code algorithm to the target, + * and executes it. * Note that some targets may need to set up, enable, + * and tear down a breakpoint (hard or * soft) to detect algorithm + * termination, while others may support lower overhead schemes where + * soft breakpoints embedded in the algorithm automatically terminate the + * algorithm. + * + * @param target used to run the algorithm + * @param arch_info target-specific description of the algorithm. + */ +int target_run_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_param, + uint32_t entry_point, uint32_t exit_point, + int timeout_ms, void *arch_info) { + int retval = ERROR_FAIL; + if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; + goto done; + } + if (!target->type->run_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; } - return target->type->run_algorithm_imp(target, num_mem_params, mem_params, num_reg_params, reg_param, entry_point, exit_point, timeout_ms, arch_info); + + target->running_alg = true; + retval = target->type->run_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_param, + entry_point, exit_point, timeout_ms, arch_info); + target->running_alg = false; + +done: + return retval; } + int target_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return target->type->read_memory(target, address, size, count, buffer); } -int target_read_phys_memory(struct target *target, +static int target_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return target->type->read_phys_memory(target, address, size, count, buffer); @@ -618,7 +686,7 @@ int target_write_memory(struct target *target, return target->type->write_memory(target, address, size, count, buffer); } -int target_write_phys_memory(struct target *target, +static int target_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { return target->type->write_phys_memory(target, address, size, count, buffer); @@ -672,17 +740,6 @@ int target_step(struct target *target, } -int target_run_algorithm(struct target *target, - int num_mem_params, struct mem_param *mem_params, - int num_reg_params, struct reg_param *reg_param, - uint32_t entry_point, uint32_t exit_point, - int timeout_ms, void *arch_info) -{ - return target->type->run_algorithm(target, - num_mem_params, mem_params, num_reg_params, reg_param, - entry_point, exit_point, timeout_ms, arch_info); -} - /** * Reset the @c examined flag for the given target. * Pure paranoia -- targets are zeroed on allocation. @@ -746,9 +803,6 @@ static int target_init_one(struct command_context *cmd_ctx, type->soft_reset_halt_imp = target->type->soft_reset_halt; type->soft_reset_halt = target_soft_reset_halt_imp; - type->run_algorithm_imp = target->type->run_algorithm; - type->run_algorithm = target_run_algorithm_imp; - /* Sanity-check MMU support ... stub in what we must, to help * implement it in stages, but warn if we need to do so. */ @@ -792,7 +846,7 @@ static int target_init_one(struct command_context *cmd_ctx, return ERROR_OK; } -int target_init(struct command_context *cmd_ctx) +static int target_init(struct command_context *cmd_ctx) { struct target *target; int retval; @@ -812,7 +866,7 @@ int target_init(struct command_context *cmd_ctx) return retval; retval = target_register_timer_callback(&handle_target, - 100, 1, cmd_ctx->interp); + polling_interval, 1, cmd_ctx->interp); if (ERROR_OK != retval) return retval; @@ -925,7 +979,7 @@ int target_unregister_event_callback(int (*callback)(struct target *target, enum return ERROR_OK; } -int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) +static int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) { struct target_timer_callback **p = &target_timer_callbacks; struct target_timer_callback *c = target_timer_callbacks; @@ -1048,7 +1102,7 @@ int target_call_timer_callbacks_now(void) return target_call_timer_callbacks_check_time(0); } -int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area) +int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area) { struct working_area *c = target->working_areas; struct working_area *new_wa = NULL; @@ -1126,8 +1180,6 @@ int target_alloc_working_area(struct target *target, uint32_t size, struct worki if (free_size < size) { - LOG_WARNING("not enough working area available(requested %u, free %u)", - (unsigned)(size), (unsigned)(free_size)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1168,7 +1220,20 @@ int target_alloc_working_area(struct target *target, uint32_t size, struct worki return ERROR_OK; } -int target_free_working_area_restore(struct target *target, struct working_area *area, int restore) +int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area) +{ + int retval; + + retval = target_alloc_working_area_try(target, size, area); + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) + { + LOG_WARNING("not enough working area available(requested %u)", (unsigned)(size)); + } + return retval; + +} + +static int target_free_working_area_restore(struct target *target, struct working_area *area, int restore) { if (area->free) return ERROR_OK; @@ -1197,7 +1262,7 @@ int target_free_working_area(struct target *target, struct working_area *area) /* free resources and restore memory, if restoring memory fails, * free up resources anyway */ -void target_free_all_working_areas_restore(struct target *target, int restore) +static void target_free_all_working_areas_restore(struct target *target, int restore) { struct working_area *c = target->working_areas; @@ -1739,14 +1804,8 @@ static int sense_handler(void) return ERROR_OK; } -static void target_call_event_callbacks_all(enum target_event e) { - struct target *target; - target = all_targets; - while (target) { - target_call_event_callbacks(target, e); - target = target->next; - } -} +static int backoff_times = 0; +static int backoff_count = 0; /* process target state changes */ static int handle_target(void *priv) @@ -1754,6 +1813,12 @@ static int handle_target(void *priv) Jim_Interp *interp = (Jim_Interp *)priv; int retval = ERROR_OK; + if (!is_jtag_poll_safe()) + { + /* polling is disabled currently */ + return ERROR_OK; + } + /* we do not want to recurse here... */ static int recursive = 0; if (! recursive) @@ -1767,7 +1832,7 @@ static int handle_target(void *priv) int did_something = 0; if (runSrstAsserted) { - target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); + LOG_INFO("srst asserted detected, running srst_asserted proc."); Jim_Eval(interp, "srst_asserted"); did_something = 1; } @@ -1778,7 +1843,7 @@ static int handle_target(void *priv) } if (runPowerDropout) { - target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); + LOG_INFO("Power dropout detected, running power_dropout proc."); Jim_Eval(interp, "power_dropout"); did_something = 1; } @@ -1804,6 +1869,14 @@ static int handle_target(void *priv) recursive = 0; } + if (backoff_times > backoff_count) + { + /* do not poll this time as we failed previously */ + backoff_count++; + return ERROR_OK; + } + backoff_count = 0; + /* Poll targets for state changes unless that's globally disabled. * Skip targets that are currently disabled. */ @@ -1820,9 +1893,26 @@ static int handle_target(void *priv) /* polling may fail silently until the target has been examined */ if ((retval = target_poll(target)) != ERROR_OK) { + /* 100ms polling interval. Increase interval between polling up to 5000ms */ + if (backoff_times * polling_interval < 5000) + { + backoff_times *= 2; + backoff_times++; + } + LOG_USER("Polling target failed, GDB will be halted. Polling again in %dms", backoff_times * polling_interval); + + /* Tell GDB to halt the debugger. This allows the user to + * run monitor commands to handle the situation. + */ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); return retval; } + /* Since we succeeded, we reset backoff count */ + if (backoff_times > 0) + { + LOG_USER("Polling succeeded again"); + } + backoff_times = 0; } } @@ -2069,11 +2159,11 @@ COMMAND_HANDLER(handle_halt_command) if (CMD_ARGC == 1) { - unsigned wait; - retval = parse_uint(CMD_ARGV[0], &wait); + unsigned wait_local; + retval = parse_uint(CMD_ARGV[0], &wait_local); if (ERROR_OK != retval) return ERROR_COMMAND_SYNTAX_ERROR; - if (!wait) + if (!wait_local) return ERROR_OK; } @@ -2256,6 +2346,76 @@ COMMAND_HANDLER(handle_md_command) return retval; } +typedef int (*target_write_fn)(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + +static int target_write_memory_fast(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +{ + return target_write_buffer(target, address, size * count, buffer); +} + +static int target_fill_mem(struct target *target, + uint32_t address, + target_write_fn fn, + unsigned data_size, + /* value */ + uint32_t b, + /* count */ + unsigned c) +{ + /* We have to write in reasonably large chunks to be able + * to fill large memory areas with any sane speed */ + const unsigned chunk_size = 16384; + uint8_t *target_buf = malloc(chunk_size * data_size); + if (target_buf == NULL) + { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + for (unsigned i = 0; i < chunk_size; i ++) + { + switch (data_size) + { + case 4: + target_buffer_set_u32(target, target_buf + i*data_size, b); + break; + case 2: + target_buffer_set_u16(target, target_buf + i*data_size, b); + break; + case 1: + target_buffer_set_u8(target, target_buf + i*data_size, b); + break; + default: + exit(-1); + } + } + + int retval = ERROR_OK; + + for (unsigned x = 0; x < c; x += chunk_size) + { + unsigned current; + current = c - x; + if (current > chunk_size) + { + current = chunk_size; + } + retval = fn(target, address + x * data_size, data_size, current, target_buf); + if (retval != ERROR_OK) + { + break; + } + /* avoid GDB timeouts */ + keep_alive(); + } + free(target_buf); + + return retval; +} + + COMMAND_HANDLER(handle_mw_command) { if (CMD_ARGC < 2) @@ -2263,8 +2423,7 @@ COMMAND_HANDLER(handle_mw_command) return ERROR_COMMAND_SYNTAX_ERROR; } bool physical=strcmp(CMD_ARGV[0], "phys")==0; - int (*fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_write_fn fn; if (physical) { CMD_ARGC--; @@ -2272,7 +2431,7 @@ COMMAND_HANDLER(handle_mw_command) fn=target_write_phys_memory; } else { - fn=target_write_memory; + fn = target_write_memory_fast; } if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -2289,35 +2448,22 @@ COMMAND_HANDLER(handle_mw_command) struct target *target = get_current_target(CMD_CTX); unsigned wordsize; - uint8_t value_buf[4]; switch (CMD_NAME[2]) { case 'w': wordsize = 4; - target_buffer_set_u32(target, value_buf, value); break; case 'h': wordsize = 2; - target_buffer_set_u16(target, value_buf, value); break; case 'b': wordsize = 1; - value_buf[0] = value; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - for (unsigned i = 0; i < count; i++) - { - int retval = fn(target, - address + i * wordsize, wordsize, 1, value_buf); - if (ERROR_OK != retval) - return retval; - keep_alive(); - } - - return ERROR_OK; + return target_fill_mem(target, address, fn, wordsize, value, count); } static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, @@ -2438,7 +2584,7 @@ COMMAND_HANDLER(handle_load_image_command) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "downloaded %" PRIu32 " bytes " - "in %fs (%0.3f kb/s)", image_size, + "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } @@ -2451,33 +2597,25 @@ COMMAND_HANDLER(handle_load_image_command) COMMAND_HANDLER(handle_dump_image_command) { struct fileio fileio; - uint8_t buffer[560]; - int retvaltemp; - - + int retval, retvaltemp; + uint32_t address, size; + struct duration bench; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC != 3) - { - command_print(CMD_CTX, "usage: dump_image
"); - return ERROR_OK; - } + return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t address; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address); - uint32_t size; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); - if (fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) - { - return ERROR_OK; - } + retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY); + if (retval != ERROR_OK) + return retval; - struct duration bench; duration_start(&bench); - int retval = ERROR_OK; + retval = ERROR_OK; while (size > 0) { size_t size_written; @@ -2498,16 +2636,20 @@ COMMAND_HANDLER(handle_dump_image_command) address += this_run_size; } - if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK) - return retvaltemp; - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + int filesize; + retval = fileio_size(&fileio, &filesize); + if (retval != ERROR_OK) + return retval; command_print(CMD_CTX, - "dumped %ld bytes in %fs (%0.3f kb/s)", (long)fileio.size, - duration_elapsed(&bench), duration_kbps(&bench, fileio.size)); + "dumped %ld bytes in %fs (%0.3f KiB/s)", (long)filesize, + duration_elapsed(&bench), duration_kbps(&bench, filesize)); } + if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK) + return retvaltemp; + return retval; } @@ -2560,6 +2702,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) } image_size = 0x0; + int diffs = 0; retval = ERROR_OK; for (i = 0; i < image.num_sections; i++) { @@ -2580,7 +2723,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) if (verify) { /* calculate checksum of image */ - image_calculate_checksum(buffer, buf_cnt, &checksum); + retval = image_calculate_checksum(buffer, buf_cnt, &checksum); + if (retval != ERROR_OK) + { + free(buffer); + break; + } retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum); if (retval != ERROR_OK) @@ -2594,7 +2742,10 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) /* failed crc checksum, fall back to a binary compare */ uint8_t *data; - command_print(CMD_CTX, "checksum mismatch - attempting binary compare"); + if (diffs == 0) + { + LOG_ERROR("checksum mismatch - attempting binary compare"); + } data = (uint8_t*)malloc(buf_cnt); @@ -2615,22 +2766,22 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) if (data[t] != buffer[t]) { command_print(CMD_CTX, - "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", + "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", + diffs, (unsigned)(t + image.sections[i].base_address), data[t], buffer[t]); - free(data); - free(buffer); - retval = ERROR_FAIL; - goto done; - } - if ((t%16384) == 0) - { - keep_alive(); + if (diffs++ >= 127) + { + command_print(CMD_CTX, "More than 128 errors, the rest are not printed."); + free(data); + free(buffer); + goto done; + } } + keep_alive(); } } - free(data); } } else @@ -2643,11 +2794,19 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) free(buffer); image_size += buf_cnt; } + if (diffs > 0) + { + command_print(CMD_CTX, "No more differences found."); + } done: + if (diffs > 0) + { + retval = ERROR_FAIL; + } if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "verified %" PRIu32 " bytes " - "in %fs (%0.3f kb/s)", image_size, + "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); } @@ -2935,8 +3094,8 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam long long a = address-min; long long b = length-1; long long c = addressSpace-1; - int index = (a*b)/c; /* danger!!!! int32 overflows */ - buckets[index]++; + int index_t = (a*b)/c; /* danger!!!! int32 overflows */ + buckets[index_t]++; } /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */ @@ -3101,12 +3260,9 @@ static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct command_context *context; struct target *target; - context = Jim_GetAssocData(interp, "context"); - if (context == NULL) - { - LOG_ERROR("mem2array: no command context"); - return JIM_ERR; - } + context = current_command_context(interp); + assert (context != NULL); + target = get_current_target(context); if (target == NULL) { @@ -3297,11 +3453,9 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct command_context *context; struct target *target; - context = Jim_GetAssocData(interp, "context"); - if (context == NULL) { - LOG_ERROR("array2mem: no command context"); - return JIM_ERR; - } + context = current_command_context(interp); + assert (context != NULL); + target = get_current_target(context); if (target == NULL) { LOG_ERROR("array2mem: no current target"); @@ -3456,22 +3610,6 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, return JIM_OK; } -void target_all_handle_event(enum target_event e) -{ - struct target *target; - - LOG_DEBUG("**all*targets: event: %d, %s", - (int)e, - Jim_Nvp_value2name_simple(nvp_target_event, e)->name); - - target = all_targets; - while (target) { - target_handle_event(target, e); - target = target->next; - } -} - - /* FIX? should we propagate errors here rather than printing them * and continuing? */ @@ -3490,7 +3628,8 @@ void target_handle_event(struct target *target, enum target_event e) Jim_GetString(teap->body, NULL)); if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) { - Jim_PrintErrorMessage(teap->interp); + Jim_MakeErrorMessage(teap->interp); + command_print(NULL,"%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL)); } } } @@ -3572,7 +3711,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) case TCFG_TYPE: /* not setable */ if (goi->isconfigure) { - Jim_SetResult_sprintf(goi->interp, + Jim_SetResultFormatted(goi->interp, "not settable: %s", n->name); return JIM_ERR; } else { @@ -3765,7 +3904,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) case TCFG_VARIANT: if (goi->isconfigure) { if (goi->argc < 1) { - Jim_SetResult_sprintf(goi->interp, + Jim_SetResultFormatted(goi->interp, "%s ?STRING?", n->name); return JIM_ERR; @@ -3785,14 +3924,14 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) break; case TCFG_CHAIN_POSITION: if (goi->isconfigure) { - Jim_Obj *o; + Jim_Obj *o_t; struct jtag_tap *tap; target_free_all_working_areas(target); - e = Jim_GetOpt_Obj(goi, &o); + e = Jim_GetOpt_Obj(goi, &o_t); if (e != JIM_OK) { return e; } - tap = jtag_tap_by_jim_obj(goi->interp, o); + tap = jtag_tap_by_jim_obj(goi->interp, o_t); if (tap == NULL) { return JIM_ERR; } @@ -3841,15 +3980,30 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc != 2 && goi.argc != 3) + if (goi.argc < 2 || goi.argc > 4) { - Jim_SetResult_sprintf(goi.interp, - "usage: %s
[]", cmd_name); + Jim_SetResultFormatted(goi.interp, + "usage: %s [phys]
[]", cmd_name); return JIM_ERR; } + target_write_fn fn; + fn = target_write_memory_fast; + + 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; - int e = Jim_GetOpt_Wide(&goi, &a); + e = Jim_GetOpt_Wide(&goi, &a); if (e != JIM_OK) return e; @@ -3859,44 +4013,35 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return e; jim_wide c = 1; - if (goi.argc == 3) + 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); - uint8_t target_buf[32]; + unsigned data_size; if (strcasecmp(cmd_name, "mww") == 0) { - target_buffer_set_u32(target, target_buf, b); - b = 4; + data_size = 4; } else if (strcasecmp(cmd_name, "mwh") == 0) { - target_buffer_set_u16(target, target_buf, b); - b = 2; + data_size = 2; } else if (strcasecmp(cmd_name, "mwb") == 0) { - target_buffer_set_u8(target, target_buf, b); - b = 1; + data_size = 1; } else { LOG_ERROR("command '%s' unknown: ", cmd_name); return JIM_ERR; } - for (jim_wide x = 0; x < c; x++) - { - e = target_write_memory(target, a, b, 1, target_buf); - if (e != ERROR_OK) - { - Jim_SetResult_sprintf(interp, - "Error writing @ 0x%08x: %d\n", (int)(a), e); - return JIM_ERR; - } - /* b = width */ - a = a + b; - } - return JIM_OK; + return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR; } static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) @@ -3906,20 +4051,36 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_GetOptInfo goi; Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - if ((goi.argc == 2) || (goi.argc == 3)) + if ((goi.argc < 1) || (goi.argc > 3)) { - Jim_SetResult_sprintf(goi.interp, - "usage: %s
[]", cmd_name); + Jim_SetResultFormatted(goi.interp, + "usage: %s [phys]
[]", cmd_name); return JIM_ERR; } + int (*fn)(struct target *target, + uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + fn=target_read_memory; + + int e; + if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) + { + /* consume it */ + struct Jim_Obj *obj; + e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + + fn=target_read_phys_memory; + } + jim_wide a; - int e = Jim_GetOpt_Wide(&goi, &a); + e = Jim_GetOpt_Wide(&goi, &a); if (e != JIM_OK) { return JIM_ERR; } jim_wide c; - if (goi.argc) { + if (goi.argc == 1) { e = Jim_GetOpt_Wide(&goi, &c); if (e != JIM_OK) { return JIM_ERR; @@ -3927,6 +4088,13 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } else { c = 1; } + + /* all args must be consumed */ + if (goi.argc != 0) + { + return JIM_ERR; + } + jim_wide b = 1; /* shut up gcc */ if (strcasecmp(cmd_name, "mdw") == 0) b = 4; @@ -3950,42 +4118,44 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (y > 16) { y = 16; } - e = target_read_memory(target, a, b, y / b, target_buf); + e = fn(target, a, b, y / b, target_buf); if (e != ERROR_OK) { - Jim_SetResult_sprintf(interp, "error reading target @ 0x%08lx", (int)(a)); + char tmp[10]; + snprintf(tmp, sizeof(tmp), "%08lx", (long)a); + Jim_SetResultFormatted(interp, "error reading target @ 0x%s", tmp); return JIM_ERR; } - Jim_fprintf(interp, interp->cookie_stdout, "0x%08x ", (int)(a)); + command_print(NULL, "0x%08x ", (int)(a)); switch (b) { case 4: for (x = 0; x < 16 && x < y; x += 4) { - z = target_buffer_get_u32(target, &(target_buf[ x * 4 ])); - Jim_fprintf(interp, interp->cookie_stdout, "%08x ", (int)(z)); + z = target_buffer_get_u32(target, &(target_buf[ x ])); + command_print(NULL, "%08x ", (int)(z)); } for (; (x < 16) ; x += 4) { - Jim_fprintf(interp, interp->cookie_stdout, " "); + command_print(NULL, " "); } break; case 2: for (x = 0; x < 16 && x < y; x += 2) { - z = target_buffer_get_u16(target, &(target_buf[ x * 2 ])); - Jim_fprintf(interp, interp->cookie_stdout, "%04x ", (int)(z)); + z = target_buffer_get_u16(target, &(target_buf[ x ])); + command_print(NULL, "%04x ", (int)(z)); } for (; (x < 16) ; x += 2) { - Jim_fprintf(interp, interp->cookie_stdout, " "); + command_print(NULL, " "); } break; case 1: default: for (x = 0 ; (x < 16) && (x < y) ; x += 1) { - z = target_buffer_get_u8(target, &(target_buf[ x * 4 ])); - Jim_fprintf(interp, interp->cookie_stdout, "%02x ", (int)(z)); + z = target_buffer_get_u8(target, &(target_buf[ x ])); + command_print(NULL, "%02x ", (int)(z)); } for (; (x < 16) ; x += 1) { - Jim_fprintf(interp, interp->cookie_stdout, " "); + command_print(NULL, " "); } break; } @@ -4007,7 +4177,7 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* terminate */ target_buf[16] = 0; /* print - with a newline */ - Jim_fprintf(interp, interp->cookie_stdout, "%s\n", target_buf); + command_print(NULL, "%s\n", target_buf); /* NEXT... */ c -= 16; a += 16; @@ -4031,7 +4201,7 @@ static int jim_target_array2mem(Jim_Interp *interp, static int jim_target_tap_disabled(Jim_Interp *interp) { - Jim_SetResult_sprintf(interp, "[TAP is disabled]"); + Jim_SetResultFormatted(interp, "[TAP is disabled]"); return JIM_ERR; } @@ -4049,9 +4219,26 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv int e = target->type->examine(target); if (e != ERROR_OK) { - Jim_SetResult_sprintf(interp, "examine-fails: %d", e); + Jim_Obj *eObj = Jim_NewIntObj(interp, e); + Jim_SetResultFormatted(interp, "examine-fails: %#s", eObj); + Jim_FreeNewObj(interp, eObj); + return JIM_ERR; + } + return JIM_OK; +} + +static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); return JIM_ERR; } + struct target *target = Jim_CmdPrivData(interp); + + if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) + return JIM_ERR; + return JIM_OK; } @@ -4074,7 +4261,9 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } if (e != ERROR_OK) { - Jim_SetResult_sprintf(interp, "poll-fails: %d", e); + Jim_Obj *eObj = Jim_NewIntObj(interp, e); + Jim_SetResultFormatted(interp, "poll-fails: %#s", eObj); + Jim_FreeNewObj(interp, eObj); return JIM_ERR; } return JIM_OK; @@ -4115,7 +4304,7 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } if (!target->type->assert_reset || !target->type->deassert_reset) { - Jim_SetResult_sprintf(interp, + Jim_SetResultFormatted(interp, "No target-specific reset for %s", target_name(target)); return JIM_ERR; @@ -4156,7 +4345,7 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a if (goi.argc != 2) { const char *cmd_name = Jim_GetString(argv[0], NULL); - Jim_SetResult_sprintf(goi.interp, + Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); return JIM_ERR; } @@ -4179,10 +4368,12 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a e = target_wait_state(target, n->value, a); if (e != ERROR_OK) { - Jim_SetResult_sprintf(goi.interp, - "target: %s wait %s fails (%d) %s", + Jim_Obj *eObj = Jim_NewIntObj(interp, e); + Jim_SetResultFormatted(goi.interp, + "target: %s wait %s fails (%#s) %s", target_name(target), n->name, - e, target_strerror_safe(e)); + eObj, target_strerror_safe(e)); + Jim_FreeNewObj(interp, eObj); return JIM_ERR; } return JIM_OK; @@ -4192,7 +4383,9 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a */ static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context"); + struct command_context *cmd_ctx = current_command_context(interp); + assert (cmd_ctx != NULL); + struct target *target = Jim_CmdPrivData(interp); struct target_event_action *teap = target->event_action; command_print(cmd_ctx, "Event actions for target (%d) %s\n", @@ -4229,7 +4422,7 @@ static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const if (goi.argc != 1) { const char *cmd_name = Jim_GetString(argv[0], NULL); - Jim_SetResult_sprintf(goi.interp, "%s ", cmd_name); + Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); return JIM_ERR; } Jim_Nvp *n; @@ -4335,6 +4528,12 @@ static const struct command_registration target_instance_command_handlers[] = { .jim_handler = jim_target_examine, .help = "used internally for reset processing", }, + { + .name = "arp_halt_gdb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_halt_gdb, + .help = "used internally for reset processing to halt GDB", + }, { .name = "arp_poll", .mode = COMMAND_EXEC, @@ -4380,7 +4579,9 @@ static int target_create(Jim_GetOptInfo *goi) struct target *target; struct command_context *cmd_ctx; - cmd_ctx = Jim_GetAssocData(goi->interp, "context"); + cmd_ctx = current_command_context(goi->interp); + assert (cmd_ctx != NULL); + if (goi->argc < 3) { Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options..."); return JIM_ERR; @@ -4392,7 +4593,7 @@ static int target_create(Jim_GetOptInfo *goi) cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); if (cmd) { cp = Jim_GetString(new_cmd, NULL); - Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp); + Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); return JIM_ERR; } @@ -4407,7 +4608,7 @@ static int target_create(Jim_GetOptInfo *goi) } } if (target_types[x] == NULL) { - Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp); + Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); for (x = 0 ; target_types[x] ; x++) { if (target_types[x + 1]) { Jim_AppendStrings(goi->interp, @@ -4554,7 +4755,9 @@ static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); return JIM_ERR; } - struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context"); + struct command_context *cmd_ctx = current_command_context(interp); + assert (cmd_ctx != NULL); + Jim_SetResultString(interp, get_current_target(cmd_ctx)->cmd_name, -1); return JIM_OK; } @@ -4615,7 +4818,7 @@ static int jim_target_number(Jim_Interp *interp, int argc, Jim_Obj *const *argv) LOG_WARNING("don't use numbers as target identifiers; use names"); if (goi.argc != 1) { - Jim_SetResult_sprintf(goi.interp, "usage: target number "); + Jim_SetResultFormatted(goi.interp, "usage: target number "); return JIM_ERR; } jim_wide w; @@ -4632,8 +4835,12 @@ static int jim_target_number(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_SetResultString(goi.interp, target_name(target), -1); return JIM_OK; } - Jim_SetResult_sprintf(goi.interp, - "Target: number %d does not exist", (int)(w)); + { + Jim_Obj *wObj = Jim_NewIntObj(goi.interp, w); + Jim_SetResultFormatted(goi.interp, + "Target: number %#s does not exist", wObj); + Jim_FreeNewObj(interp, wObj); + } return JIM_ERR; } @@ -4829,7 +5036,7 @@ COMMAND_HANDLER(handle_fast_load_image_command) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "Loaded %" PRIu32 " bytes " - "in %fs (%0.3f kb/s)", image_size, + "in %fs (%0.3f KiB/s)", image_size, duration_elapsed(&bench), duration_kbps(&bench, image_size)); command_print(CMD_CTX, @@ -5101,7 +5308,7 @@ static const struct command_registration target_exec_command_handlers[] = { .usage = "filename [offset [type]]", }, { - .name = "ocd_mem2array", + .name = "mem2array", .mode = COMMAND_EXEC, .jim_handler = jim_mem2array, .help = "read 8/16/32 bit memory and return as a TCL array " @@ -5109,7 +5316,7 @@ static const struct command_registration target_exec_command_handlers[] = { .usage = "arrayname bitwidth address count", }, { - .name = "ocd_array2mem", + .name = "array2mem", .mode = COMMAND_EXEC, .jim_handler = jim_array2mem, .help = "convert a TCL array to memory locations " @@ -5126,7 +5333,7 @@ static const struct command_registration target_exec_command_handlers[] = { }, COMMAND_REGISTRATION_DONE }; -int target_register_user_commands(struct command_context *cmd_ctx) +static int target_register_user_commands(struct command_context *cmd_ctx) { int retval = ERROR_OK; if ((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK)