@itemize @bullet
@item @b{post-reset}
@* The TAP has just completed a JTAG reset.
-For the first such handler called, the tap is still
-in the JTAG @sc{reset} state.
+The tap may still be in the JTAG @sc{reset} state.
+Handlers for these events might perform initialization sequences
+such as issuing TCK cycles, TMS sequences to ensure
+exit from the ARM SWD mode, and more.
+
Because the scan chain has not yet been verified, handlers for these events
@emph{should not issue commands which scan the JTAG IR or DR registers}
of any particular target.
@b{NOTE:} As this is written (September 2009), nothing prevents such access.
+@item @b{setup}
+@* The scan chain has been reset and verified.
+This handler may enable TAPs as needed.
@item @b{tap-disable}
@* The TAP needs to be disabled. This handler should
implement @command{jtag tapdisable}
@example
jtag configure CHIP.jrc -event post-reset @{
- echo "Reset done"
+ echo "JTAG Reset done"
... non-scan jtag operations to be done after reset
@}
@end example
In OpenOCD, tap enabling/disabling is invoked by the Tcl commands
shown below, and is implemented using TAP event handlers.
So for example, when defining a TAP for a CPU connected to
-a JTAG router, you should define TAP event handlers using
+a JTAG router, your @file{target.cfg} file
+should define TAP event handlers using
code that looks something like this:
@example
jtag configure CHIP.cpu -event tap-enable @{
- echo "Enabling CPU TAP"
... jtag operations using CHIP.jrc
@}
jtag configure CHIP.cpu -event tap-disable @{
- echo "Disabling CPU TAP"
... jtag operations using CHIP.jrc
@}
@end example
+Then you might want that CPU's TAP enabled almost all the time:
+
+@example
+jtag configure $CHIP.jrc -event setup "jtag tapenable $CHIP.cpu"
+@end example
+
+Note how that particular setup event handler declaration
+uses quotes to evaluate @code{$CHIP} when the event is configured.
+Using brackets @{ @} would cause it to be evaluated later,
+at runtime, when it might have a different value.
+
@deffn Command {jtag tapdisable} dotted.name
If necessary, disables the tap
by sending it a @option{tap-disable} event.
static const char *jtag_event_strings[] =
{
[JTAG_TRST_ASSERTED] = "TAP reset",
+ [JTAG_TAP_EVENT_SETUP] = "TAP setup",
[JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
- [JTAG_TAP_EVENT_POST_RESET] = "TAP post reset",
[JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
};
/* NOTE: order here matches TRST path in jtag_add_reset() */
jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
- jtag_notify_reset();
+ jtag_notify_event(JTAG_TRST_ASSERTED);
}
void jtag_add_pathmove(int num_states, const tap_state_t *path)
* sequence must match jtag_add_tlr().
*/
jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
- jtag_notify_reset();
+ jtag_notify_event(JTAG_TRST_ASSERTED);
}
}
}
{
jtag_tap_t *tap;
int retval;
+ bool issue_setup = true;
LOG_DEBUG("Init JTAG chain");
if (jtag_examine_chain() != ERROR_OK)
{
LOG_ERROR("Trying to use configured scan chain anyway...");
+ issue_setup = false;
}
if (jtag_validate_ircapture() != ERROR_OK)
{
LOG_WARNING("Errors during IR capture, continuing anyway...");
+ issue_setup = false;
}
+ if (issue_setup)
+ jtag_notify_event(JTAG_TAP_EVENT_SETUP);
+ else
+ LOG_WARNING("Bypassing JTAG setup events due to errors");
+
+
return ERROR_OK;
}
/*
- * There are three cases when JTAG_TRST_ASSERTED callback is invoked. The
- * event is invoked *after* TRST is asserted(or queued rather). It is illegal
- * to communicate with the JTAG interface during the callback(as there is
- * currently a queue being built).
+ * - TRST_ASSERTED triggers two sets of callbacks, after operations to
+ * reset the scan chain -- via TMS+TCK signaling, or deasserting the
+ * nTRST signal -- are queued:
*
- * - TMS reset
- * - SRST pulls TRST
- * - TRST asserted
+ * + Callbacks in C code fire first, patching internal state
+ * + Then post-reset event scripts fire ... activating JTAG circuits
+ * via TCK cycles, exiting SWD mode via TMS sequences, etc
*
- * TAP activation/deactivation is currently implemented outside the core
- * using scripted code that understands the specific router type.
+ * During those callbacks, scan chain contents have not been validated.
+ * JTAG operations that address a specific TAP (primarily DR/IR scans)
+ * must *not* be queued.
+ *
+ * - TAP_EVENT_SETUP is reported after TRST_ASSERTED, and after the scan
+ * chain has been validated. JTAG operations including scans that
+ * target specific TAPs may be performed.
+ *
+ * - TAP_EVENT_ENABLE and TAP_EVENT_DISABLE implement TAP activation and
+ * deactivation outside the core using scripted code that understands
+ * the specific JTAG router type. They might be triggered indirectly
+ * from EVENT_SETUP operations.
*/
enum jtag_event {
JTAG_TRST_ASSERTED,
+ JTAG_TAP_EVENT_SETUP,
JTAG_TAP_EVENT_ENABLE,
JTAG_TAP_EVENT_DISABLE,
- JTAG_TAP_EVENT_POST_RESET,
};
struct jtag_tap_event_action_s
/// @returns the number of times the scan queue has been flushed
int jtag_get_flush_queue_count(void);
-/// Notify all TAP's about a TLR reset
-void jtag_notify_reset(void);
+/// Report Tcl event to all TAPs
+void jtag_notify_event(enum jtag_event);
/* can be implemented by hw + sw */
#endif
static const Jim_Nvp nvp_jtag_tap_event[] = {
- { .value = JTAG_TAP_EVENT_POST_RESET, .name = "post-reset" },
+ { .value = JTAG_TRST_ASSERTED, .name = "post-reset" },
+ { .value = JTAG_TAP_EVENT_SETUP, .name = "setup" },
{ .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" },
{ .value = JTAG_TAP_EVENT_DISABLE, .name = "tap-disable" },
for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) {
if (jteap->event == e) {
- LOG_DEBUG("JTAG tap: %s event: %d (%s) action: %s\n",
+ LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
tap->dotted_name,
e,
Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name,
case JTAG_TAP_EVENT_ENABLE:
case JTAG_TAP_EVENT_DISABLE:
/* NOTE: we currently assume the handlers
- * can't fail. That presumes later code
- * will be verifying the scan chains ...
+ * can't fail. Right here is where we should
+ * really be verifying the scan chains ...
*/
tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
+ LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
+ tap->enabled ? "enabled" : "disabled");
break;
default:
break;
}
-void jtag_notify_reset(void)
+void jtag_notify_event(enum jtag_event event)
{
jtag_tap_t *tap;
+
for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
- {
- jtag_tap_handle_event(tap, JTAG_TAP_EVENT_POST_RESET);
- }
+ jtag_tap_handle_event(tap, event);
}
# TI boards default to EMU0/EMU1 *high* -- ARM and ETB are *disabled*
# after JTAG reset until ICEpick is used to route them in.
-#set EMU01 "-disable"
+set EMU01 "-disable"
# With EMU0/EMU1 jumpered *low* ARM and ETB are *enabled* without
# needing any ICEpick interaction.
-set EMU01 "-enable"
+#set EMU01 "-enable"
source [find target/icepick.cfg]
}
jtag newtap $_CHIPNAME jrc -irlen 6 -irmask 0x3f -expected-id $_JRC_TAPID
+jtag configure $_CHIPNAME.jrc -event setup \
+ "jtag tapenable $_CHIPNAME.etb; jtag tapenable $_CHIPNAME.arm"
+
################
# various symbol definitions, to avoid hard-wiring addresses
set _CHIPNAME dm365
}
-#
-# For now, expect EMU0/EMU1 jumpered LOW (not TI's default) so ARM and ETB
-# are enabled without making ICEpick route ARM and ETB into the JTAG chain.
-#
-# Also note: when running without RTCK before the PLLs are set up, you
-# may need to slow the JTAG clock down quite a lot (under 2 MHz).
-#
+# TI boards default to EMU0/EMU1 *high* -- ARM and ETB are *disabled*
+# after JTAG reset until ICEpick is used to route them in.
+set EMU01 "-disable"
+
+# With EMU0/EMU1 jumpered *low* ARM and ETB are *enabled* without
+# needing any ICEpick interaction.
+#set EMU01 "-enable"
+
source [find target/icepick.cfg]
-set EMU01 "-enable"
-#set EMU01 "-disable"
# Subsidiary TAP: ARM ETB11, with scan chain for 4K of ETM trace buffer
if { [info exists ETB_TAPID ] } {
}
jtag newtap $_CHIPNAME jrc -irlen 6 -irmask 0x3f -expected-id $_JRC_TAPID
+jtag configure $_CHIPNAME.jrc -event setup \
+ "jtag tapenable $_CHIPNAME.etb; jtag tapenable $_CHIPNAME.arm"
+
################
# various symbol definitions, to avoid hard-wiring addresses
set _CHIPNAME dm6446
}
-#
-# For now, expect EMU0/EMU1 jumpered LOW (not TI's default) so ARM and ETB
-# are enabled without making ICEpick route ARM and ETB into the JTAG chain.
-# Override by setting EMU01 to "-disable".
-#
-# Also note: when running without RTCK before the PLLs are set up, you
-# may need to slow the JTAG clock down quite a lot (under 2 MHz).
-#
+# TI boards default to EMU0/EMU1 *high* -- ARM and ETB are *disabled*
+# after JTAG reset until ICEpick is used to route them in.
+set EMU01 "-disable"
+
+# With EMU0/EMU1 jumpered *low* ARM and ETB are *enabled* without
+# needing any ICEpick interaction.
+#set EMU01 "-enable"
+
source [find target/icepick.cfg]
-set EMU01 "-enable"
-#set EMU01 "-disable"
# Subsidiary TAP: unknown ... must enable via ICEpick
jtag newtap $_CHIPNAME unknown -irlen 8 -disable
}
jtag newtap $_CHIPNAME jrc -irlen 6 -irmask 0x3f -expected-id $_JRC_TAPID
+jtag configure $_CHIPNAME.jrc -event setup \
+ "jtag tapenable $_CHIPNAME.etb; jtag tapenable $_CHIPNAME.arm"
+
+################
# GDB target: the ARM, using SRAM1 for scratch. SRAM0 (also 8K)
# and the ETB memory (4K) are other options, while trace is unused.
# Little-endian; use the OpenOCD default.