X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=1ea1a61668c9d059299e6225778138ba92b2f8c8;hp=ccaa6e3943c95d83f7902c9e5108c745963e665c;hb=d4d62ea8a80502f85f1ca92b231da56ef3b84baf;hpb=25b855d2d2eaa68787799c97b654167ddec04f85 diff --git a/src/target/target.c b/src/target/target.c index ccaa6e3943..1ea1a61668 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -36,7 +36,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -56,15 +56,22 @@ #include "image.h" #include "rtos/rtos.h" +/* default halt wait timeout (ms) */ +#define DEFAULT_HALT_TIMEOUT 5000 + static int target_read_buffer_default(struct target *target, uint32_t address, - uint32_t size, uint8_t *buffer); + uint32_t count, uint8_t *buffer); static int target_write_buffer_default(struct target *target, uint32_t address, - uint32_t size, const uint8_t *buffer); + uint32_t count, const uint8_t *buffer); 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); +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); /* targets */ extern struct target_type arm7tdmi_target; @@ -80,6 +87,7 @@ extern struct target_type dragonite_target; extern struct target_type xscale_target; extern struct target_type cortexm3_target; extern struct target_type cortexa8_target; +extern struct target_type cortexr4_target; extern struct target_type arm11_target; extern struct target_type mips_m4k_target; extern struct target_type avr_target; @@ -87,7 +95,10 @@ extern struct target_type dsp563xx_target; extern struct target_type dsp5680xx_target; extern struct target_type testee_target; extern struct target_type avr32_ap7k_target; -extern struct target_type stm32_stlink_target; +extern struct target_type hla_target; +extern struct target_type nds32_v2_target; +extern struct target_type nds32_v3_target; +extern struct target_type nds32_v3m_target; static struct target_type *target_types[] = { &arm7tdmi_target, @@ -103,6 +114,7 @@ static struct target_type *target_types[] = { &xscale_target, &cortexm3_target, &cortexa8_target, + &cortexr4_target, &arm11_target, &mips_m4k_target, &avr_target, @@ -110,7 +122,10 @@ static struct target_type *target_types[] = { &dsp5680xx_target, &testee_target, &avr32_ap7k_target, - &stm32_stlink_target, + &hla_target, + &nds32_v2_target, + &nds32_v3_target, + &nds32_v3m_target, NULL, }; @@ -213,6 +228,7 @@ static const Jim_Nvp nvp_target_debug_reason[] = { { .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 = NULL, .value = -1 }, }; @@ -379,9 +395,9 @@ struct target *get_target(const char *id) /* try as tcltarget name */ for (target = all_targets; target; target = target->next) { - if (target->cmd_name == NULL) + if (target_name(target) == NULL) continue; - if (strcmp(id, target->cmd_name) == 0) + if (strcmp(id, target_name(target)) == 0) return target; } @@ -395,7 +411,7 @@ struct target *get_target(const char *id) for (target = all_targets; target; target = target->next) { if (target->target_number == (int)num) { LOG_WARNING("use '%s' as target identifier, not '%u'", - target->cmd_name, num); + target_name(target), num); return target; } } @@ -448,7 +464,7 @@ int target_poll(struct target *target) target->halt_issued = false; else { long long t = timeval_ms() - target->halt_issued_time; - if (t > 1000) { + if (t > DEFAULT_HALT_TIMEOUT) { target->halt_issued = false; LOG_INFO("Halt timed out, wake up GDB."); target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); @@ -567,8 +583,10 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res retval = target_call_timer_callbacks_now(); struct target *target; - for (target = all_targets; target; target = target->next) + for (target = all_targets; target; target = target->next) { target->type->check_reset(target); + target->running_alg = false; + } return retval; } @@ -611,9 +629,17 @@ static int jtag_enable_callback(enum jtag_event event, void *priv) return ERROR_OK; jtag_unregister_event_callback(jtag_enable_callback, target); - return target_examine_one(target); -} + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); + + int retval = target_examine_one(target); + if (retval != ERROR_OK) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); + + return retval; +} /* Targets that correctly implement init + examine, i.e. * no communication with target during init: @@ -632,49 +658,35 @@ int target_examine(void) target); continue; } + + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); + retval = target_examine_one(target); if (retval != ERROR_OK) return retval; + + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); } return retval; } + const char *target_type_name(struct target *target) { return target->type->name; } -static int target_write_memory_imp(struct target *target, uint32_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) -{ - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - return target->type->write_memory_imp(target, address, size, count, buffer); -} - -static int target_read_memory_imp(struct target *target, uint32_t address, - uint32_t size, uint32_t count, uint8_t *buffer) -{ - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - return target->type->read_memory_imp(target, address, size, count, buffer); -} - -static int target_soft_reset_halt_imp(struct target *target) +static int target_soft_reset_halt(struct target *target) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); return ERROR_FAIL; } - if (!target->type->soft_reset_halt_imp) { + if (!target->type->soft_reset_halt) { LOG_ERROR("Target %s does not support soft_reset_halt", target_name(target)); return ERROR_FAIL; } - return target->type->soft_reset_halt_imp(target); + return target->type->soft_reset_halt(target); } /** @@ -808,6 +820,7 @@ int target_run_flash_async_algorithm(struct target *target, uint32_t entry_point, uint32_t exit_point, void *arch_info) { int retval; + int timeout = 0; /* Set up working area. First word is write pointer, second word is read pointer, * rest is fifo data area. */ @@ -879,9 +892,19 @@ int target_run_flash_async_algorithm(struct target *target, * less than buffer size / flash speed. This is very unlikely to * run when using high latency connections such as USB. */ alive_sleep(10); + + /* 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) { + 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 write */ if (thisrun_bytes > count * block_size) thisrun_bytes = count * block_size; @@ -926,38 +949,48 @@ int target_run_flash_async_algorithm(struct target *target, int target_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } return target->type->read_memory(target, address, size, count, buffer); } -static int target_read_phys_memory(struct target *target, +int target_read_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } return target->type->read_phys_memory(target, address, size, count, buffer); } int target_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } return target->type->write_memory(target, address, size, count, buffer); } -static int target_write_phys_memory(struct target *target, +int target_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } return target->type->write_phys_memory(target, address, size, count, buffer); } -int target_bulk_write_memory(struct target *target, - uint32_t address, uint32_t count, const uint8_t *buffer) -{ - return target->type->bulk_write_memory(target, address, count, buffer); -} - int target_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_breakpoint(target, breakpoint); @@ -967,7 +1000,7 @@ int target_add_context_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_context_breakpoint(target, breakpoint); @@ -977,7 +1010,7 @@ int target_add_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_hybrid_breakpoint(target, breakpoint); @@ -993,7 +1026,7 @@ int target_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_watchpoint(target, watchpoint); @@ -1003,11 +1036,29 @@ int target_remove_watchpoint(struct target *target, { return target->type->remove_watchpoint(target, watchpoint); } +int target_hit_watchpoint(struct target *target, + struct watchpoint **hit_watchpoint) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + + if (target->type->hit_watchpoint == NULL) { + /* For backward compatible, if hit_watchpoint is not implemented, + * return ERROR_FAIL such that gdb_server will not take the nonsense + * information. */ + return ERROR_FAIL; + } + + return target->type->hit_watchpoint(target, hit_watchpoint); +} int target_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size) + 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); + return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } int target_step(struct target *target, int current, uint32_t address, int handle_breakpoints) @@ -1015,6 +1066,24 @@ int target_step(struct target *target, return target->type->step(target, current, address, handle_breakpoints); } +int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + return target->type->get_gdb_fileio_info(target, fileio_info); +} + +int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); +} + /** * Reset the @c examined flag for the given target. * Pure paranoia -- targets are zeroed on allocation. @@ -1060,23 +1129,6 @@ static int target_init_one(struct command_context *cmd_ctx, return retval; } - /** - * @todo get rid of those *memory_imp() methods, now that all - * callers are using target_*_memory() accessors ... and make - * sure the "physical" paths handle the same issues. - */ - /* a non-invasive way(in terms of patches) to add some code that - * runs before the type->write/read_memory implementation - */ - type->write_memory_imp = target->type->write_memory; - type->write_memory = target_write_memory_imp; - - type->read_memory_imp = target->type->read_memory; - type->read_memory = target_read_memory_imp; - - type->soft_reset_halt_imp = target->type->soft_reset_halt; - type->soft_reset_halt = target_soft_reset_halt_imp; - /* Sanity-check MMU support ... stub in what we must, to help * implement it in stages, but warn if we need to do so. */ @@ -1115,6 +1167,12 @@ static int target_init_one(struct command_context *cmd_ctx, if (target->type->write_buffer == NULL) target->type->write_buffer = target_write_buffer_default; + if (target->type->get_gdb_fileio_info == NULL) + target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default; + + if (target->type->gdb_fileio_end == NULL) + target->type->gdb_fileio_end = target_gdb_fileio_end_default; + return ERROR_OK; } @@ -1664,6 +1722,22 @@ int target_arch_state(struct target *target) return retval; } +static int target_get_gdb_fileio_info_default(struct target *target, + struct gdb_fileio_info *fileio_info) +{ + /* If target does not support semi-hosting function, target + has no need to provide .get_gdb_fileio_info callback. + It just return ERROR_FAIL and gdb_server will return "Txx" + as target halted every time. */ + return ERROR_FAIL; +} + +static int target_gdb_fileio_end_default(struct target *target, + int retcode, int fileio_errno, bool ctrl_c) +{ + return ERROR_OK; +} + /* Single aligned words are guaranteed to use 16 or 32 bit access * mode respectively, otherwise data is handled as quickly as * possible @@ -1692,57 +1766,37 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, return target->type->write_buffer(target, address, size, buffer); } -static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) +static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) { - int retval = ERROR_OK; + uint32_t size; - if (((address % 2) == 0) && (size == 2)) - return target_write_memory(target, address, 2, 1, buffer); - - /* handle unaligned head bytes */ - if (address % 4) { - uint32_t unaligned = 4 - (address % 4); - - if (unaligned > size) - unaligned = size; - - retval = target_write_memory(target, address, 1, unaligned, buffer); - if (retval != ERROR_OK) - return retval; - - buffer += unaligned; - address += unaligned; - size -= unaligned; - } - - /* handle aligned words */ - if (size >= 4) { - int aligned = size - (size % 4); - - /* use bulk writes above a certain limit. This may have to be changed */ - if (aligned > 128) { - retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer); - if (retval != ERROR_OK) - return retval; - } else { - retval = target_write_memory(target, address, 4, aligned / 4, buffer); + /* Align up to maximum 4 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) { + if (address & size) { + int retval = target_write_memory(target, address, size, 1, buffer); if (retval != ERROR_OK) return retval; + address += size; + count -= size; + buffer += size; } - - buffer += aligned; - address += aligned; - size -= aligned; } - /* handle tail writes of less than 4 bytes */ - if (size > 0) { - retval = target_write_memory(target, address, 1, size, buffer); - if (retval != ERROR_OK) - return retval; + /* Write the data with as large access size as possible. */ + for (; size > 0; size /= 2) { + uint32_t aligned = count - count % size; + if (aligned > 0) { + int retval = target_write_memory(target, address, size, aligned / size, buffer); + if (retval != ERROR_OK) + return retval; + address += aligned; + count -= aligned; + buffer += aligned; + } } - return retval; + return ERROR_OK; } /* Single aligned words are guaranteed to use 16 or 32 bit access @@ -1773,58 +1827,34 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u return target->type->read_buffer(target, address, size, buffer); } -static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) +static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) { - int retval = ERROR_OK; - - if (((address % 2) == 0) && (size == 2)) - return target_read_memory(target, address, 2, 1, buffer); - - /* handle unaligned head bytes */ - if (address % 4) { - uint32_t unaligned = 4 - (address % 4); - - if (unaligned > size) - unaligned = size; - - retval = target_read_memory(target, address, 1, unaligned, buffer); - if (retval != ERROR_OK) - return retval; - - buffer += unaligned; - address += unaligned; - size -= unaligned; - } - - /* handle aligned words */ - if (size >= 4) { - int aligned = size - (size % 4); + uint32_t size; - retval = target_read_memory(target, address, 4, aligned / 4, buffer); - if (retval != ERROR_OK) - return retval; - - buffer += aligned; - address += aligned; - size -= aligned; + /* Align up to maximum 4 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) { + if (address & size) { + int retval = target_read_memory(target, address, size, 1, buffer); + if (retval != ERROR_OK) + return retval; + address += size; + count -= size; + buffer += size; + } } - /*prevent byte access when possible (avoid AHB access limitations in some cases)*/ - if (size >= 2) { - int aligned = size - (size % 2); - retval = target_read_memory(target, address, 2, aligned / 2, buffer); - if (retval != ERROR_OK) - return retval; - - buffer += aligned; - address += aligned; - size -= aligned; - } - /* handle tail writes of less than 4 bytes */ - if (size > 0) { - retval = target_read_memory(target, address, 1, size, buffer); - if (retval != ERROR_OK) - return retval; + /* Read the data with as large access size as possible. */ + for (; size > 0; size /= 2) { + uint32_t aligned = count - count % size; + if (aligned > 0) { + int retval = target_read_memory(target, address, size, aligned / size, buffer); + if (retval != ERROR_OK) + return retval; + address += aligned; + count -= aligned; + buffer += aligned; + } } return ERROR_OK; @@ -2139,9 +2169,6 @@ static int sense_handler(void) return ERROR_OK; } -static int backoff_times; -static int backoff_count; - /* process target state changes */ static int handle_target(void *priv) { @@ -2197,13 +2224,6 @@ 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. */ @@ -2213,18 +2233,26 @@ static int handle_target(void *priv) if (!target->tap->enabled) continue; + if (target->backoff.times > target->backoff.count) { + /* do not poll this time as we failed previously */ + target->backoff.count++; + continue; + } + target->backoff.count = 0; + /* only poll target if we've got power and srst isn't asserted */ if (!powerDropout && !srstAsserted) { /* polling may fail silently until the target has been examined */ retval = target_poll(target); if (retval != ERROR_OK) { /* 100ms polling interval. Increase interval between polling up to 5000ms */ - if (backoff_times * polling_interval < 5000) { - backoff_times *= 2; - backoff_times++; + if (target->backoff.times * polling_interval < 5000) { + target->backoff.times *= 2; + target->backoff.times++; } - LOG_USER("Polling target failed, GDB will be halted. Polling again in %dms", - backoff_times * polling_interval); + LOG_USER("Polling target %s failed, GDB will be halted. Polling again in %dms", + target_name(target), + target->backoff.times * polling_interval); /* Tell GDB to halt the debugger. This allows the user to * run monitor commands to handle the situation. @@ -2233,9 +2261,9 @@ static int handle_target(void *priv) return retval; } /* Since we succeeded, we reset backoff count */ - if (backoff_times > 0) - LOG_USER("Polling succeeded again"); - backoff_times = 0; + if (target->backoff.times > 0) + LOG_USER("Polling target %s succeeded again", target_name(target)); + target->backoff.times = 0; } } @@ -2396,13 +2424,11 @@ COMMAND_HANDLER(handle_wait_halt_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned ms = 5000; + unsigned ms = DEFAULT_HALT_TIMEOUT; if (1 == CMD_ARGC) { int retval = parse_uint(CMD_ARGV[0], &ms); if (ERROR_OK != retval) return ERROR_COMMAND_SYNTAX_ERROR; - /* convert seconds (given) to milliseconds (needed) */ - ms *= 1000; } struct target *target = get_current_target(CMD_CTX); @@ -2475,7 +2501,7 @@ COMMAND_HANDLER(handle_soft_reset_halt_command) LOG_USER("requesting target halt and executing a soft reset"); - target->type->soft_reset_halt(target); + target_soft_reset_halt(target); return ERROR_OK; } @@ -3361,24 +3387,28 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam max = samples[i]; } - int addressSpace = (max - min + 1); + /* max should be (largest sample + 1) + * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ + max++; + + int addressSpace = max - min; assert(addressSpace >= 2); static const uint32_t maxBuckets = 16 * 1024; /* maximum buckets. */ - uint32_t length = addressSpace; - if (length > maxBuckets) - length = maxBuckets; - int *buckets = malloc(sizeof(int)*length); + uint32_t numBuckets = addressSpace; + if (numBuckets > maxBuckets) + numBuckets = maxBuckets; + int *buckets = malloc(sizeof(int) * numBuckets); if (buckets == NULL) { fclose(f); return; } - memset(buckets, 0, sizeof(int) * length); + memset(buckets, 0, sizeof(int) * numBuckets); for (i = 0; i < sampleNum; i++) { uint32_t address = samples[i]; long long a = address - min; - long long b = length - 1; - long long c = addressSpace - 1; + long long b = numBuckets; + long long c = addressSpace; int index_t = (a * b) / c; /* danger!!!! int32 overflows */ buckets[index_t]++; } @@ -3386,7 +3416,7 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */ writeLong(f, min); /* low_pc */ writeLong(f, max); /* high_pc */ - writeLong(f, length); /* # of samples */ + writeLong(f, numBuckets); /* # of buckets */ writeLong(f, 100); /* KLUDGE! We lie, ca. 100Hz best case. */ writeString(f, "seconds"); for (i = 0; i < (15-strlen("seconds")); i++) @@ -3395,9 +3425,9 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ - char *data = malloc(2 * length); + char *data = malloc(2 * numBuckets); if (data != NULL) { - for (i = 0; i < length; i++) { + for (i = 0; i < numBuckets; i++) { int val; val = buckets[i]; if (val > 65535) @@ -3406,7 +3436,7 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam data[i * 2 + 1] = (val >> 8) & 0xff; } free(buckets); - writeData(f, data, length * 2); + writeData(f, data, numBuckets * 2); free(data); } else free(buckets); @@ -4329,6 +4359,34 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 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); @@ -4357,78 +4415,80 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) fn = target_read_phys_memory; } - jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); + /* Read address parameter */ + jim_wide addr; + e = Jim_GetOpt_Wide(&goi, &addr); if (e != JIM_OK) return JIM_ERR; - jim_wide c; + + /* 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, &c); + e = Jim_GetOpt_Wide(&goi, &count); if (e != JIM_OK) return JIM_ERR; } else - c = 1; + count = 1; /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; - jim_wide b = 1; /* shut up gcc */ + jim_wide dwidth = 1; /* shut up gcc */ if (strcasecmp(cmd_name, "mdw") == 0) - b = 4; + dwidth = 4; else if (strcasecmp(cmd_name, "mdh") == 0) - b = 2; + dwidth = 2; else if (strcasecmp(cmd_name, "mdb") == 0) - b = 1; + dwidth = 1; else { LOG_ERROR("command '%s' unknown: ", cmd_name); return JIM_ERR; } /* convert count to "bytes" */ - c = c * b; + int bytes = count * dwidth; struct target *target = Jim_CmdPrivData(goi.interp); uint8_t target_buf[32]; jim_wide x, y, z; - while (c > 0) { - y = c; - if (y > 16) - y = 16; - e = fn(target, a, b, y / b, target_buf); + 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) { - char tmp[10]; - snprintf(tmp, sizeof(tmp), "%08lx", (long)a); - Jim_SetResultFormatted(interp, "error reading target @ 0x%s", tmp); + Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr); return JIM_ERR; } - command_print(NULL, "0x%08x ", (int)(a)); - switch (b) { + 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(NULL, "%08x ", (int)(z)); + command_print_sameline(NULL, "%08x ", (int)(z)); } for (; (x < 16) ; x += 4) - command_print(NULL, " "); + 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(NULL, "%04x ", (int)(z)); + command_print_sameline(NULL, "%04x ", (int)(z)); } for (; (x < 16) ; x += 2) - command_print(NULL, " "); + 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(NULL, "%02x ", (int)(z)); + command_print_sameline(NULL, "%02x ", (int)(z)); } for (; (x < 16) ; x += 1) - command_print(NULL, " "); + command_print_sameline(NULL, " "); break; } /* ascii-ify the bytes */ @@ -4449,10 +4509,10 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* terminate */ target_buf[16] = 0; /* print - with a newline */ - command_print(NULL, "%s\n", target_buf); + command_print_sameline(NULL, "%s\n", target_buf); /* NEXT... */ - c -= 16; - a += 16; + bytes -= 16; + addr += 16; } return JIM_OK; } @@ -4854,6 +4914,15 @@ static int target_create(Jim_GetOptInfo *goi) /* 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) { Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); @@ -4970,7 +5039,7 @@ static int target_create(Jim_GetOptInfo *goi) } /* now - create the new target name command */ - const const struct command_registration target_subcommands[] = { + const struct command_registration target_subcommands[] = { { .chain = target_instance_command_handlers, }, @@ -4979,7 +5048,7 @@ static int target_create(Jim_GetOptInfo *goi) }, COMMAND_REGISTRATION_DONE }; - const const struct command_registration target_commands[] = { + const struct command_registration target_commands[] = { { .name = cp, .mode = COMMAND_ANY, @@ -5009,7 +5078,7 @@ static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv struct command_context *cmd_ctx = current_command_context(interp); assert(cmd_ctx != NULL); - Jim_SetResultString(interp, get_current_target(cmd_ctx)->cmd_name, -1); + Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1); return JIM_OK; } @@ -5087,8 +5156,10 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) target->head = head; curr = curr->next; } - if (target->rtos) + + if (target && target->rtos) retval = rtos_smp_init(head->target); + return retval; } @@ -5481,7 +5552,7 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_wait_halt_command, .mode = COMMAND_EXEC, .help = "wait up to the specified number of milliseconds " - "(default 5) for a previously requested halt", + "(default 5000) for a previously requested halt", .usage = "[milliseconds]", }, { @@ -5489,7 +5560,7 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_halt_command, .mode = COMMAND_EXEC, .help = "request target to halt, then wait up to the specified" - "number of milliseconds (default 5) for it to complete", + "number of milliseconds (default 5000) for it to complete", .usage = "[milliseconds]", }, {