From 7c7467b34f11939fbce41e39dfa1b6b0e110a89c Mon Sep 17 00:00:00 2001
From: dbrownell <dbrownell@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Date: Mon, 5 Oct 2009 08:20:28 +0000
Subject: [PATCH] Add a new JTAG "setup" event; use for better DaVinci ICEpick
 support.

The model is that this fires after scanchain verification, when it's
safe to call "jtag tapenable $TAPNAME".  So it will fire as part of
non-error paths of "init" and "reset" command processing.  However it
will *NOT* trigger during "jtag_reset" processing, which skips all
scan chain verification, or after verification errors.

ALSO:
 - switch DaVinci chips to use this new mechanism
 - log TAP activation/deactivation, since their IDCODEs aren't verified
 - unify "enum jtag_event" scripted event notifications
 - remove duplicative JTAG_TAP_EVENT_POST_RESET


git-svn-id: svn://svn.berlios.de/openocd/trunk@2800 b42882b7-edfa-0310-969c-e2dbd0fdcd60
---
 doc/openocd.texi         | 28 ++++++++++++++++++++++------
 src/jtag/core.c          | 15 ++++++++++++---
 src/jtag/jtag.h          | 33 +++++++++++++++++++++------------
 src/jtag/tcl.c           | 18 ++++++++++--------
 tcl/target/ti_dm355.cfg  |  7 +++++--
 tcl/target/ti_dm365.cfg  | 20 +++++++++++---------
 tcl/target/ti_dm6446.cfg | 22 ++++++++++++----------
 7 files changed, 93 insertions(+), 50 deletions(-)

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 32797fb39..8156de4d1 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -2428,12 +2428,18 @@ The TAP events currently defined are:
 @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}
@@ -2450,7 +2456,7 @@ contents to be accurate), you might:
 
 @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
@@ -2493,20 +2499,30 @@ does include a kind of JTAG router functionality.
 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.
diff --git a/src/jtag/core.c b/src/jtag/core.c
index 6177c1dc8..128504046 100644
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -61,8 +61,8 @@ static int jtag_error = ERROR_OK;
 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",
 };
 
@@ -489,7 +489,7 @@ void jtag_add_tlr(void)
 
 	/* 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)
@@ -704,7 +704,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 			 * sequence must match jtag_add_tlr().
 			 */
 			jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-			jtag_notify_reset();
+			jtag_notify_event(JTAG_TRST_ASSERTED);
 		}
 	}
 }
@@ -1232,6 +1232,7 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx)
 {
 	jtag_tap_t *tap;
 	int retval;
+	bool issue_setup = true;
 
 	LOG_DEBUG("Init JTAG chain");
 
@@ -1249,13 +1250,21 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx)
 	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;
 }
 
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index 938d854bc..f255a70e1 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -192,23 +192,32 @@ extern unsigned jtag_tap_count(void);
 
 
 /*
- * 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
@@ -643,8 +652,8 @@ extern void jtag_execute_queue_noclear(void);
 /// @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 */
diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
index 53c19e1a1..212be3557 100644
--- a/src/jtag/tcl.c
+++ b/src/jtag/tcl.c
@@ -41,7 +41,8 @@
 #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" },
 
@@ -373,7 +374,7 @@ static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e)
 
 	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,
@@ -384,10 +385,12 @@ static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e)
 			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;
@@ -586,13 +589,12 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 }
 
 
-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);
 }
 
 
diff --git a/tcl/target/ti_dm355.cfg b/tcl/target/ti_dm355.cfg
index b1e19e99d..2551c3ed4 100644
--- a/tcl/target/ti_dm355.cfg
+++ b/tcl/target/ti_dm355.cfg
@@ -9,11 +9,11 @@ if { [info exists CHIPNAME] } {
 
 # 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]
 
@@ -50,6 +50,9 @@ if { [info exists JRC_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
diff --git a/tcl/target/ti_dm365.cfg b/tcl/target/ti_dm365.cfg
index 3a17d1a8b..e2d29bd5a 100644
--- a/tcl/target/ti_dm365.cfg
+++ b/tcl/target/ti_dm365.cfg
@@ -7,16 +7,15 @@ if { [info exists CHIPNAME] } {
    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 ] } {
@@ -46,6 +45,9 @@ if { [info exists JRC_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
diff --git a/tcl/target/ti_dm6446.cfg b/tcl/target/ti_dm6446.cfg
index e96c3e15f..4dac3d5fa 100644
--- a/tcl/target/ti_dm6446.cfg
+++ b/tcl/target/ti_dm6446.cfg
@@ -7,17 +7,15 @@ if { [info exists CHIPNAME] } {
    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
@@ -57,6 +55,10 @@ if { [info exists JRC_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"
+
+################
 # 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.
-- 
GitLab