David Brownell <david-b@pacbell.net> More jtag_add_reset() cleanup:
[openocd.git] / src / jtag / core.c
index d9cdffa53dcbb61d0c242cf869e48124b4c354c3..d278c96bcca83346f58245ca151889d0ebfec06c 100644 (file)
@@ -60,11 +60,15 @@ static int jtag_error = ERROR_OK;
 
 static const char *jtag_event_strings[] =
 {
-       [JTAG_TRST_ASSERTED] = "JTAG controller reset (RESET or TRST)",
+       [JTAG_TRST_ASSERTED] = "JTAG controller reset (TLR or TRST)",
        [JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
        [JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
 };
 
+/*
+ * JTAG adapters must initialize with TRST and SRST de-asserted
+ * (they're negative logic, so that means *high*)
+ */
 static int jtag_trst = 0;
 static int jtag_srst = 0;
 
@@ -581,102 +585,105 @@ void jtag_add_clocks(int num_cycles)
 void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 {
        int trst_with_tlr = 0;
+       int new_srst = 0;
+       int new_trst = 0;
 
-       /* FIX!!! there are *many* different cases here. A better
-        * approach is needed for legal combinations of transitions...
+       /* Without SRST, we must use target-specific JTAG operations
+        * on each target; callers should not be requesting SRST when
+        * that signal doesn't exist.
+        *
+        * RESET_SRST_PULLS_TRST is a board or chip level quirk, which
+        * can kick in even if the JTAG adapter can't drive TRST.
         */
-       if ((jtag_reset_config & RESET_HAS_SRST)&&
-                       (jtag_reset_config & RESET_HAS_TRST)&&
-                       ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0))
-       {
-               if (((req_tlr_or_trst&&!jtag_trst)||
-                               (!req_tlr_or_trst && jtag_trst))&&
-                               ((req_srst&&!jtag_srst)||
-                                               (!req_srst && jtag_srst)))
-               {
-                       /* FIX!!! srst_pulls_trst allows 1,1 => 0,0 transition.... */
-                       //LOG_ERROR("BUG: transition of req_tlr_or_trst and req_srst in the same jtag_add_reset() call is undefined");
+       if (req_srst) {
+               if (!(jtag_reset_config & RESET_HAS_SRST)) {
+                       LOG_ERROR("BUG: can't assert SRST");
+                       jtag_set_error(ERROR_FAIL);
+                       return;
+               }
+               if ((jtag_reset_config & RESET_SRST_PULLS_TRST) != 0
+                               && !req_tlr_or_trst) {
+                       LOG_ERROR("BUG: can't assert only SRST");
+                       jtag_set_error(ERROR_FAIL);
+                       return;
                }
+               new_srst = 1;
        }
 
-       /* Make sure that jtag_reset_config allows the requested reset */
-       /* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */
-       if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tlr_or_trst))
-       {
-               LOG_ERROR("BUG: requested reset would assert trst");
-               jtag_set_error(ERROR_FAIL);
-               return;
+       /* JTAG reset (entry to TAP_RESET state) can always be achieved
+        * using TCK and TMS; that may go through a TAP_{IR,DR}UPDATE
+        * state first.  TRST accelerates it, and bypasses those states.
+        *
+        * RESET_TRST_PULLS_SRST is a board or chip level quirk, which
+        * can kick in even if the JTAG adapter can't drive SRST.
+        */
+       if (req_tlr_or_trst) {
+               if (!(jtag_reset_config & RESET_HAS_TRST))
+                       trst_with_tlr = 1;
+               else if ((jtag_reset_config & RESET_TRST_PULLS_SRST) != 0
+                               && !req_srst)
+                       trst_with_tlr = 1;
+               else
+                       new_trst = 1;
        }
 
-       /* if TRST pulls SRST, we reset with TAP T-L-R */
-       if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_tlr_or_trst)) && (req_srst == 0))
-       {
-               trst_with_tlr = 1;
-       }
+       /* Maybe change TRST and/or SRST signal state */
+       if (jtag_srst != new_srst || jtag_trst != new_trst) {
+               int retval;
 
-       if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))
-       {
-               LOG_ERROR("BUG: requested SRST assertion, but the current configuration doesn't support this");
-               jtag_set_error(ERROR_FAIL);
-               return;
-       }
+               retval = interface_jtag_add_reset(new_trst, new_srst);
+               if (retval != ERROR_OK)
+                       jtag_set_error(retval);
+               else
+                       retval = jtag_execute_queue();
 
