extern struct target_type mips_m4k_target;
extern struct target_type avr_target;
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;
static struct target_type *target_types[] =
{
&mips_m4k_target,
&avr_target,
&dsp563xx_target,
+ &dsp5680xx_target,
&testee_target,
&avr32_ap7k_target,
+ &stm32_stlink_target,
NULL,
};
*buffer = value;
}
+/* write a uint32_t array to a buffer in target memory endianness */
+void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf)
+{
+ uint32_t i;
+ for(i = 0; i < count; i ++)
+ dstbuf[i] = target_buffer_get_u32(target,&buffer[i*4]);
+}
+
+/* write a uint16_t array to a buffer in target memory endianness */
+void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf)
+{
+ uint32_t i;
+ for(i = 0; i < count; i ++)
+ dstbuf[i] = target_buffer_get_u16(target,&buffer[i*2]);
+}
+
+/* write a uint32_t array to a buffer in target memory endianness */
+void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, uint32_t *srcbuf)
+{
+ uint32_t i;
+ for(i = 0; i < count; i ++)
+ target_buffer_set_u32(target,&buffer[i*4],srcbuf[i]);
+}
+
+/* write a uint16_t array to a buffer in target memory endianness */
+void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, uint16_t *srcbuf)
+{
+ uint32_t i;
+ for(i = 0; i < count; i ++)
+ target_buffer_set_u16(target,&buffer[i*2],srcbuf[i]);
+}
+
/* return a pointer to a configured target; id is name or number */
struct target *get_target(const char *id)
{
return retval;
}
+/**
+ * Downloads a target-specific native code algorithm to the target,
+ * executes and leaves it running.
+ *
+ * @param target used to run the algorithm
+ * @param arch_info target-specific description of the algorithm.
+ */
+int target_start_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ uint32_t entry_point, uint32_t exit_point,
+ void *arch_info)
+{
+ int retval = ERROR_FAIL;
+
+ if (!target_was_examined(target))
+ {
+ LOG_ERROR("Target not examined yet");
+ goto done;
+ }
+ if (!target->type->start_algorithm) {
+ LOG_ERROR("Target type '%s' does not support %s",
+ target_type_name(target), __func__);
+ goto done;
+ }
+ if (target->running_alg) {
+ LOG_ERROR("Target is already running an algorithm");
+ goto done;
+ }
+
+ target->running_alg = true;
+ retval = target->type->start_algorithm(target,
+ num_mem_params, mem_params,
+ num_reg_params, reg_params,
+ entry_point, exit_point, arch_info);
+
+done:
+ return retval;
+}
+
+/**
+ * Waits for an algorithm started with target_start_algorithm() to complete.
+ *
+ * @param target used to run the algorithm
+ * @param arch_info target-specific description of the algorithm.
+ */
+int target_wait_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ uint32_t exit_point, int timeout_ms,
+ void *arch_info)
+{
+ int retval = ERROR_FAIL;
+
+ if (!target->type->wait_algorithm) {
+ LOG_ERROR("Target type '%s' does not support %s",
+ target_type_name(target), __func__);
+ goto done;
+ }
+ if (!target->running_alg) {
+ LOG_ERROR("Target is not running an algorithm");
+ goto done;
+ }
+
+ retval = target->type->wait_algorithm(target,
+ num_mem_params, mem_params,
+ num_reg_params, reg_params,
+ exit_point, timeout_ms, arch_info);
+ if (retval != ERROR_TARGET_TIMEOUT)
+ 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->add_breakpoint(target, breakpoint);
}
+
+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);
+ return ERROR_TARGET_NOT_HALTED;
+ }
+ return target->type->add_context_breakpoint(target, breakpoint);
+}
+
+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);
+ return ERROR_TARGET_NOT_HALTED;
+ }
+ return target->type->add_hybrid_breakpoint(target, breakpoint);
+}
+
int target_remove_breakpoint(struct target *target,
struct breakpoint *breakpoint)
{
if (type->check_reset== NULL)
type->check_reset = default_check_reset;
+ assert(type->init_target != NULL);
+
int retval = type->init_target(cmd_ctx, target);
if (ERROR_OK != retval)
{
COMMAND_HANDLER(handle_target_init_command)
{
+ int retval;
+
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
}
target_initialized = true;
+ retval = command_run_line(CMD_CTX, "init_targets");
+ if (ERROR_OK != retval)
+ return retval;
+
LOG_DEBUG("Initializing targets...");
return target_init(CMD_CTX);
}
if (callback == NULL)
{
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if (*callbacks_p)
if (callback == NULL)
{
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if (*callbacks_p)
if (callback == NULL)
{
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
while (c)
if (callback == NULL)
{
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
while (c)
if (buffer == NULL)
{
LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size);
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
retval = target_read_buffer(target, address, size, buffer);
if (retval != ERROR_OK)
return retval;
}
-COMMAND_HANDLER(handle_targets_command)
+static int find_target(struct command_context *cmd_ctx, const char *name)
{
- struct target *target = all_targets;
+ struct target *target = get_target(name);
+ if (target == NULL) {
+ LOG_ERROR("Target: %s is unknown, try one of:\n", name);
+ return ERROR_FAIL;
+ }
+ if (!target->tap->enabled) {
+ LOG_USER("Target: TAP %s is disabled, "
+ "can't be the current target\n",
+ target->tap->dotted_name);
+ return ERROR_FAIL;
+ }
+
+ cmd_ctx->current_target = target->target_number;
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_targets_command)
+{
+ int retval = ERROR_OK;
if (CMD_ARGC == 1)
{
- target = get_target(CMD_ARGV[0]);
- if (target == NULL) {
- command_print(CMD_CTX,"Target: %s is unknown, try one of:\n", CMD_ARGV[0]);
- goto DumpTargets;
- }
- if (!target->tap->enabled) {
- command_print(CMD_CTX,"Target: TAP %s is disabled, "
- "can't be the current target\n",
- target->tap->dotted_name);
- return ERROR_FAIL;
+ retval = find_target(CMD_CTX, CMD_ARGV[0]);
+ if (retval == ERROR_OK) {
+ /* we're done! */
+ return retval;
}
-
- CMD_CTX->current_target = target->target_number;
- return ERROR_OK;
}
-DumpTargets:
- target = all_targets;
+ struct target *target = all_targets;
command_print(CMD_CTX, " TargetName Type Endian TapName State ");
command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------");
while (target)
marker = '*';
/* keep columns lined up to match the headers above */
- command_print(CMD_CTX, "%2d%c %-18s %-10s %-6s %-18s %s",
- target->target_number,
- marker,
- target_name(target),
- target_type_name(target),
- Jim_Nvp_value2name_simple(nvp_target_endian,
- target->endianness)->name,
- target->tap->dotted_name,
- state);
+ command_print(CMD_CTX,
+ "%2d%c %-18s %-10s %-6s %-18s %s",
+ target->target_number,
+ marker,
+ target_name(target),
+ target_type_name(target),
+ Jim_Nvp_value2name_simple(nvp_target_endian,
+ target->endianness)->name,
+ target->tap->dotted_name,
+ state);
target = target->next;
}
- return ERROR_OK;
+ return retval;
}
/* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */
}
}
+ assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */
+
/* display a register */
if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9'))))
{
if (CMD_ARGC == 2)
{
uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8));
+ if (buf == NULL)
+ return ERROR_FAIL;
str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0);
reg->type->set(reg, buf);
return ERROR_OK;
}
- command_print(CMD_CTX, "usage: reg <#|name> [value]");
-
- return ERROR_OK;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_HANDLER(handle_poll_command)
int retval = parse_uint(CMD_ARGV[0], &ms);
if (ERROR_OK != retval)
{
- command_print(CMD_CTX, "usage: %s [seconds]", CMD_NAME);
return ERROR_COMMAND_SYNTAX_ERROR;
}
// convert seconds (given) to milliseconds (needed)
{
char* buf = buf_to_str(breakpoint->orig_instr,
breakpoint->length, 16);
- command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i, 0x%s",
+ command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s",
breakpoint->address,
breakpoint->length,
breakpoint->set, buf);
}
else
{
- command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i",
- breakpoint->address,
- breakpoint->length, breakpoint->set);
+ if ((breakpoint->address == 0) && (breakpoint->asid != 0))
+ command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i",
+ breakpoint->asid,
+ breakpoint->length, breakpoint->set);
+ else if ((breakpoint->address != 0) && (breakpoint->asid != 0))
+ {
+ command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
+ breakpoint->address,
+ breakpoint->length, breakpoint->set);
+ command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
+ breakpoint->asid);
+ }
+ else
+ command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
+ breakpoint->address,
+ breakpoint->length, breakpoint->set);
}
breakpoint = breakpoint->next;
}
static int handle_bp_command_set(struct command_context *cmd_ctx,
- uint32_t addr, uint32_t length, int hw)
+ uint32_t addr, uint32_t asid, uint32_t length, int hw)
{
struct target *target = get_current_target(cmd_ctx);
- int retval = breakpoint_add(target, addr, length, hw);
- if (ERROR_OK == retval)
- command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
+
+ if (asid == 0)
+ {
+ int retval = breakpoint_add(target, addr, length, hw);
+ if (ERROR_OK == retval)
+ command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
+ else
+ {
+ LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used");
+ return retval;
+ }
+ }
+ else if (addr == 0)
+ {
+ int retval = context_breakpoint_add(target, asid, length, hw);
+ 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
- LOG_ERROR("Failure setting breakpoint");
- return retval;
+ {
+ int retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
+ 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;
}
COMMAND_HANDLER(handle_bp_command)
{
- if (CMD_ARGC == 0)
- return handle_bp_command_list(CMD_CTX);
-
- if (CMD_ARGC < 2 || CMD_ARGC > 3)
- {
- command_print(CMD_CTX, "usage: bp <address> <length> ['hw']");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
uint32_t addr;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+ uint32_t asid;
uint32_t length;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
-
int hw = BKPT_SOFT;
- if (CMD_ARGC == 3)
+ switch(CMD_ARGC)
{
- if (strcmp(CMD_ARGV[2], "hw") == 0)
+ case 0:
+ return handle_bp_command_list(CMD_CTX);
+
+ case 2:
+ asid = 0;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
+ return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
+
+ case 3:
+ if(strcmp(CMD_ARGV[2], "hw") == 0)
+ {
+ hw = BKPT_HARD;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
+
+ asid = 0;
+ return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
+ }
+ else if(strcmp(CMD_ARGV[2], "hw_ctx") == 0)
+ {
+ hw = BKPT_HARD;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
+ addr = 0;
+ return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
+ }
+
+ case 4:
hw = BKPT_HARD;
- else
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length);
+ return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
+
+ default:
return ERROR_COMMAND_SYNTAX_ERROR;
}
-
- return handle_bp_command_set(CMD_CTX, addr, length, hw);
}
COMMAND_HANDLER(handle_rbp_command)
break;
default:
- command_print(CMD_CTX, "usage: wp [address length "
- "[(r|w|a) [value [mask]]]]");
return ERROR_COMMAND_SYNTAX_ERROR;
}
}
}
- int addressSpace = (max-min + 1);
+ int addressSpace = (max - min + 1);
+ assert(addressSpace >= 2);
static const uint32_t maxBuckets = 16 * 1024; /* maximum buckets. */
uint32_t length = addressSpace;
/* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */
struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1);
+ int retval = ERROR_OK;
for (;;)
{
- int retval;
target_poll(target);
if (target->state == TARGET_HALTED)
{
}
free(samples);
- return ERROR_OK;
+ return retval;
}
static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, uint32_t val)
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
e = JIM_ERR;
- len = 0;
+ break;
} else {
v = 0; /* shut up gcc */
for (i = 0 ;i < count ;i++, n++) {
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- return JIM_OK;
+ return e;
}
static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, uint32_t *val)
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL);
e = JIM_ERR;
- len = 0;
+ break;
}
}
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- return JIM_OK;
+ return e;
}
/* FIX? should we propagate errors here rather than printing them
free((void *)(target->variant));
}
e = Jim_GetOpt_String(goi, &cp, NULL);
+ if (e != JIM_OK)
+ return e;
target->variant = strdup(cp);
} else {
if (goi->argc != 0) {
/* TYPE */
e = Jim_GetOpt_String(goi, &cp2, NULL);
+ if (e != JIM_OK)
+ return e;
cp = cp2;
/* now does target type exist */
for (x = 0 ; target_types[x] ; x++) {
.name = cp,
.mode = COMMAND_ANY,
.help = "target command group",
+ .usage = "",
.chain = target_subcommands,
},
COMMAND_REGISTRATION_DONE
int i;
const char *targetname;
int retval,len;
- struct target *target;
+ struct target *target = (struct target *) NULL;
struct target_list *head, *curr, *new;
- curr = (struct target_list*) NULL;
- head = (struct target_list*) NULL;
- new = (struct target_list*) NULL;
+ curr = (struct target_list *) NULL;
+ head = (struct target_list *) NULL;
+ new = (struct target_list *) NULL;
retval = 0;
LOG_DEBUG("%d",argc);
/* argv[1] = target to associate in smp
- * argv[2] = target to assoicate in smp
+ * argv[2] = target to assoicate in smp
* argv[3] ...
*/
while(curr!=(struct target_list *)NULL)
{
- target=curr->target;
- target->smp = 1;
- target->head = head;
- curr=curr->next;
+ target = curr->target;
+ target->smp = 1;
+ target->head = head;
+ curr = curr->next;
}
- return retval;
+ if (target->rtos)
+ retval = rtos_smp_init(head->target);
+ return retval;
}
.mode = COMMAND_EXEC,
.help = "loads active fast load image to current target "
"- mainly for profiling purposes",
+ .usage = "",
},
{
.name = "profile",
.handler = handle_profile_command,
.mode = COMMAND_EXEC,
+ .usage = "seconds filename",
.help = "profiling samples the CPU PC",
},
/** @todo don't register virt2phys() unless target supports it */
.name = "soft_reset_halt",
.handler = handle_soft_reset_halt_command,
.mode = COMMAND_EXEC,
+ .usage = "",
.help = "halt the target and do a soft reset",
},
{
.handler = handle_bp_command,
.mode = COMMAND_EXEC,
.help = "list or set hardware or software breakpoint",
- .usage = "[address length ['hw']]",
+ .usage = "<address> [<asid>]<length> ['hw'|'hw_ctx']",
},
{
.name = "rbp",