X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=a3230d2486fbccac84221cd2f6383669b9625400;hp=253928d7c3ce0c9a2c1e0ea0f258ce6c981b19ff;hb=17a052d6fe44fc265d48e94bdd3356d6f25ca064;hpb=ab858febb6ca6e5dada1492e96c00d8b12c575c0 diff --git a/src/target/target.c b/src/target/target.c index 253928d7c3..a3230d2486 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -108,6 +108,8 @@ extern struct target_type quark_x10xx_target; extern struct target_type quark_d20xx_target; extern struct target_type stm8_target; extern struct target_type riscv_target; +extern struct target_type mem_ap_target; +extern struct target_type esirisc_target; static struct target_type *target_types[] = { &arm7tdmi_target, @@ -141,6 +143,8 @@ static struct target_type *target_types[] = { &quark_d20xx_target, &stm8_target, &riscv_target, + &mem_ap_target, + &esirisc_target, #if BUILD_TARGET64 &aarch64_target, #endif @@ -513,9 +517,7 @@ struct target *get_target_by_num(int num) struct target *get_current_target(struct command_context *cmd_ctx) { - struct target *target = cmd_ctx->current_target_override - ? cmd_ctx->current_target_override - : cmd_ctx->current_target; + struct target *target = get_current_target_or_null(cmd_ctx); if (target == NULL) { LOG_ERROR("BUG: current_target out of bounds"); @@ -525,6 +527,13 @@ struct target *get_current_target(struct command_context *cmd_ctx) return target; } +struct target *get_current_target_or_null(struct command_context *cmd_ctx) +{ + return cmd_ctx->current_target_override + ? cmd_ctx->current_target_override + : cmd_ctx->current_target; +} + int target_poll(struct target *target) { int retval; @@ -1043,6 +1052,9 @@ int target_run_flash_async_algorithm(struct target *target, retval = target_write_u32(target, wp_addr, wp); if (retval != ERROR_OK) break; + + /* Avoid GDB timeouts */ + keep_alive(); } if (retval != ERROR_OK) { @@ -1197,12 +1209,29 @@ int target_hit_watchpoint(struct target *target, return target->type->hit_watchpoint(target, hit_watchpoint); } +const char *target_get_gdb_arch(struct target *target) +{ + if (target->type->get_gdb_arch == NULL) + return NULL; + return target->type->get_gdb_arch(target); +} + int target_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } + +bool target_supports_gdb_connection(struct target *target) +{ + /* + * based on current code, we can simply exclude all the targets that + * don't provide get_gdb_reg_list; this could change with new targets. + */ + return !!target->type->get_gdb_reg_list; +} + int target_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { @@ -1431,7 +1460,8 @@ int target_register_trace_callback(int (*callback)(struct target *target, return ERROR_OK; } -int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv) +int target_register_timer_callback(int (*callback)(void *priv), + unsigned int time_ms, enum target_timer_type type, void *priv) { struct target_timer_callback **callbacks_p = &target_timer_callbacks; @@ -1446,7 +1476,7 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int (*callbacks_p) = malloc(sizeof(struct target_timer_callback)); (*callbacks_p)->callback = callback; - (*callbacks_p)->periodic = periodic; + (*callbacks_p)->type = type; (*callbacks_p)->time_ms = time_ms; (*callbacks_p)->removed = false; @@ -1596,7 +1626,7 @@ static int target_call_timer_callback(struct target_timer_callback *cb, { cb->callback(cb->priv); - if (cb->periodic) + if (cb->type == TARGET_TIMER_TYPE_PERIODIC) return target_timer_callback_periodic_restart(cb, now); return target_unregister_timer_callback(cb->callback, cb->priv); @@ -1630,7 +1660,7 @@ static int target_call_timer_callbacks_check_time(int checktime) } bool call_it = (*callback)->callback && - ((!checktime && (*callback)->periodic) || + ((!checktime && (*callback)->type == TARGET_TIMER_TYPE_PERIODIC) || timeval_compare(&now, &(*callback)->when) >= 0); if (call_it) @@ -1890,6 +1920,65 @@ int target_free_working_area(struct target *target, struct working_area *area) return target_free_working_area_restore(target, area, 1); } +/* free resources and restore memory, if restoring memory fails, + * free up resources anyway + */ +static void target_free_all_working_areas_restore(struct target *target, int restore) +{ + struct working_area *c = target->working_areas; + + LOG_DEBUG("freeing all working areas"); + + /* Loop through all areas, restoring the allocated ones and marking them as free */ + while (c) { + if (!c->free) { + if (restore) + target_restore_working_area(target, c); + c->free = true; + *c->user = NULL; /* Same as above */ + c->user = NULL; + } + c = c->next; + } + + /* Run a merge pass to combine all areas into one */ + target_merge_working_areas(target); + + print_wa_layout(target); +} + +void target_free_all_working_areas(struct target *target) +{ + target_free_all_working_areas_restore(target, 1); + + /* Now we have none or only one working area marked as free */ + if (target->working_areas) { + /* Free the last one to allow on-the-fly moving and resizing */ + free(target->working_areas->backup); + free(target->working_areas); + target->working_areas = NULL; + } +} + +/* Find the largest number of bytes that can be allocated */ +uint32_t target_get_working_area_avail(struct target *target) +{ + struct working_area *c = target->working_areas; + uint32_t max_size = 0; + + if (c == NULL) + return target->working_area_size; + + while (c) { + if (c->free && max_size < c->size) + max_size = c->size; + + c = c->next; + } + + return max_size; +} + static void target_destroy(struct target *target) { if (target->type->deinit_target) @@ -1909,11 +1998,6 @@ static void target_destroy(struct target *target) } target_free_all_working_areas(target); - /* Now we have none or only one working area marked as free */ - if (target->working_areas) { - free(target->working_areas->backup); - free(target->working_areas); - } /* release the targets SMP list */ if (target->smp) { @@ -1964,57 +2048,6 @@ void target_quit(void) all_targets = NULL; } -/* free resources and restore memory, if restoring memory fails, - * free up resources anyway - */ -static void target_free_all_working_areas_restore(struct target *target, int restore) -{ - struct working_area *c = target->working_areas; - - LOG_DEBUG("freeing all working areas"); - - /* Loop through all areas, restoring the allocated ones and marking them as free */ - while (c) { - if (!c->free) { - if (restore) - target_restore_working_area(target, c); - c->free = true; - *c->user = NULL; /* Same as above */ - c->user = NULL; - } - c = c->next; - } - - /* Run a merge pass to combine all areas into one */ - target_merge_working_areas(target); - - print_wa_layout(target); -} - -void target_free_all_working_areas(struct target *target) -{ - target_free_all_working_areas_restore(target, 1); -} - -/* Find the largest number of bytes that can be allocated */ -uint32_t target_get_working_area_avail(struct target *target) -{ - struct working_area *c = target->working_areas; - uint32_t max_size = 0; - - if (c == NULL) - return target->working_area_size; - - while (c) { - if (c->free && max_size < c->size) - max_size = c->size; - - c = c->next; - } - - return max_size; -} - int target_arch_state(struct target *target) { int retval; @@ -2792,6 +2825,8 @@ COMMAND_HANDLER(handle_reg_command) for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) { + if (reg->exist == false) + continue; /* only print cached values if they are valid */ if (reg->valid) { value = buf_to_str(reg->value, @@ -2845,14 +2880,15 @@ COMMAND_HANDLER(handle_reg_command) /* access a single register by its name */ reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1); - if (!reg) { - command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); - return ERROR_OK; - } + if (!reg) + goto not_found; } assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ + if (!reg->exist) + goto not_found; + /* display a register */ if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')))) { @@ -2886,6 +2922,10 @@ COMMAND_HANDLER(handle_reg_command) } return ERROR_COMMAND_SYNTAX_ERROR; + +not_found: + command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); + return ERROR_OK; } COMMAND_HANDLER(handle_poll_command) @@ -3680,38 +3720,31 @@ static int handle_bp_command_set(struct command_context *cmd_ctx, if (asid == 0) { retval = breakpoint_add(target, addr, length, hw); + /* error is always logged in breakpoint_add(), do not print it again */ if (ERROR_OK == retval) command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr); - else { - LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); - return retval; - } + } else if (addr == 0) { if (target->type->add_context_breakpoint == NULL) { - LOG_WARNING("Context breakpoint not available"); - return ERROR_OK; + LOG_ERROR("Context breakpoint not available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = context_breakpoint_add(target, asid, length, hw); + /* error is always logged in context_breakpoint_add(), do not print it again */ if (ERROR_OK == retval) command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); - else { - LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used"); - return retval; - } + } else { if (target->type->add_hybrid_breakpoint == NULL) { - LOG_WARNING("Hybrid breakpoint not available"); - return ERROR_OK; + LOG_ERROR("Hybrid breakpoint not available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = hybrid_breakpoint_add(target, addr, asid, length, hw); + /* error is always logged in hybrid_breakpoint_add(), do not print it again */ if (ERROR_OK == retval) command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); - else { - LOG_ERROR("Failure setting breakpoint, the same address is already used"); - return retval; - } } - return ERROR_OK; + return retval; } COMMAND_HANDLER(handle_bp_command) @@ -5843,8 +5876,7 @@ static const struct command_registration target_subcommand_handlers[] = { }, { .name = "create", - /* REVISIT this should be COMMAND_CONFIG ... */ - .mode = COMMAND_ANY, + .mode = COMMAND_CONFIG, .jim_handler = jim_target_create, .usage = "name type '-chain-position' name [options ...]", .help = "Creates and selects a new target",