From 53a936afc0092f4a65975d35bab0e10944fad3db Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 11 Nov 2016 14:39:09 +0100 Subject: [PATCH] Add -defer-examine option to target create command The '-defer-examine' option to target create allows declaring targets that are present on the chain, but not fully functional. They will be skipped by the initial arp_examine as well as arp_examine after reset. Manual examine using 'arp_examine' is needed to examine them, with the idea that some kind of actions is neeed to bring them to a state where examine will succeed (if at all possible). In order to allow value less options to target command, I had to relax the goi.argc check in jim_target_configure(). Change-Id: I9bf4e8d27eb6476dd9353d15f48965a8cfd5c122 Signed-off-by: Esben Haabendal Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3076 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 6 ++- src/rtos/rtos.c | 5 ++- src/target/startup.tcl | 14 ++++++- src/target/target.c | 84 ++++++++++++++++++++++++++++++++++++++---- src/target/target.h | 3 ++ 5 files changed, 102 insertions(+), 10 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 0fef9fbb4b..4ce61871b9 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4126,6 +4126,10 @@ The value should normally correspond to a static mapping for the @option{FreeRTOS}|@option{linux}|@option{ChibiOS}|@option{embKernel}|@option{mqx} @xref{gdbrtossupport,,RTOS Support}. +@item @code{-defer-examine} -- skip target examination at initial JTAG chain +scan and after a reset. A manual call to arp_examine is required to +access the target for debugging. + @end itemize @end deffn @@ -4162,7 +4166,7 @@ omap3530.cpu mww 0x5555 123 The commands supported by OpenOCD target objects are: -@deffn Command {$target_name arp_examine} +@deffn Command {$target_name arp_examine} @option{allow-defer} @deffnx Command {$target_name arp_halt} @deffnx Command {$target_name arp_poll} @deffnx Command {$target_name arp_reset} diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 448c49c060..aa8efbe727 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -104,6 +104,7 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target) int x; const char *cp; struct Jim_Obj *res; + int e; if (!goi->isconfigure && goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); @@ -112,7 +113,9 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target) os_free(target); - Jim_GetOpt_String(goi, &cp, NULL); + e = Jim_GetOpt_String(goi, &cp, NULL); + if (e != JIM_OK) + return e; if (0 == strcmp(cp, "auto")) { /* Auto detect tries to look up all symbols for each RTOS, diff --git a/src/target/startup.tcl b/src/target/startup.tcl index cf2813ba85..9bbc6e32c9 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -65,7 +65,7 @@ proc ocd_process_reset_inner { MODE } { foreach t $targets { if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { $t invoke-event examine-start - set err [catch "$t arp_examine"] + set err [catch "$t arp_examine allow-defer"] if { $err == 0 } { $t invoke-event examine-end } @@ -111,6 +111,12 @@ proc ocd_process_reset_inner { MODE } { continue } + # don't wait for targets where examination is deferred + # they can not be halted anyway at this point + if { ![$t was_examined] && [$t examine_deferred] } { + continue + } + # Wait upto 1 second for target to halt. Why 1sec? Cause # the JTAG tap reset signal might be hooked to a slow # resistor/capacitor circuit - and it might take a while @@ -135,6 +141,12 @@ proc ocd_process_reset_inner { MODE } { continue } + # don't wait for targets where examination is deferred + # they can not be halted anyway at this point + if { ![$t was_examined] && [$t examine_deferred] } { + continue + } + set err [catch "$t arp_waitstate halted 5000"] # Did it halt? if { $err == 0 } { diff --git a/src/target/target.c b/src/target/target.c index c23590e598..4c5ddd3e03 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -283,6 +283,10 @@ const char *target_state_name(struct target *t) LOG_ERROR("Invalid target state: %d", (int)(t->state)); cp = "(*BUG*unknown*BUG*)"; } + + if (!target_was_examined(t) && t->defer_examine) + cp = "examine deferred"; + return cp; } @@ -731,6 +735,9 @@ int target_examine(void) continue; } + if (target->defer_examine) + continue; + retval = target_examine_one(target); if (retval != ERROR_OK) return retval; @@ -4325,6 +4332,7 @@ enum target_cfg_param { TCFG_CHAIN_POSITION, TCFG_DBGBASE, TCFG_RTOS, + TCFG_DEFER_EXAMINE, }; static Jim_Nvp nvp_config_opts[] = { @@ -4339,6 +4347,7 @@ static Jim_Nvp nvp_config_opts[] = { { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, { .name = "-dbgbase", .value = TCFG_DBGBASE }, { .name = "-rtos", .value = TCFG_RTOS }, + { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, { .name = NULL, .value = -1 } }; @@ -4613,6 +4622,13 @@ no_params: } /* loop for more */ break; + + case TCFG_DEFER_EXAMINE: + /* DEFER_EXAMINE */ + target->defer_examine = true; + /* loop for more */ + break; + } } /* while (goi->argc) */ @@ -4627,12 +4643,9 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); - int need_args = 1 + goi.isconfigure; - if (goi.argc < need_args) { + if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - goi.isconfigure - ? "missing: -option VALUE ..." - : "missing: -option ..."); + "missing: -option ..."); return JIM_ERR; } struct target *target = Jim_CmdPrivData(goi.interp); @@ -4883,20 +4896,58 @@ static int jim_target_tap_disabled(Jim_Interp *interp) static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + bool allow_defer = false; + + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc > 1) { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, + "usage: %s ['allow-defer']", cmd_name); return JIM_ERR; } + if (goi.argc > 0 && + strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) { + /* consume it */ + struct Jim_Obj *obj; + int e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + allow_defer = true; + } + struct target *target = Jim_CmdPrivData(interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); + if (allow_defer && target->defer_examine) { + LOG_INFO("Deferring arp_examine of %s", target_name(target)); + LOG_INFO("Use arp_examine command to examine it manually!"); + return JIM_OK; + } + int e = target->type->examine(target); if (e != ERROR_OK) return JIM_ERR; return JIM_OK; } +static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target_was_examined(target)); + return JIM_OK; +} + +static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target->defer_examine); + return JIM_OK; +} + static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { @@ -4964,6 +5015,10 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) target_name(target)); return JIM_ERR; } + + if (target->defer_examine) + target_reset_examined(target); + /* determine if we should halt or not. */ target->reset_halt = !!a; /* When this happens - all workareas are invalid. */ @@ -5174,6 +5229,21 @@ static const struct command_registration target_instance_command_handlers[] = { .mode = COMMAND_EXEC, .jim_handler = jim_target_examine, .help = "used internally for reset processing", + .usage = "arp_examine ['allow-defer']", + }, + { + .name = "was_examined", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_was_examined, + .help = "used internally for reset processing", + .usage = "was_examined", + }, + { + .name = "examine_deferred", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_examine_deferred, + .help = "used internally for reset processing", + .usage = "examine_deferred", }, { .name = "arp_halt_gdb", diff --git a/src/target/target.h b/src/target/target.h index 8f6a7d901a..7f6ac14857 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -130,6 +130,9 @@ struct target { struct jtag_tap *tap; /* where on the jtag chain is this */ int32_t coreid; /* which device on the TAP? */ + /** Should we defer examine to later */ + bool defer_examine; + /** * Indicates whether this target has been examined. * -- 2.30.2