-       if (req_tlr_or_trst)
-       {
-               if (!trst_with_tlr && (jtag_reset_config & RESET_HAS_TRST))
-               {
-                       jtag_trst = 1;
-               } else
-               {
-                       trst_with_tlr = 1;
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("TRST/SRST error %d", retval);
+                       return;
                }
-       } else
-       {
-               jtag_trst = 0;
        }
 
-       jtag_srst = req_srst;
-
-       int retval = interface_jtag_add_reset(jtag_trst, jtag_srst);
-       if (retval != ERROR_OK)
-       {
-               jtag_set_error(retval);
-               return;
-       }
-       jtag_execute_queue();
-
-       if (jtag_srst)
-       {
-               LOG_DEBUG("SRST line asserted");
-       }
-       else
-       {
-               LOG_DEBUG("SRST line released");
-               if (jtag_nsrst_delay)
-                       jtag_add_sleep(jtag_nsrst_delay * 1000);
+       /* SRST resets everything hooked up to that signal */
+       if (jtag_srst != new_srst) {
+               jtag_srst = new_srst;
+               if (jtag_srst)
+                       LOG_DEBUG("SRST line asserted");
+               else {
+                       LOG_DEBUG("SRST line released");
+                       if (jtag_nsrst_delay)
+                               jtag_add_sleep(jtag_nsrst_delay * 1000);
+               }
        }
 
-       if (trst_with_tlr)
-       {
-               LOG_DEBUG("JTAG reset with RESET instead of TRST");
+       /* Maybe enter the JTAG TAP_RESET state ...
+        *  - using only TMS, TCK, and the JTAG state machine
+        *  - or else more directly, using TRST
+        *
+        * TAP_RESET should be invisible to non-debug parts of the system.
+        */
+       if (trst_with_tlr) {
+               LOG_DEBUG("JTAG reset with TLR instead of TRST");
                jtag_set_end_state(TAP_RESET);
                jtag_add_tlr();
-               return;
-       }
 
-       if (jtag_trst)
-       {
-               /* we just asserted nTRST, so we're now in Test-Logic-Reset,
-                * and inform possible listeners about this
-                */
-               LOG_DEBUG("TRST line asserted");
-               tap_set_state(TAP_RESET);
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-       }
-       else
-       {
-               if (jtag_ntrst_delay)
-                       jtag_add_sleep(jtag_ntrst_delay * 1000);
+       } else if (jtag_trst != new_trst) {
+               jtag_trst = new_trst;
+               if (jtag_trst) {
+                       /* we just asserted nTRST, so we're now in TAP_RESET;
+                        * inform possible listeners about this
+                        *
+                        * REVISIT asserting TRST is less significant than
+                        * being in TAP_RESET ... both entries (TRST, TLR)
+                        * should trigger a callback.
+                        */
+                       LOG_DEBUG("TRST line asserted");
+                       tap_set_state(TAP_RESET);
+                       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+               } else {
+                       LOG_DEBUG("TRST line released");
+                       if (jtag_ntrst_delay)
+                               jtag_add_sleep(jtag_ntrst_delay * 1000);
+               }
        }
 }
 
@@ -811,6 +818,7 @@ static int jtag_reset_callback(enum jtag_event event, void *priv)
        {
                tap->enabled = !tap->disabled_after_reset;
 
+               /* current instruction is either BYPASS or IDCODE */
                buf_set_ones(tap->cur_instr, tap->ir_length);
                tap->bypass = 1;
        }
@@ -1223,11 +1231,11 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
        if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
                return retval;
 
-       LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / RESET");
+       LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / TLR");
 
        /* Reset can happen after a power cycle.
         *
-        * Ideally we would only assert TRST or run RESET before the target reset.
+        * Ideally we would only assert TRST or run TLR before the target reset.
         *
         * However w/srst_pulls_trst, trst is asserted together with the target
         * reset whether we want it or not.
@@ -1240,7 +1248,7 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
         * NB! order matters!!!! srst *can* disconnect JTAG circuitry
         *
         */
-       jtag_add_reset(1, 0); /* RESET or TRST */
+       jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */
        if (jtag_reset_config & RESET_HAS_SRST)
        {
                jtag_add_reset(1, 1);

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)