diff --git a/doc/openocd.texi b/doc/openocd.texi index e94c9d02b..b32ed213f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -1411,6 +1411,20 @@ chip can be tweaked by the board. Some chips have specific ways the TRST and SRST signals are managed. In the unusual case that these are @emph{chip specific} and can never be changed by board wiring, they could go here. +For example, some chips can't support JTAG debugging without +both signals. + +Provide a @code{reset-assert} event handler if you can. +Such a handler uses JTAG operations to reset the target, +letting this target config be used in systems which don't +provide the optional SRST signal, or on systems where you +don't want to reset all targets at once. +Such a handler might write to chip registers to force a reset, +use a JRC to do that (preferable -- the target may be wedged!), +or force a watchdog timer to trigger. +(For Cortex-M3 targets, this is not necessary. The target +driver knows how to use trigger an NVIC reset when SRST is +not available.) Some chips need special attention during reset handling if they're going to be used with JTAG. @@ -1418,6 +1432,8 @@ An example might be needing to send some commands right after the target's TAP has been reset, providing a @code{reset-deassert-post} event handler that writes a chip register to report that JTAG debugging is being done. +Another would be reconfiguring the watchdog so that it stops +counting while the core is halted in the debugger. JTAG clocking constraints often change during reset, and in some cases target config files (rather than board config files) @@ -2401,6 +2417,12 @@ There are also @emph{event handlers} associated with TAPs or Targets. Those handlers are Tcl procedures you can provide, which are invoked at particular points in the reset sequence. +@emph{When SRST is not an option} you must set +up a @code{reset-assert} event handler for your target. +For example, some JTAG adapters don't include the SRST signal; +and some boards have multiple targets, and you won't always +want to reset everything at once. + After configuring those mechanisms, you might still find your board doesn't start up or reset correctly. For example, maybe it needs a slightly different sequence @@ -3390,9 +3412,14 @@ For example: @itemize @bullet @item What should happen when GDB connects? Should your target reset? @item When GDB tries to flash the target, do you need to enable the flash via a special command? +@item Is using SRST appropriate (and possible) on your system? +Or instead of that, do you need to issue JTAG commands to trigger reset? +SRST usually resets everything on the scan chain, which can be inappropriate. @item During reset, do you need to write to certain memory locations to set up system clocks or to reconfigure the SDRAM? +How about configuring the watchdog timer, or other peripherals, +to stop running while you hold the core stopped for debugging? @end itemize All of the above items can be addressed by target event handlers. @@ -3457,16 +3484,28 @@ The following target events are defined: @item @b{reset-assert-pre} @* Issued as part of @command{reset} processing after @command{reset_init} was triggered -but before SRST alone is re-asserted on the tap. +but before either SRST alone is re-asserted on the scan chain, +or @code{reset-assert} is triggered. +@item @b{reset-assert} +@* Issued as part of @command{reset} processing +after @command{reset-assert-pre} was triggered. +When such a handler is present, cores which support this event will use +it instead of asserting SRST. +This support is essential for debugging with JTAG interfaces which +don't include an SRST line (JTAG doesn't require SRST), and for +selective reset on scan chains that have multiple targets. @item @b{reset-assert-post} @* Issued as part of @command{reset} processing -when SRST is asserted on the tap. +after @code{reset-assert} has been triggered. +or the target asserted SRST on the entire scan chain. @item @b{reset-deassert-pre} @* Issued as part of @command{reset} processing -when SRST is about to be released on the tap. +after @code{reset-assert-post} has been triggered. @item @b{reset-deassert-post} @* Issued as part of @command{reset} processing -when SRST has been released on the tap. +after @code{reset-deassert-pre} has been triggered +and (if the target is using it) after SRST has been +released on the scan chain. @item @b{reset-end} @* Issued as the final step in @command{reset} processing. @ignore diff --git a/src/target/target.c b/src/target/target.c index 3de9f2c6a..a2bd88689 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -147,6 +147,7 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_RESET_START, .name = "reset-start" }, { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" }, + { .value = TARGET_EVENT_RESET_ASSERT, .name = "reset-assert" }, { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" }, { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" }, { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" }, @@ -154,8 +155,8 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" }, { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" }, { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" }, - { .value = TARGET_EVENT_RESET_INIT , .name = "reset-init" }, - { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, + { .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" }, + { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" }, { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" }, @@ -3523,6 +3524,20 @@ void target_handle_event(struct target *target, enum target_event e) } } +/** + * Returns true only if the target has a handler for the specified event. + */ +bool target_has_event_action(struct target *target, enum target_event event) +{ + struct target_event_action *teap; + + for (teap = target->event_action; teap != NULL; teap = teap->next) { + if (teap->event == event) + return true; + } + return false; +} + enum target_cfg_param { TCFG_TYPE, TCFG_EVENT, diff --git a/src/target/target.h b/src/target/target.h index 15003c654..55e9088ac 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -196,6 +196,7 @@ enum target_event TARGET_EVENT_RESET_START, TARGET_EVENT_RESET_ASSERT_PRE, + TARGET_EVENT_RESET_ASSERT, /* C code uses this instead of SRST */ TARGET_EVENT_RESET_ASSERT_POST, TARGET_EVENT_RESET_DEASSERT_PRE, TARGET_EVENT_RESET_DEASSERT_POST, @@ -226,7 +227,9 @@ struct target_event_action { struct Jim_Obj *body; int has_percent; struct target_event_action *next; - }; +}; + +bool target_has_event_action(struct target *target, enum target_event event); struct target_event_callback {