* Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
- * Copyright (C) 2007,2008 Øyvind Harboe *
+ * Copyright (C) 2007-2009 Øyvind Harboe *
* oyvind.harboe@zylin.com *
* *
* Copyright (C) 2008, Duane Ellis *
extern target_type_t arm926ejs_target;
extern target_type_t fa526_target;
extern target_type_t feroceon_target;
+extern target_type_t dragonite_target;
extern target_type_t xscale_target;
extern target_type_t cortexm3_target;
extern target_type_t cortexa8_target;
&arm926ejs_target,
&fa526_target,
&feroceon_target,
+ &dragonite_target,
&xscale_target,
&cortexm3_target,
&cortexa8_target,
{ .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
{ .value = TARGET_EVENT_OLD_pre_resume , .name = "old-pre_resume" },
- { .value = TARGET_EVENT_EARLY_HALTED, .name = "early-halted" },
+ { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
{ .value = TARGET_EVENT_HALTED, .name = "halted" },
{ .value = TARGET_EVENT_RESUMED, .name = "resumed" },
{ .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
return cp;
}
-static int max_target_number(void)
-{
- target_t *t;
- int x;
-
- x = -1;
- t = all_targets;
- while (t) {
- if (x < t->target_number) {
- x = (t->target_number) + 1;
- }
- t = t->next;
- }
- return x;
-}
-
/* determine the number of the new target */
static int new_target_number(void)
{
return x + 1;
}
-static int target_continuous_poll = 1;
-
/* read a uint32_t from a buffer in target memory endianness */
uint32_t target_buffer_get_u32(target_t *target, const uint8_t *buffer)
{
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)
return NULL;
for (target = all_targets; target; target = target->next) {
- if (target->target_number == (int)num)
+ if (target->target_number == (int)num) {
+ LOG_WARNING("use '%s' as target identifier, not '%u'",
+ target->cmd_name, num);
return target;
+ }
}
return NULL;
return NULL;
}
-int get_num_by_target(target_t *query_target)
-{
- return query_target->target_number;
-}
-
target_t* get_current_target(command_context_t *cmd_ctx)
{
target_t *target = get_target_by_num(cmd_ctx->current_target);
int target_poll(struct target_s *target)
{
+ int retval;
+
/* We can't poll until after examine */
if (!target_was_examined(target))
{
/* Fail silently lest we pollute the log */
return ERROR_FAIL;
}
- return target->type->poll(target);
+
+ retval = target->type->poll(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (target->halt_issued)
+ {
+ if (target->state == TARGET_HALTED)
+ {
+ target->halt_issued = false;
+ } else
+ {
+ long long t = timeval_ms() - target->halt_issued_time;
+ if (t>1000)
+ {
+ target->halt_issued = false;
+ LOG_INFO("Halt timed out, wake up GDB.");
+ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
+ }
+ }
+ }
+
+ return ERROR_OK;
}
int target_halt(struct target_s *target)
{
+ int retval;
/* We can't poll until after examine */
if (!target_was_examined(target))
{
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
}
- return target->type->halt(target);
+
+ retval = target->type->halt(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ target->halt_issued = true;
+ target->halt_issued_time = timeval_ms();
+
+ return ERROR_OK;
}
int target_resume(struct target_s *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
* more predictable, i.e. dr/irscan & pathmove in events will
* not have JTAG operations injected into the middle of a sequence.
*/
- int save_poll = target_continuous_poll;
- target_continuous_poll = 0;
+ bool save_poll = jtag_poll_get_enabled();
+
+ jtag_poll_set_enabled(false);
sprintf(buf, "ocd_process_reset %s", n->name);
retval = Jim_Eval(interp, buf);
- target_continuous_poll = save_poll;
+ jtag_poll_set_enabled(save_poll);
if (retval != JIM_OK) {
Jim_PrintErrorMessage(interp);
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
}
+ if (!target->type->soft_reset_halt_imp) {
+ LOG_ERROR("Target %s does not support soft_reset_halt",
+ target->cmd_name);
+ return ERROR_FAIL;
+ }
return target->type->soft_reset_halt_imp(target);
}
if (event == TARGET_EVENT_HALTED)
{
/* execute early halted first */
- target_call_event_callbacks(target, TARGET_EVENT_EARLY_HALTED);
+ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
}
LOG_DEBUG("target event %i (%s)",
size -= aligned;
}
+ /*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)
{
register_command(cmd_ctx, NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value> [count]");
register_command(cmd_ctx, NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value> [count]");
- register_command(cmd_ctx, NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");
- register_command(cmd_ctx, NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint <adress>");
- register_command(cmd_ctx, NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");
- register_command(cmd_ctx, NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");
+ register_command(cmd_ctx, NULL, "bp",
+ handle_bp_command, COMMAND_EXEC,
+ "list or set breakpoint [<address> <length> [hw]]");
+ register_command(cmd_ctx, NULL, "rbp",
+ handle_rbp_command, COMMAND_EXEC,
+ "remove breakpoint <address>");
+ register_command(cmd_ctx, NULL, "wp",
+ handle_wp_command, COMMAND_EXEC,
+ "list or set watchpoint "
+ "[<address> <length> <r/w/a> [value] [mask]]");
+ register_command(cmd_ctx, NULL, "rwp",
+ handle_rwp_command, COMMAND_EXEC,
+ "remove watchpoint <address>");
register_command(cmd_ctx, NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19'] [min_address] [max_length]");
register_command(cmd_ctx, NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
return ERROR_OK;
}
+static void target_call_event_callbacks_all(enum target_event e) {
+ target_t *target;
+ target = all_targets;
+ while (target) {
+ target_call_event_callbacks(target, e);
+ target = target->next;
+ }
+}
+
/* process target state changes */
int handle_target(void *priv)
{
int did_something = 0;
if (runSrstAsserted)
{
+ target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT);
Jim_Eval(interp, "srst_asserted");
did_something = 1;
}
}
if (runPowerDropout)
{
+ target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT);
Jim_Eval(interp, "power_dropout");
did_something = 1;
}
* Skip targets that are currently disabled.
*/
for (target_t *target = all_targets;
- target_continuous_poll && target;
+ is_jtag_poll_safe() && target;
target = target->next)
{
if (!target->tap->enabled)
{
/* polling may fail silently until the target has been examined */
if ((retval = target_poll(target)) != ERROR_OK)
+ {
+ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
return retval;
+ }
}
}
while (cache)
{
int i;
- for (i = 0; i < cache->num_regs; i++)
+
+ for (i = 0, reg = cache->reg_list;
+ i < cache->num_regs;
+ i++, reg++, count++)
{
- value = buf_to_str(cache->reg_list[i].value, cache->reg_list[i].size, 16);
- command_print(cmd_ctx, "(%i) %s (/%i): 0x%s (dirty: %i, valid: %i)",
- count++,
- cache->reg_list[i].name,
- (int)(cache->reg_list[i].size),
- value,
- cache->reg_list[i].dirty,
- cache->reg_list[i].valid);
- free(value);
+ /* only print cached values if they are valid */
+ if (reg->valid) {
+ value = buf_to_str(reg->value,
+ reg->size, 16);
+ command_print(cmd_ctx,
+ "(%i) %s (/%" PRIu32 "): 0x%s%s",
+ count, reg->name,
+ reg->size, value,
+ reg->dirty
+ ? " (dirty)"
+ : "");
+ free(value);
+ } else {
+ command_print(cmd_ctx, "(%i) %s (/%" PRIu32 ")",
+ count, reg->name,
+ reg->size) ;
+ }
}
cache = cache->next;
}
if (argc == 0)
{
command_print(cmd_ctx, "background polling: %s",
- target_continuous_poll ? "on" : "off");
+ jtag_poll_get_enabled() ? "on" : "off");
command_print(cmd_ctx, "TAP: %s (%s)",
target->tap->dotted_name,
target->tap->enabled ? "enabled" : "disabled");
{
if (strcmp(args[0], "on") == 0)
{
- target_continuous_poll = 1;
+ jtag_poll_set_enabled(true);
}
else if (strcmp(args[0], "off") == 0)
{
- target_continuous_poll = 0;
+ jtag_poll_set_enabled(false);
}
else
{
break;
}
image_size += length;
- command_print(cmd_ctx, "%u byte written at address 0x%8.8" PRIx32 "",
+ command_print(cmd_ctx, "%u bytes written at address 0x%8.8" PRIx32 "",
(unsigned int)length,
image.sections[i].base_address + offset);
}
void target_handle_event(target_t *target, enum target_event e)
{
target_event_action_t *teap;
- int done;
- teap = target->event_action;
-
- done = 0;
- while (teap) {
+ for (teap = target->event_action; teap != NULL; teap = teap->next) {
if (teap->event == e) {
- done = 1;
LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s",
target->target_number,
target->cmd_name,
Jim_PrintErrorMessage(interp);
}
}
- teap = teap->next;
- }
- if (!done) {
- LOG_DEBUG("event: %d %s - no action",
- e,
- Jim_Nvp_value2name_simple(nvp_target_event, e)->name);
}
}
}
if (goi->isconfigure) {
+ bool replace = true;
if (teap == NULL) {
/* create new */
teap = calloc(1, sizeof(*teap));
+ replace = false;
}
teap->event = n->value;
Jim_GetOpt_Obj(goi, &o);
*/
Jim_IncrRefCount(teap->body);
- /* add to head of event list */
- teap->next = target->event_action;
- target->event_action = teap;
+ if (!replace)
+ {
+ /* add to head of event list */
+ teap->next = target->event_action;
+ target->event_action = teap;
+ }
Jim_SetEmptyResult(goi->interp);
} else {
/* get */
break;
case TS_CMD_RESET:
if (goi.argc != 2) {
- Jim_WrongNumArgs(interp, 2, argv, "t | f|assert | deassert BOOL");
+ Jim_WrongNumArgs(interp, 2, argv,
+ "([tT]|[fF]|assert|deassert) BOOL");
return JIM_ERR;
}
e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n);
}
if (!target->tap->enabled)
goto err_tap_disabled;
+ if (!target->type->assert_reset
+ || !target->type->deassert_reset) {
+ Jim_SetResult_sprintf(interp,
+ "No target-specific reset for %s",
+ target->cmd_name);
+ return JIM_ERR;
+ }
/* determine if we should halt or not. */
target->reset_halt = !!a;
/* When this happens - all workareas are invalid. */
target->display = 1;
+ target->halt_issued = false;
+
/* initialize trace information */
target->trace_info = malloc(sizeof(trace_t));
target->trace_info->num_trace_points = 0;
return target_create(&goi);
break;
case TG_CMD_NUMBER:
+ /* It's OK to remove this mechanism sometime after August 2010 or so */
+ LOG_WARNING("don't use numbers as target identifiers; use names");
if (goi.argc != 1) {
Jim_SetResult_sprintf(goi.interp, "expected: target number ?NUMBER?");
return JIM_ERR;
if (e != JIM_OK) {
return JIM_ERR;
}
- {
- target_t *t;
- t = get_target_by_num(w);
- if (t == NULL) {
- Jim_SetResult_sprintf(goi.interp,"Target: number %d does not exist", (int)(w));
- return JIM_ERR;
- }
- Jim_SetResultString(goi.interp, t->cmd_name, -1);
- return JIM_OK;
+ for (x = 0, target = all_targets; target; target = target->next, x++) {
+ if (target->target_number == w)
+ break;
+ }
+ if (target == NULL) {
+ Jim_SetResult_sprintf(goi.interp,
+ "Target: number %d does not exist", (int)(w));
+ return JIM_ERR;
}
+ Jim_SetResultString(goi.interp, target->cmd_name, -1);
+ return JIM_OK;
case TG_CMD_COUNT:
if (goi.argc != 0) {
Jim_WrongNumArgs(goi.interp, 0, goi.argv, "<no parameters>");
return JIM_ERR;
}
- Jim_SetResult(goi.interp,
- Jim_NewIntObj(goi.interp, max_target_number()));
+ for (x = 0, target = all_targets; target; target = target->next, x++)
+ continue;
+ Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, x));
return JIM_OK;
}
fastload[i].length = length;
image_size += length;
- command_print(cmd_ctx, "%u byte written at address 0x%8.8x",
+ command_print(cmd_ctx, "%u bytes written at address 0x%8.8x",
(unsigned int)length,
((unsigned int)(image.sections[i].base_address + offset)));
}