* Copyright (C) 2008 by Spencer Oliver *
* spen@spen-soft.co.uk *
* *
+ * Copyright (C) 2008 by Rick Altherr *
+ * kc8apf@kc8apf.net> *
+ * *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
#include <fileio.h>
#include <image.h>
-static int USE_OLD_RESET = 0; // temp
-
int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv);
int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_NEWreset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
}
const Jim_Nvp nvp_target_event[] = {
- { .value = TARGET_EVENT_OLD_pre_reset , .name = "old-pre_reset" },
{ .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
- { .value = TARGET_EVENT_OLD_post_reset , .name = "old-post_reset" },
{ .value = TARGET_EVENT_OLD_pre_resume , .name = "old-pre_resume" },
{ .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
{ .value = TARGET_EVENT_RESUME_END, .name = "resume-end" },
+
+ { .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
+ { .name = "gdb-end", .value = TARGET_EVENT_GDB_END },
+
+
/* historical name */
{ .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
}
-static int NEW_target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
+int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
{
char buf[100];
int retval;
sprintf( buf, "ocd_process_reset %s", n->name );
retval = Jim_Eval( interp, buf );
- if(retval != JIM_ERR){
+ if(retval != JIM_OK) {
+ Jim_PrintErrorMessage(interp);
return ERROR_FAIL;
}
return retval;
}
-// Next patch - this turns into TCL...
-static int OLD_target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
-{
- int retval = ERROR_OK;
- target_t *target;
-
- target = all_targets;
-
- target_all_handle_event( TARGET_EVENT_OLD_pre_reset );
-
- if ((retval = jtag_init_reset(cmd_ctx)) != ERROR_OK)
- return retval;
-
- keep_alive(); /* we might be running on a very slow JTAG clk */
-
- /* First time this is executed after launching OpenOCD, it will read out
- * the type of CPU, etc. and init Embedded ICE registers in host
- * memory.
- *
- * It will also set up ICE registers in the target.
- *
- * However, if we assert TRST later, we need to set up the registers again.
- *
- * For the "reset halt/init" case we must only set up the registers here.
- */
- if ((retval = target_examine()) != ERROR_OK)
- return retval;
-
- keep_alive(); /* we might be running on a very slow JTAG clk */
-
- target = all_targets;
- while (target)
- {
- /* we have no idea what state the target is in, so we
- * have to drop working areas
- */
- target_free_all_working_areas_restore(target, 0);
- target->reset_halt=((reset_mode==RESET_HALT)||(reset_mode==RESET_INIT));
- if ((retval = target->type->assert_reset(target))!=ERROR_OK)
- return retval;
- target = target->next;
- }
-
- target = all_targets;
- while (target)
- {
- if ((retval = target->type->deassert_reset(target))!=ERROR_OK)
- return retval;
- target = target->next;
- }
-
- target = all_targets;
- while (target)
- {
- /* We can fail to bring the target into the halted state, try after reset has been deasserted */
- if (target->reset_halt)
- {
- /* wait up to 1 second for halt. */
- if ((retval = target_wait_state(target, TARGET_HALTED, 1000)) != ERROR_OK)
- return retval;
- if (target->state != TARGET_HALTED)
- {
- LOG_WARNING("Failed to reset target into halted mode - issuing halt");
- if ((retval = target->type->halt(target))!=ERROR_OK)
- return retval;
- }
- }
-
- target = target->next;
- }
-
-
- LOG_DEBUG("Waiting for halted stated as appropriate");
-
- if ((reset_mode == RESET_HALT) || (reset_mode == RESET_INIT))
- {
- target = all_targets;
- while (target)
- {
- /* Wait for reset to complete, maximum 5 seconds. */
- if (((retval=target_wait_state(target, TARGET_HALTED, 5000)))==ERROR_OK)
- {
- if (reset_mode == RESET_INIT){
- target_handle_event( target, TARGET_EVENT_OLD_post_reset );
- }
-
- }
- target = target->next;
- }
- }
-
- /* We want any events to be processed before the prompt */
- if ((retval = target_call_timer_callbacks_now()) != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
-{
- if( USE_OLD_RESET ){
- return OLD_target_process_reset( cmd_ctx, reset_mode );
- } else {
- return NEW_target_process_reset( cmd_ctx, reset_mode );
- }
-}
-
static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
{
target->type->examine = default_examine;
}
- if (target->type->init_target(cmd_ctx, target) != ERROR_OK)
+ if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK)
{
LOG_ERROR("target '%s' init failed", target->type->name);
- exit(-1);
+ return retval;
}
/* Set up default functions if none are provided by target */
int target_register_commands(struct command_context_s *cmd_ctx)
{
- register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL);
- register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]");
- register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>");
- register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "PRELIMINARY! - profile <seconds> <gmon.out>");
+ register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, "change the current command line target (one parameter) or lists targets (with no parameter)");
+ register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "set a new working space");
+ register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "translate a virtual address into a physical address");
+ register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "profiling samples the CPU PC");
register_jim(cmd_ctx, "target", jim_target, "configure target" );
LOG_DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);
- if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK)
+ if ((retval = target->type->write_memory(target, address, 1, 1, &value)) != ERROR_OK)
{
LOG_DEBUG("failed: %i", retval);
}
int target_register_user_commands(struct command_context_s *cmd_ctx)
{
int retval = ERROR_OK;
- register_command(cmd_ctx, NULL, "reg", handle_reg_command, COMMAND_EXEC, NULL);
+ register_command(cmd_ctx, NULL, "reg", handle_reg_command, COMMAND_EXEC, "display or set a register");
register_command(cmd_ctx, NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state");
register_command(cmd_ctx, NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");
register_command(cmd_ctx, NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");
register_command(cmd_ctx, NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");
register_command(cmd_ctx, NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");
- register_command(cmd_ctx, NULL, "NEWreset", handle_NEWreset_command, COMMAND_EXEC, "reset target [run|halt|init] - default is run");
- register_command(cmd_ctx, NULL, "reset", handle_reset_command, COMMAND_EXEC, "OLDreset target [run|halt|init] - default is run");
+ register_command(cmd_ctx, NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init] - default is run");
register_command(cmd_ctx, NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
register_command(cmd_ctx, NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
}
+// every 300ms we check for reset & powerdropout and issue a "reset halt" if
+// so.
+
+static int powerDropout;
+static int srstAsserted;
+
+static int sense_handler()
+{
+ static int prevSrstAsserted = 0;
+ static int prevPowerdropout = 0;
+
+ int retval;
+ if ((retval=jtag_power_dropout(&powerDropout))!=ERROR_OK)
+ return retval;
+
+ int powerRestored;
+ powerRestored = prevPowerdropout && !powerDropout;
+ if (powerRestored)
+ {
+ LOG_USER("Sensed power restore.");
+ }
+
+ long long current = timeval_ms();
+ static long long lastPower = 0;
+ int waitMore = lastPower + 2000 > current;
+ if (powerDropout && !waitMore)
+ {
+ LOG_USER("Sensed power dropout.");
+ lastPower = current;
+ }
+
+ if ((retval=jtag_srst_asserted(&srstAsserted))!=ERROR_OK)
+ return retval;
+
+ int srstDeasserted;
+ srstDeasserted = prevSrstAsserted && !srstAsserted;
+
+ static long long lastSrst = 0;
+ waitMore = lastSrst + 2000 > current;
+ if (srstDeasserted && !waitMore)
+ {
+ LOG_USER("Sensed nSRST deasserted");
+ lastSrst = current;
+ }
+
+ if (!prevSrstAsserted && srstAsserted)
+ {
+ LOG_USER("Sensed nSRST asserted");
+ }
+
+ prevSrstAsserted = srstAsserted;
+ prevPowerdropout = powerDropout;
+
+ if (srstDeasserted || powerRestored)
+ {
+ /* Other than logging the event we can't do anything here.
+ * Issuing a reset is a particularly bad idea as we might
+ * be inside a reset already.
+ */
+ }
+
+ return ERROR_OK;
+}
+
+
/* process target state changes */
int handle_target(void *priv)
{
while (target)
{
- if (target_continous_poll)
+ sense_handler();
+
+ /* only poll target if we've got power and srst isn't asserted */
+ if (target_continous_poll&&!powerDropout&&!srstAsserted)
{
/* polling may fail silently until the target has been examined */
if((retval = target_poll(target)) != ERROR_OK)
return target_process_reset(cmd_ctx, reset_mode);
}
-int handle_NEWreset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
- int x;
- char *cp;
-
- if (argc >= 1){
- x = strtol( args[0], &cp, 0 );
- if( *cp != 0 ){
- command_print( cmd_ctx, "Not numeric: %s\n", args[0] );
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- USE_OLD_RESET = !!x;
- }
- command_print( cmd_ctx, "reset method: %d (%s)\n",
- USE_OLD_RESET,
- USE_OLD_RESET ? "old-method" : "new-method" );
- return ERROR_OK;
-}
int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
LOG_DEBUG("-");
if (argc == 0)
- target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
+ return target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
if (argc == 1)
- target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */
+ return target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */
return ERROR_OK;
}
{
long l;
u32 width;
- u32 len;
+ int len;
u32 addr;
u32 count;
u32 v;
{
long l;
u32 width;
- u32 len;
+ int len;
u32 addr;
u32 count;
u32 v;
e,
Jim_Nvp_value2name_simple( nvp_target_event, e )->name,
Jim_GetString( teap->body, NULL ) );
- Jim_EvalObj( interp, teap->body );
+ if (Jim_EvalObj( interp, teap->body )!=JIM_OK)
+ {
+ Jim_PrintErrorMessage(interp);
+ }
}
teap = teap->next;
}
}
if( goi->isconfigure ){
- if( goi->argc == 0 ){
+ if( goi->argc != 1 ){
Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
return JIM_ERR;
}
target->next = NULL;
target->arch_info = NULL;
+ target->display = 1;
+
/* initialize trace information */
target->trace_info = malloc(sizeof(trace_t));
target->trace_info->num_trace_points = 0;
target, /* private data */
NULL ); /* no del proc */
- (*(target->type->target_create))( target, goi->interp );
return e;
}
/* target_old_syntax
*
- * argv[0] typename (above)
- * argv[1] endian
- * argv[2] reset method, deprecated/ignored
- * argv[3] = old param
- * argv[4] = old param
+ * It appears that there are 2 old syntaxes:
+ *
+ * target <typename> <endian> <chain position> <variant>
+ *
+ * and
+ *
+ * target <typename> <endian> <reset mode> <chain position> <variant>
*
- * We will combine all "old params" into a single param.
- * Then later, split them again.
*/
+
+ /* The minimum number of arguments is 4 */
if( argc < 4 ){
- Jim_WrongNumArgs( interp, 1, argv, "[OLDSYNTAX] ?TYPE? ?ENDIAN? ?RESET? ?old-params?");
+ Jim_WrongNumArgs( interp, 1, argv, "[OLDSYNTAX] ?TYPE? ?ENDIAN? ?CHAIN-POSITION? ?VARIANT?");
return JIM_ERR;
}
+
/* the command */
new_argv[0] = argv[0];
new_argv[1] = Jim_NewStringObj( interp, "create", -1 );
new_argv[4] = Jim_NewStringObj( interp, "-endian", -1 );
new_argv[5] = goi.argv[1];
new_argv[6] = Jim_NewStringObj( interp, "-chain-position", -1 );
- new_argv[7] = goi.argv[2];
- new_argv[8] = Jim_NewStringObj( interp, "-variant", -1 );
- new_argv[9] = goi.argv[3];
- new_argc = 10;
+
+ /* If goi.argv[2] is not a number, we need to skip it since it is the reset mode. */
+ jim_wide w;
+ int chain_position_argv = 2;
+ if (JIM_ERR == Jim_GetWide(interp, goi.argv[chain_position_argv], &w)) {
+ if (chain_position_argv + 1 < goi.argc) {
+ chain_position_argv += 1;
+ } else {
+ Jim_WrongNumArgs( interp, 1, argv, "[OLDSYNTAX] ?TYPE? ?ENDIAN? ?RESET? ?CHAIN-POSITION? ?VARIANT?");
+ return JIM_ERR;
+ }
+ }
+
+ new_argv[7] = goi.argv[chain_position_argv];
+
+ /* Only provide a variant configure option if there was a variant specified */
+ if (chain_position_argv + 1 < goi.argc) {
+ new_argv[8] = Jim_NewStringObj( interp, "-variant", -1 );
+ new_argv[9] = goi.argv[chain_position_argv + 1];
+ new_argc = 10;
+ } else {
+ new_argc = 8;
+ }
+
/*
* new arg syntax:
* argv[0] = command
* argv[1] = create
* argv[2] = cmdname
* argv[3] = typename
- * argv[4] = **FIRST** "configure" option.
- *
- * Here, we make them:
- *
* argv[4] = -endian
* argv[5] = little
* argv[6] = -position