#include <helper/time_support.h>
#include <jtag/jtag.h>
+#include <flash/nor/core.h>
#include "target.h"
#include "target_type.h"
return ERROR_OK;
}
+/**
+ * Make the target (re)start executing using its saved execution
+ * context (possibly with some modifications).
+ *
+ * @param target Which target should start executing.
+ * @param current True to use the target's saved program counter instead
+ * of the address parameter
+ * @param address Optionally used as the program counter.
+ * @param handle_breakpoints True iff breakpoints at the resumption PC
+ * should be skipped. (For example, maybe execution was stopped by
+ * such a breakpoint, in which case it would be counterprodutive to
+ * let it re-trigger.
+ * @param debug_execution False if all working areas allocated by OpenOCD
+ * should be released and/or restored to their original contents.
+ * (This would for example be true to run some downloaded "helper"
+ * algorithm code, which resides in one such working buffer and uses
+ * another for data storage.)
+ *
+ * @todo Resolve the ambiguity about what the "debug_execution" flag
+ * signifies. For example, Target implementations don't agree on how
+ * it relates to invalidation of the register cache, or to whether
+ * breakpoints and watchpoints should be enabled. (It would seem wrong
+ * to enable breakpoints when running downloaded "helper" algorithms
+ * (debug_execution true), since the breakpoints would be set to match
+ * target firmware being debugged, not the helper algorithm.... and
+ * enabling them could cause such helpers to malfunction (for example,
+ * by overwriting data with a breakpoint instruction. On the other
+ * hand the infrastructure for running such helpers might use this
+ * procedure but rely on hardware breakpoint to detect termination.)
+ */
int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
{
int retval;
return ERROR_FAIL;
}
- /* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can
- * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?)
- * the application.
+ /* note that resume *must* be asynchronous. The CPU can halt before
+ * we poll. The CPU can even halt at the current PC as a result of
+ * a software breakpoint being inserted by (a bug?) the application.
*/
if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
return retval;
+ /* Invalidate any cached protect/erase/... flash status, since
+ * almost all targets will now be able modify the flash by
+ * themselves. We want flash drivers and infrastructure to
+ * be able to rely on (non-invalidated) cached state.
+ *
+ * REVISIT do the same for NAND ; maybe other flash flavors too...
+ */
+ nor_resume(target);
return retval;
}
/* We want any events to be processed before the prompt */
retval = target_call_timer_callbacks_now();
+ struct target *target;
+ for (target = all_targets; target; target = target->next) {
+ target->type->check_reset(target);
+ }
+
return retval;
}
return ERROR_OK;
}
+/* no check by default */
+static int default_check_reset(struct target *target)
+{
+ return ERROR_OK;
+}
+
int target_examine_one(struct target *target)
{
return target->type->examine(target);
if (type->examine == NULL)
type->examine = default_examine;
+ if (type->check_reset== NULL)
+ type->check_reset = default_check_reset;
+
int retval = type->init_target(cmd_ctx, target);
if (ERROR_OK != retval)
{
return ERROR_OK;
}
-static void target_call_event_callbacks_all(enum target_event e) {
- struct target *target;
- target = all_targets;
- while (target) {
- target_call_event_callbacks(target, e);
- target = target->next;
- }
-}
-
/* process target state changes */
static int handle_target(void *priv)
{
int did_something = 0;
if (runSrstAsserted)
{
- target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT);
+ LOG_INFO("srst asserted detected, running srst_asserted proc.");
Jim_Eval(interp, "srst_asserted");
did_something = 1;
}
}
if (runPowerDropout)
{
- target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT);
+ LOG_INFO("Power dropout detected, running power_dropout proc.");
Jim_Eval(interp, "power_dropout");
did_something = 1;
}
/* polling may fail silently until the target has been examined */
if ((retval = target_poll(target)) != ERROR_OK)
{
+ /* FIX!!!!! If we add a LOG_INFO() here to output a line in GDB
+ * *why* we are aborting GDB, then we'll spam telnet when the
+ * poll is failing persistently.
+ *
+ * If we could implement an event that detected the
+ * target going from non-pollable to pollable, we could issue
+ * an error only upon the transition.
+ */
target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
return retval;
}
const char *value_fmt;
switch (size) {
case 4: value_fmt = "%8.8x "; break;
- case 2: value_fmt = "%4.2x "; break;
+ case 2: value_fmt = "%4.4x "; break;
case 1: value_fmt = "%2.2x "; break;
default:
/* "can't happen", caller checked */
return JIM_OK;
}
+static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ if (argc != 1)
+ {
+ Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
+ return JIM_ERR;
+ }
+ struct target *target = Jim_CmdPrivData(interp);
+
+ if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK)
+ return JIM_ERR;
+
+ return JIM_OK;
+}
+
static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc != 1)
.jim_handler = jim_target_examine,
.help = "used internally for reset processing",
},
+ {
+ .name = "arp_halt_gdb",
+ .mode = COMMAND_EXEC,
+ .jim_handler = jim_target_halt_gdb,
+ .help = "used internally for reset processing to halt GDB",
+ },
{
.name = "arp_poll",
.mode = COMMAND_EXEC,
return register_commands(cmd_ctx, NULL, target_command_handlers);
}
+static bool target_reset_nag = true;
+
+bool get_target_reset_nag(void)
+{
+ return target_reset_nag;
+}
+
+COMMAND_HANDLER(handle_target_reset_nag)
+{
+ return CALL_COMMAND_HANDLER(handle_command_parse_bool,
+ &target_reset_nag, "Nag after each reset about options to improve "
+ "performance");
+}
+
static const struct command_registration target_exec_command_handlers[] = {
{
.name = "fast_load_image",
.handler = handle_virt2phys_command,
.mode = COMMAND_ANY,
.help = "translate a virtual address into a physical address",
- .usage = "virual_address",
+ .usage = "virtual_address",
},
{
.name = "reg",
"and write the 8/16/32 bit values",
.usage = "arrayname bitwidth address count",
},
+ {
+ .name = "reset_nag",
+ .handler = handle_target_reset_nag,
+ .mode = COMMAND_ANY,
+ .help = "Nag after each reset about options that could have been "
+ "enabled to improve performance. ",
+ .usage = "['enable'|'disable']",
+ },
COMMAND_REGISTRATION_DONE
};
int target_register_user_commands(struct command_context *cmd_ctx)