X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=d2dff111a5c7adfa062ccd9e7eb2c1ad6ae06580;hb=HEAD;hp=0099292119f8041f6f8e938806ac2cefd0bb2cf4;hpb=da76f8f0b4b98c2b7f04b5fe94f721aed7b2cfab;p=openocd.git diff --git a/src/target/target.c b/src/target/target.c index 0099292119..efc168903b 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -56,10 +56,6 @@ static int target_read_buffer_default(struct target *target, target_addr_t addre uint32_t count, uint8_t *buffer); static int target_write_buffer_default(struct target *target, target_addr_t address, 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); @@ -248,7 +244,7 @@ static const struct nvp nvp_reset_modes[] = { { .name = NULL, .value = -1 }, }; -const char *debug_reason_name(struct target *t) +const char *debug_reason_name(const struct target *t) { const char *cp; @@ -261,7 +257,7 @@ const char *debug_reason_name(struct target *t) return cp; } -const char *target_state_name(struct target *t) +const char *target_state_name(const struct target *t) { const char *cp; cp = nvp_value2name(nvp_target_state, t->state)->name; @@ -298,23 +294,6 @@ const char *target_reset_mode_name(enum target_reset_mode reset_mode) return cp; } -/* determine the number of the new target */ -static int new_target_number(void) -{ - struct target *t; - int x; - - /* number is 0 based */ - x = -1; - t = all_targets; - while (t) { - if (x < t->target_number) - x = t->target_number; - t = t->next; - } - return x + 1; -} - static void append_to_list_all_targets(struct target *target) { struct target **t = &all_targets; @@ -450,7 +429,7 @@ void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_ target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]); } -/* return a pointer to a configured target; id is name or number */ +/* return a pointer to a configured target; id is name or index in all_targets */ struct target *get_target(const char *id) { struct target *target; @@ -463,36 +442,17 @@ struct target *get_target(const char *id) return target; } - /* It's OK to remove this fallback sometime after August 2010 or so */ - - /* no match, try as number */ - unsigned num; - if (parse_uint(id, &num) != ERROR_OK) + /* try as index */ + unsigned int index, counter; + if (parse_uint(id, &index) != ERROR_OK) return NULL; - for (target = all_targets; target; target = target->next) { - if (target->target_number == (int)num) { - LOG_WARNING("use '%s' as target identifier, not '%u'", - target_name(target), num); - return target; - } - } - - return NULL; -} - -/* returns a pointer to the n-th configured target */ -struct target *get_target_by_num(int num) -{ - struct target *target = all_targets; - - while (target) { - if (target->target_number == num) - return target; - target = target->next; - } + for (target = all_targets, counter = index; + target && counter; + target = target->next, --counter) + ; - return NULL; + return target; } struct target *get_current_target(struct command_context *cmd_ctx) @@ -711,10 +671,14 @@ static int default_check_reset(struct target *target) * Keep in sync */ int target_examine_one(struct target *target) { + LOG_TARGET_DEBUG(target, "Examination started"); + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); int retval = target->type->examine(target); if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "Examination failed"); + LOG_TARGET_DEBUG(target, "examine() returned error code %d", retval); target_reset_examined(target); target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_FAIL); return retval; @@ -723,6 +687,7 @@ int target_examine_one(struct target *target) target_set_examined(target); target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); + LOG_TARGET_INFO(target, "Examination succeed"); return ERROR_OK; } @@ -768,7 +733,7 @@ int target_examine(void) return retval; } -const char *target_type_name(struct target *target) +const char *target_type_name(const struct target *target) { return target->type->name; } @@ -1235,6 +1200,10 @@ int target_run_read_async_algorithm(struct target *target, /* Avoid GDB timeouts */ keep_alive(); + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + break; + } } if (retval != ERROR_OK) { @@ -1325,7 +1294,7 @@ 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 (add breakpoint)", target_name(target)); + LOG_TARGET_ERROR(target, "not halted (add breakpoint)"); return ERROR_TARGET_NOT_HALTED; } return target->type->add_breakpoint(target, breakpoint); @@ -1335,7 +1304,7 @@ int target_add_context_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted (add context breakpoint)", target_name(target)); + LOG_TARGET_ERROR(target, "not halted (add context breakpoint)"); return ERROR_TARGET_NOT_HALTED; } return target->type->add_context_breakpoint(target, breakpoint); @@ -1345,7 +1314,7 @@ int target_add_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted (add hybrid breakpoint)", target_name(target)); + LOG_TARGET_ERROR(target, "not halted (add hybrid breakpoint)"); return ERROR_TARGET_NOT_HALTED; } return target->type->add_hybrid_breakpoint(target, breakpoint); @@ -1361,7 +1330,7 @@ int target_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted (add watchpoint)", target_name(target)); + LOG_TARGET_ERROR(target, "not halted (add watchpoint)"); return ERROR_TARGET_NOT_HALTED; } return target->type->add_watchpoint(target, watchpoint); @@ -1375,7 +1344,7 @@ int target_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted (hit watchpoint)", target->cmd_name); + LOG_TARGET_ERROR(target, "not halted (hit watchpoint)"); return ERROR_TARGET_NOT_HALTED; } @@ -1389,7 +1358,7 @@ int target_hit_watchpoint(struct target *target, return target->type->hit_watchpoint(target, hit_watchpoint); } -const char *target_get_gdb_arch(struct target *target) +const char *target_get_gdb_arch(const struct target *target) { if (!target->type->get_gdb_arch) return NULL; @@ -1429,7 +1398,7 @@ int target_get_gdb_reg_list_noread(struct target *target, return target_get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } -bool target_supports_gdb_connection(struct target *target) +bool target_supports_gdb_connection(const struct target *target) { /* * exclude all the targets that don't provide get_gdb_reg_list @@ -1457,7 +1426,7 @@ int target_step(struct target *target, 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 (gdb fileio)", target->cmd_name); + LOG_TARGET_ERROR(target, "not halted (gdb fileio)"); return ERROR_TARGET_NOT_HALTED; } return target->type->get_gdb_fileio_info(target, fileio_info); @@ -1466,7 +1435,7 @@ int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fi 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 (gdb fileio end)", target->cmd_name); + LOG_TARGET_ERROR(target, "not halted (gdb fileio end)"); return ERROR_TARGET_NOT_HALTED; } return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); @@ -1529,7 +1498,7 @@ static int target_init_one(struct command_context *cmd_ctx, */ if (type->mmu) { if (!type->virt2phys) { - LOG_ERROR("type '%s' is missing virt2phys", type->name); + LOG_ERROR("type '%s' is missing virt2phys", target_name(target)); type->virt2phys = identity_virt2phys; } } else { @@ -1538,7 +1507,7 @@ static int target_init_one(struct command_context *cmd_ctx, * ensure that virt2phys() is always an identity mapping. */ if (type->write_phys_memory || type->read_phys_memory || type->virt2phys) - LOG_WARNING("type '%s' has bad MMU hooks", type->name); + LOG_WARNING("type '%s' has bad MMU hooks", target_name(target)); type->mmu = no_mmu; type->write_phys_memory = type->write_memory; @@ -2212,6 +2181,9 @@ uint32_t target_get_working_area_avail(struct target *target) static void target_destroy(struct target *target) { + breakpoint_remove_all(target); + watchpoint_remove_all(target); + if (target->type->deinit_target) target->type->deinit_target(target); @@ -2840,10 +2812,10 @@ COMMAND_HANDLER(handle_targets_command) } } - struct target *target = all_targets; + unsigned int index = 0; command_print(CMD, " TargetName Type Endian TapName State "); command_print(CMD, "-- ------------------ ---------- ------ ------------------ ------------"); - while (target) { + for (struct target *target = all_targets; target; target = target->next, ++index) { const char *state; char marker = ' '; @@ -2858,7 +2830,7 @@ COMMAND_HANDLER(handle_targets_command) /* keep columns lined up to match the headers above */ command_print(CMD, "%2d%c %-18s %-10s %-6s %-18s %s", - target->target_number, + index, marker, target_name(target), target_type_name(target), @@ -2866,7 +2838,6 @@ COMMAND_HANDLER(handle_targets_command) target->endianness)->name, target->tap->dotted_name, state); - target = target->next; } return retval; @@ -3052,6 +3023,10 @@ COMMAND_HANDLER(handle_reg_command) LOG_DEBUG("-"); struct target *target = get_current_target(CMD_CTX); + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } struct reg *reg = NULL; /* list all available registers for the current target */ @@ -3116,7 +3091,7 @@ COMMAND_HANDLER(handle_reg_command) if (!reg) { command_print(CMD, "%i is out of bounds, the current target " "has only %i registers (0 - %i)", num, count, count - 1); - return ERROR_OK; + return ERROR_FAIL; } } else { /* access a single register by its name */ @@ -3135,9 +3110,9 @@ COMMAND_HANDLER(handle_reg_command) if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')))) { if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0)) - reg->valid = 0; + reg->valid = false; - if (reg->valid == 0) { + if (!reg->valid) { int retval = reg->type->get(reg); if (retval != ERROR_OK) { LOG_ERROR("Could not read register '%s'", reg->name); @@ -3175,7 +3150,7 @@ COMMAND_HANDLER(handle_reg_command) not_found: command_print(CMD, "register %s not found in current target", CMD_ARGV[0]); - return ERROR_OK; + return ERROR_FAIL; } COMMAND_HANDLER(handle_poll_command) @@ -3249,8 +3224,11 @@ int target_wait_state(struct target *target, enum target_state state, unsigned i nvp_value2name(nvp_target_state, state)->name); } - if (cur-then > 500) + if (cur - then > 500) { keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + } if ((cur-then) > ms) { LOG_ERROR("timed out while waiting for target %s", @@ -3532,6 +3510,11 @@ static int target_fill_mem(struct target *target, break; /* avoid GDB timeouts */ keep_alive(); + + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + break; + } } free(target_buf); @@ -3874,6 +3857,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver } } keep_alive(); + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + free(data); + free(buffer); + goto done; + } } } free(data); @@ -3926,24 +3915,24 @@ static int handle_bp_command_list(struct command_invocation *cmd) if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_hex_str(breakpoint->orig_instr, breakpoint->length); - command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, 0x%s", + command_print(cmd, "Software breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, orig_instr=0x%s", breakpoint->address, breakpoint->length, buf); free(buf); } else { if ((breakpoint->address == 0) && (breakpoint->asid != 0)) - command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %u", + command_print(cmd, "Context breakpoint: asid=0x%8.8" PRIx32 ", len=0x%x, num=%u", breakpoint->asid, breakpoint->length, breakpoint->number); else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u", + command_print(cmd, "Hybrid breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, num=%u", breakpoint->address, breakpoint->length, breakpoint->number); command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32, breakpoint->asid); } else - command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u", + command_print(cmd, "Hardware breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, num=%u", breakpoint->address, breakpoint->length, breakpoint->number); } @@ -3967,7 +3956,7 @@ static int handle_bp_command_set(struct command_invocation *cmd, } else if (addr == 0) { if (!target->type->add_context_breakpoint) { - LOG_ERROR("Context breakpoint not available"); + LOG_TARGET_ERROR(target, "Context breakpoint not available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = context_breakpoint_add(target, asid, length, hw); @@ -3977,7 +3966,7 @@ static int handle_bp_command_set(struct command_invocation *cmd, } else { if (!target->type->add_hybrid_breakpoint) { - LOG_ERROR("Hybrid breakpoint not available"); + LOG_TARGET_ERROR(target, "Hybrid breakpoint not available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = hybrid_breakpoint_add(target, addr, asid, length, hw); @@ -4034,21 +4023,31 @@ COMMAND_HANDLER(handle_bp_command) COMMAND_HANDLER(handle_rbp_command) { + int retval; + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; struct target *target = get_current_target(CMD_CTX); if (!strcmp(CMD_ARGV[0], "all")) { - breakpoint_remove_all(target); + retval = breakpoint_remove_all(target); + + if (retval != ERROR_OK) { + command_print(CMD, "Error encountered during removal of all breakpoints."); + command_print(CMD, "Some breakpoints may have remained set."); + } } else { target_addr_t addr; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - breakpoint_remove(target, addr); + retval = breakpoint_remove(target, addr); + + if (retval != ERROR_OK) + command_print(CMD, "Error during removal of breakpoint at address " TARGET_ADDR_FMT, addr); } - return ERROR_OK; + return retval; } COMMAND_HANDLER(handle_wp_command) @@ -4059,13 +4058,14 @@ COMMAND_HANDLER(handle_wp_command) struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { + char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a')); 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, + ", r/w/a: %c, value: 0x%8.8" PRIx64 + ", mask: 0x%8.8" PRIx64, watchpoint->address, watchpoint->length, - (int)watchpoint->rw, + wp_type, watchpoint->value, watchpoint->mask); watchpoint = watchpoint->next; @@ -4076,15 +4076,20 @@ COMMAND_HANDLER(handle_wp_command) enum watchpoint_rw type = WPT_ACCESS; target_addr_t addr = 0; uint32_t length = 0; - uint32_t data_value = 0x0; - uint32_t data_mask = 0xffffffff; + uint64_t data_value = 0x0; + uint64_t data_mask = WATCHPOINT_IGNORE_DATA_VALUE_MASK; + bool mask_specified = false; switch (CMD_ARGC) { case 5: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], data_mask); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[4], data_mask); + mask_specified = true; /* fall through */ case 4: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], data_value); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], data_value); + // if user specified only data value without mask - the mask should be 0 + if (!mask_specified) + data_mask = 0; /* fall through */ case 3: switch (CMD_ARGV[2][0]) { @@ -4098,7 +4103,7 @@ COMMAND_HANDLER(handle_wp_command) type = WPT_ACCESS; break; default: - LOG_ERROR("invalid watchpoint mode ('%c')", CMD_ARGV[2][0]); + LOG_TARGET_ERROR(target, "invalid watchpoint mode ('%c')", CMD_ARGV[2][0]); return ERROR_COMMAND_SYNTAX_ERROR; } /* fall through */ @@ -4114,23 +4119,37 @@ COMMAND_HANDLER(handle_wp_command) int retval = watchpoint_add(target, addr, length, type, data_value, data_mask); if (retval != ERROR_OK) - LOG_ERROR("Failure setting watchpoints"); + LOG_TARGET_ERROR(target, "Failure setting watchpoints"); return retval; } COMMAND_HANDLER(handle_rwp_command) { + int retval; + 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); - watchpoint_remove(target, addr); + if (!strcmp(CMD_ARGV[0], "all")) { + retval = watchpoint_remove_all(target); - return ERROR_OK; + if (retval != ERROR_OK) { + command_print(CMD, "Error encountered during removal of all watchpoints."); + command_print(CMD, "Some watchpoints may have remained set."); + } + } else { + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + + retval = watchpoint_remove(target, addr); + + if (retval != ERROR_OK) + command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr); + } + + return retval; } /** @@ -4293,7 +4312,7 @@ COMMAND_HANDLER(handle_profile_command) if ((CMD_ARGC != 2) && (CMD_ARGC != 4)) return ERROR_COMMAND_SYNTAX_ERROR; - const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000; + const uint32_t MAX_PROFILE_SAMPLE_NUM = 1000000; uint32_t offset; uint32_t num_of_samples; int retval = ERROR_OK; @@ -4374,192 +4393,6 @@ COMMAND_HANDLER(handle_profile_command) return retval; } -static int new_u64_array_element(Jim_Interp *interp, const char *varname, int idx, uint64_t val) -{ - char *namebuf; - Jim_Obj *obj_name, *obj_val; - int result; - - namebuf = alloc_printf("%s(%d)", varname, idx); - if (!namebuf) - return JIM_ERR; - - 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(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; -} - -static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) -{ - int e; - - LOG_WARNING("DEPRECATED! use 'read_memory' not 'mem2array'"); - - /* 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; - } - - /* 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); - 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; - - /* 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); - if (e != JIM_OK) - return e; - size_t len = l; - - /* Arg 4: phys */ - bool is_phys = false; - if (argc > 4) { - 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; - } - - /* Argument checks */ - if (len == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); - return JIM_ERR; - } - if ((addr + (len * width)) < addr) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); - return JIM_ERR; - } - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - 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)) || - ((width == 8) && ((addr & 7) == 0))) { - /* alignment correct */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "mem2array address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", - addr, - width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* index counter */ - size_t idx = 0; - - const size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - 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.. */ - - int retval; - if (is_phys) - retval = target_read_phys_memory(target, addr, width, chunk_len, buffer); - else - retval = target_read_memory(target, addr, width, chunk_len, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("mem2array: Read @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", - addr, - width, - chunk_len); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); - e = JIM_ERR; - break; - } else { - 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; - case 2: - v = target_buffer_get_u16(target, &buffer[i*width]); - break; - case 1: - v = buffer[i] & 0x0ff; - break; - } - new_u64_array_element(interp, varname, idx, v); - } - len -= chunk_len; - addr += chunk_len * width; - } - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; -} - COMMAND_HANDLER(handle_target_read_memory) { /* @@ -4683,201 +4516,6 @@ COMMAND_HANDLER(handle_target_read_memory) return ERROR_OK; } -static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t idx, uint64_t *val) -{ - char *namebuf = alloc_printf("%s(%zu)", varname, idx); - if (!namebuf) - return JIM_ERR; - - Jim_Obj *obj_name = Jim_NewStringObj(interp, namebuf, -1); - if (!obj_name) { - free(namebuf); - return JIM_ERR; - } - - Jim_IncrRefCount(obj_name); - Jim_Obj *obj_val = Jim_GetVariable(interp, obj_name, JIM_ERRMSG); - Jim_DecrRefCount(interp, obj_name); - free(namebuf); - if (!obj_val) - return JIM_ERR; - - jim_wide wide_val; - int result = Jim_GetWide(interp, obj_val, &wide_val); - *val = wide_val; - return result; -} - -static int target_array2mem(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj *const *argv) -{ - int e; - - LOG_WARNING("DEPRECATED! use 'write_memory' not 'array2mem'"); - - /* 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; - } - - /* 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); - 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; - - /* 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); - if (e != JIM_OK) - return e; - size_t len = l; - - /* Arg 4: Phys */ - bool is_phys = false; - if (argc > 4) { - 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; - } - - /* 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; - } - - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "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)) || - ((width == 8) && ((addr & 7) == 0))) { - /* alignment correct */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "array2mem address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", - addr, - width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* assume ok */ - e = JIM_OK; - - const size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - 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; - - const size_t chunk_len = MIN(len, max_chunk_len); /* in elements.. */ - - /* 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; - case 2: - target_buffer_set_u16(target, &buffer[i * width], v); - break; - case 1: - buffer[i] = v & 0x0ff; - break; - } - } - len -= chunk_len; - - /* Write the buffer to memory */ - int retval; - if (is_phys) - retval = target_write_phys_memory(target, addr, width, chunk_len, buffer); - else - retval = target_write_memory(target, addr, width, chunk_len, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("array2mem: Write @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", - addr, - width, - chunk_len); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); - e = JIM_ERR; - break; - } - addr += chunk_len * width; - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; -} - static int target_jim_write_memory(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { @@ -5026,8 +4664,7 @@ void target_handle_event(struct target *target, enum target_event e) 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, + LOG_DEBUG("target: %s (%s) event: %d (%s) action: %s", target_name(target), target_type_name(target), e, @@ -5115,7 +4752,7 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc, return JIM_ERR; } - if (force) { + if (force || !reg->valid) { int retval = reg->type->get(reg); if (retval != ERROR_OK) { @@ -5214,7 +4851,7 @@ static int target_jim_set_reg(Jim_Interp *interp, int argc, /** * Returns true only if the target has a handler for the specified event. */ -bool target_has_event_action(struct target *target, enum target_event event) +bool target_has_event_action(const struct target *target, enum target_event event) { struct target_event_action *teap; @@ -5446,13 +5083,13 @@ no_params: e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; - /* make this exactly 1 or 0 */ - target->backup_working_area = (!!w); + /* make this boolean */ + target->backup_working_area = (w != 0); } else { if (goi->argc != 0) goto no_params; } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area ? 1 : 0)); /* loop for more e*/ break; @@ -5615,24 +5252,6 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a return target_configure(&goi, target); } -static int jim_target_mem2array(Jim_Interp *interp, - int argc, Jim_Obj *const *argv) -{ - 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 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); -} - COMMAND_HANDLER(handle_target_examine) { bool allow_defer = false; @@ -5812,8 +5431,7 @@ COMMAND_HANDLER(handle_target_event_list) struct target *target = get_current_target(CMD_CTX); struct target_event_action *teap = target->event_action; - command_print(CMD, "Event actions for target (%d) %s\n", - target->target_number, + command_print(CMD, "Event actions for target %s\n", target_name(target)); command_print(CMD, "%-25s | Body", "Event"); command_print(CMD, "------------------------- | " @@ -5840,6 +5458,28 @@ COMMAND_HANDLER(handle_target_current_state) return ERROR_OK; } +COMMAND_HANDLER(handle_target_debug_reason) +{ + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct target *target = get_current_target(CMD_CTX); + + + const char *debug_reason = nvp_value2name(nvp_target_debug_reason, + target->debug_reason)->name; + + if (!debug_reason) { + command_print(CMD, "bug: invalid debug reason (%d)", + target->debug_reason); + return ERROR_FAIL; + } + + command_print(CMD, "%s", debug_reason); + + return ERROR_OK; +} + static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct jim_getopt_info goi; @@ -5933,22 +5573,6 @@ static const struct command_registration target_instance_command_handlers[] = { .help = "Display target memory as 8-bit bytes", .usage = "address [count]", }, - { - .name = "array2mem", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_array2mem, - .help = "Writes Tcl array of 8/16/32 bit numbers " - "to target memory", - .usage = "arrayname bitwidth address count", - }, - { - .name = "mem2array", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_mem2array, - .help = "Loads Tcl array of 8/16/32 bit numbers " - "from target memory", - .usage = "arrayname bitwidth address count", - }, { .name = "get_reg", .mode = COMMAND_EXEC, @@ -5991,6 +5615,13 @@ static const struct command_registration target_instance_command_handlers[] = { .help = "displays the current state of this target", .usage = "", }, + { + .name = "debug_reason", + .mode = COMMAND_EXEC, + .handler = handle_target_debug_reason, + .help = "displays the debug reason of this target", + .usage = "", + }, { .name = "arp_examine", .mode = COMMAND_EXEC, @@ -6090,7 +5721,7 @@ static int target_create(struct jim_getopt_info *goi) if (e != JIM_OK) return e; struct transport *tr = get_current_transport(); - if (tr->override_target) { + if (tr && tr->override_target) { e = tr->override_target(&cp); if (e != ERROR_OK) { LOG_ERROR("The selected transport doesn't support this target"); @@ -6133,9 +5764,6 @@ static int target_create(struct jim_getopt_info *goi) /* set empty smp cluster */ target->smp_targets = &empty_smp_targets; - /* set target number */ - target->target_number = new_target_number(); - /* allocate memory for each unique target type */ target->type = malloc(sizeof(struct target_type)); if (!target->type) { @@ -6152,7 +5780,7 @@ static int target_create(struct jim_getopt_info *goi) target->working_area = 0x0; target->working_area_size = 0x0; target->working_areas = NULL; - target->backup_working_area = 0; + target->backup_working_area = false; target->state = TARGET_UNKNOWN; target->debug_reason = DBG_REASON_UNDEFINED; @@ -6666,8 +6294,8 @@ COMMAND_HANDLER(handle_ps_command) struct target *target = get_current_target(CMD_CTX); char *display; if (target->state != TARGET_HALTED) { - LOG_INFO("target not halted !!"); - return ERROR_OK; + command_print(CMD, "Error: [%s] not halted", target_name(target)); + return ERROR_TARGET_NOT_HALTED; } if ((target->rtos) && (target->rtos->type) @@ -6698,8 +6326,8 @@ COMMAND_HANDLER(handle_test_mem_access_command) int retval = ERROR_OK; if (target->state != TARGET_HALTED) { - LOG_INFO("target not halted !!"); - return ERROR_FAIL; + command_print(CMD, "Error: [%s] not halted", target_name(target)); + return ERROR_TARGET_NOT_HALTED; } if (CMD_ARGC != 1) @@ -6879,8 +6507,8 @@ static const struct command_registration target_exec_command_handlers[] = { .mode = COMMAND_ANY, .help = "Load image into server memory for later use by " "fast_load; primarily for profiling", - .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " - "[min_address [max_length]]", + .usage = "filename [address ['bin'|'ihex'|'elf'|'s19' " + "[min_address [max_length]]]]", }, { .name = "fast_load", @@ -7040,21 +6668,21 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_wp_command, .mode = COMMAND_EXEC, .help = "list (no params) or create watchpoints", - .usage = "[address length [('r'|'w'|'a') value [mask]]]", + .usage = "[address length [('r'|'w'|'a') [value [mask]]]]", }, { .name = "rwp", .handler = handle_rwp_command, .mode = COMMAND_EXEC, .help = "remove watchpoint", - .usage = "address", + .usage = "'all' | address", }, { .name = "load_image", .handler = handle_load_image_command, .mode = COMMAND_EXEC, - .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " - "[min_address] [max_length]", + .usage = "filename [address ['bin'|'ihex'|'elf'|'s19' " + "[min_address [max_length]]]]", }, { .name = "dump_image", @@ -7108,6 +6736,13 @@ static const struct command_registration target_exec_command_handlers[] = { .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, + { + .name = "debug_reason", + .mode = COMMAND_EXEC, + .handler = handle_target_debug_reason, + .help = "displays the debug reason of this target", + .usage = "", + }, { .name = "reset_nag", .handler = handle_target_reset_nag, @@ -7147,3 +6782,29 @@ static int target_register_user_commands(struct command_context *cmd_ctx) return register_commands(cmd_ctx, NULL, target_exec_command_handlers); } + +const char *target_debug_reason_str(enum target_debug_reason reason) +{ + switch (reason) { + case DBG_REASON_DBGRQ: + return "DBGRQ"; + case DBG_REASON_BREAKPOINT: + return "BREAKPOINT"; + case DBG_REASON_WATCHPOINT: + return "WATCHPOINT"; + case DBG_REASON_WPTANDBKPT: + return "WPTANDBKPT"; + case DBG_REASON_SINGLESTEP: + return "SINGLESTEP"; + case DBG_REASON_NOTHALTED: + return "NOTHALTED"; + case DBG_REASON_EXIT: + return "EXIT"; + case DBG_REASON_EXC_CATCH: + return "EXC_CATCH"; + case DBG_REASON_UNDEFINED: + return "UNDEFINED"; + default: + return "UNKNOWN!"; + } +}