* 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 *
int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
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);
{ .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" },
{ .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
- { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-end" },
+ { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
{ .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" },
{
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");
if (argc == 1)
{
/* try as tcltarget name */
- for( target = all_targets ; target ; target++ ){
+ for( target = all_targets ; target ; target = target->next ){
if( target->cmd_name ){
if( 0 == strcmp( args[0], target->cmd_name ) ){
/* MATCH */
cmd_ctx->current_target = target->target_number;
return ERROR_OK;
}
- DumpTargets:
+DumpTargets:
- command_print(cmd_ctx, " CmdName Type Endian ChainPos State ");
- command_print(cmd_ctx, "-- ---------- ---------- ---------- -------- ----------");
+ target = all_targets;
+ command_print(cmd_ctx, " CmdName Type Endian AbsChainPos Name State ");
+ command_print(cmd_ctx, "-- ---------- ---------- ---------- ----------- ------------- ----------");
while (target)
{
/* XX: abcdefghij abcdefghij abcdefghij abcdefghij */
- command_print(cmd_ctx, "%2d: %-10s %-10s %-10s %8d %s",
+ command_print(cmd_ctx, "%2d: %-10s %-10s %-10s %10d %14s %s",
target->target_number,
target->cmd_name,
target->type->name,
Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness )->name,
- target->chain_position,
+ target->tap->abs_chain_position,
+ target->tap->dotted_name,
Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
target = target->next;
}
return ERROR_OK;
}
+// every 300ms we check for reset & powerdropout and issue a "reset halt" if
+// so.
+static int powerDropout;
+static int srstAsserted;
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int runPowerRestore;
+static int runPowerDropout;
+static int runSrstAsserted;
+static int runSrstDeasserted;
+
+static int sense_handler(void)
{
- int retval = ERROR_OK;
- target_t *target = NULL;
+ static int prevSrstAsserted = 0;
+ static int prevPowerdropout = 0;
- if ((argc < 4) || (argc > 5))
- {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
+ int retval;
+ if ((retval=jtag_power_dropout(&powerDropout))!=ERROR_OK)
+ return retval;
- target = get_target_by_num(strtoul(args[0], NULL, 0));
- if (!target)
+ int powerRestored;
+ powerRestored = prevPowerdropout && !powerDropout;
+ if (powerRestored)
{
- return ERROR_COMMAND_SYNTAX_ERROR;
+ runPowerRestore = 1;
}
- target_free_all_working_areas(target);
- target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);
- if (argc == 5)
+ long long current = timeval_ms();
+ static long long lastPower = 0;
+ int waitMore = lastPower + 2000 > current;
+ if (powerDropout && !waitMore)
{
- target->working_area_virt = strtoul(args[4], NULL, 0);
+ runPowerDropout = 1;
+ lastPower = current;
}
- target->working_area_size = strtoul(args[2], NULL, 0);
- if (strcmp(args[3], "backup") == 0)
+ 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)
{
- target->backup_working_area = 1;
+ runSrstDeasserted = 1;
+ lastSrst = current;
}
- else if (strcmp(args[3], "nobackup") == 0)
+
+ if (!prevSrstAsserted && srstAsserted)
{
- target->backup_working_area = 0;
+ runSrstAsserted = 1;
}
- else
+
+ prevSrstAsserted = srstAsserted;
+ prevPowerdropout = powerDropout;
+
+ if (srstDeasserted || powerRestored)
{
- LOG_ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);
- return ERROR_COMMAND_SYNTAX_ERROR;
+ /* 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 retval;
+ return ERROR_OK;
}
int handle_target(void *priv)
{
int retval = ERROR_OK;
+
+ /* we do not want to recurse here... */
+ static int recursive = 0;
+ if (! recursive)
+ {
+ recursive = 1;
+ sense_handler();
+ /* danger! running these procedures can trigger srst assertions and power dropouts.
+ * We need to avoid an infinite loop/recursion here and we do that by
+ * clearing the flags after running these events.
+ */
+ int did_something = 0;
+ if (runSrstAsserted)
+ {
+ Jim_Eval( interp, "srst_asserted");
+ did_something = 1;
+ }
+ if (runSrstDeasserted)
+ {
+ Jim_Eval( interp, "srst_deasserted");
+ did_something = 1;
+ }
+ if (runPowerDropout)
+ {
+ Jim_Eval( interp, "power_dropout");
+ did_something = 1;
+ }
+ if (runPowerRestore)
+ {
+ Jim_Eval( interp, "power_restore");
+ did_something = 1;
+ }
+
+ if (did_something)
+ {
+ /* clear detect flags */
+ sense_handler();
+ }
+
+ /* clear action flags */
+
+ runSrstAsserted=0;
+ runSrstDeasserted=0;
+ runPowerRestore=0;
+ runPowerDropout=0;
+
+ recursive = 0;
+ }
+
target_t *target = all_targets;
while (target)
{
- if (target_continous_poll)
+
+ /* 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)
target = target->next;
}
+
return retval;
}
break;
case TCFG_CHAIN_POSITION:
if( goi->isconfigure ){
+ Jim_Obj *o;
+ jtag_tap_t *tap;
target_free_all_working_areas(target);
- e = Jim_GetOpt_Wide( goi, &w );
+ e = Jim_GetOpt_Obj( goi, &o );
if( e != JIM_OK ){
return e;
}
+ tap = jtag_TapByJimObj( goi->interp, o );
+ if( tap == NULL ){
+ return JIM_ERR;
+ }
/* make this exactly 1 or 0 */
- target->chain_position = w;
+ target->tap = tap;
} else {
if( goi->argc != 0 ){
goto no_params;
}
}
- Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->chain_position ) );
+ Jim_SetResultString( interp, target->tap->dotted_name, -1 );
/* loop for more e*/
break;
}
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;
int x,r,e;
jim_wide w;
struct command_context_s *cmd_ctx;
- const char *cp;
target_t *target;
Jim_GetOptInfo goi;
enum tcmd {
return JIM_ERR;
}
- /* is this old syntax? */
- /* To determine: We have to peek at argv[0]*/
- cp = Jim_GetString( goi.argv[0], NULL );
- for( x = 0 ; target_types[x] ; x++ ){
- if( 0 == strcmp(cp,target_types[x]->name) ){
- break;
- }
- }
- if( target_types[x] ){
- /* YES IT IS OLD SYNTAX */
- int chain_position_offset;
- Jim_Obj *new_argv[10];
- int new_argc;
-
- /* target_old_syntax
- *
- * It appears that there are 2 old syntaxes:
- *
- * target <typename> <endian> <chain position> <variant>
- *
- * and
- *
- * target <typename> <endian> <reset mode> <chain position> <variant>
- *
- * The following uses the number of arguments to switch between them.
- */
- if( argc < 5 ){
- Jim_WrongNumArgs( interp, 1, argv, "[OLDSYNTAX] ?TYPE? ?ENDIAN? ?CHAIN-POSITION? ?VARIANT?");
- return JIM_ERR;
- }
-
- /* Use the correct argument offset for the chain position */
- if (argc < 6) {
- /* target <type> <endian> <chain position> <variant> */
- chain_position_offset = 2;
- } else {
- chain_position_offset = 3;
- /* target <type> <endian> <reset mode> <chain position> <variant> */
- }
-
- /* the command */
- new_argv[0] = argv[0];
- new_argv[1] = Jim_NewStringObj( interp, "create", -1 );
- {
- char buf[ 30 ];
- sprintf( buf, "target%d", new_target_number() );
- new_argv[2] = Jim_NewStringObj( interp, buf , -1 );
- }
- new_argv[3] = goi.argv[0]; /* typename */
- 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[chain_position_offset];
- new_argv[8] = Jim_NewStringObj( interp, "-variant", -1 );
- new_argv[9] = goi.argv[chain_position_offset + 1];
- new_argc = 10;
-
- /*
- * 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
- * argv[7] = NUMBER
- * argv[8] = -variant
- * argv[9] = "somestring"
- */
-
- /* don't let these be released */
- for( x = 0 ; x < new_argc ; x++ ){
- Jim_IncrRefCount( new_argv[x]);
- }
- /* call our self */
- LOG_DEBUG("Target OLD SYNTAX - converted to new syntax");
-
- r = jim_target( goi.interp, new_argc, new_argv );
-
- /* release? these items */
- for( x = 0 ; x < new_argc ; x++ ){
- Jim_DecrRefCount( interp, new_argv[x] );
- }
- return r;
- }
-
//Jim_GetOpt_Debug( &goi );
r = Jim_GetOpt_Enum( &goi, target_cmds, &x );
if( r != JIM_OK ){