JTAG: jtag_tap_init() bugfixes
[openocd.git] / src / jtag / core.c
index 854236f3d15346d31b5d3bba24e89c4803ff34ea..08cfe436b236a41b94a009ef2a72b3abc6bfc404 100644 (file)
@@ -68,10 +68,12 @@ static const char *jtag_event_strings[] =
 
 /*
  * JTAG adapters must initialize with TRST and SRST de-asserted
- * (they're negative logic, so that means *high*)
+ * (they're negative logic, so that means *high*).  But some
+ * hardware doesn't necessarily work that way ... so set things
+ * up so that jtag_init() always forces that state.
  */
-static int jtag_trst = 0;
-static int jtag_srst = 0;
+static int jtag_trst = -1;
+static int jtag_srst = -1;
 
 /**
  * List all TAPs that have been created.
@@ -135,6 +137,32 @@ int jtag_error_clear(void)
        return temp;
 }
 
+/************/
+
+static bool jtag_poll = 1;
+
+bool is_jtag_poll_safe(void)
+{
+       /* Polling can be disabled explicitly with set_enabled(false).
+        * It is also implicitly disabled while TRST is active and
+        * while SRST is gating the JTAG clock.
+        */
+       if (!jtag_poll || jtag_trst != 0)
+               return false;
+       return jtag_srst == 0 || (jtag_reset_config & RESET_SRST_NO_GATING);
+}
+
+bool jtag_poll_get_enabled(void)
+{
+       return jtag_poll;
+}
+
+void jtag_poll_set_enabled(bool value)
+{
+       jtag_poll = value;
+}
+
+/************/
 
 jtag_tap_t *jtag_all_taps(void)
 {
@@ -539,12 +567,14 @@ int jtag_add_statemove(tap_state_t goal_state)
                tap_state_name(goal_state));
 
 
-       if (goal_state == cur_state)
-               ;       /* nothing to do */
-       else if (goal_state == TAP_RESET)
-       {
+       /* If goal is RESET, be paranoid and force that that transition
+        * (e.g. five TCK cycles, TMS high).  Else trust "cur_state".
+        */
+       if (goal_state == TAP_RESET)
                jtag_add_tlr();
-       }
+       else if (goal_state == cur_state)
+               /* nothing to do */ ;
+
        else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state))
        {
                unsigned tms_bits  = tap_get_tms_path(cur_state, goal_state);
@@ -890,7 +920,15 @@ static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count)
        }
 
        /* if there wasn't a single non-zero bit or if all bits were one,
-        * the scan is not valid */
+        * the scan is not valid.  We wrote a mix of both values; either
+        *
+        *  - There's a hardware issue (almost certainly):
+        *     + all-zeroes can mean a target stuck in JTAG reset
+        *     + all-ones tends to mean no target
+        *  - The scan chain is WAY longer than we can handle, *AND* either
+        *     + there are several hundreds of TAPs in bypass, or
+        *     + at least a few dozen TAPs all have an all-ones IDCODE
+        */
        if (zero_check == 0x00 || one_check == 0xff)
        {
                LOG_ERROR("JTAG scan chain interrogation failed: all %s",
@@ -937,8 +975,9 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
        for (; count < max - 31; count += 32)
        {
                uint32_t idcode = buf_get_u32(idcodes, count, 32);
-               // do not trigger the warning if the data looks good
-               if (!triggered && jtag_idcode_is_final(idcode))
+
+               /* do not trigger the warning if the data looks good */
+               if (jtag_idcode_is_final(idcode))
                        continue;
                LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
                                        count, (unsigned int)idcode);
@@ -954,8 +993,9 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
                return true;
 
        /* Loop over the expected identification codes and test for a match */
-       uint8_t ii;
-       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       unsigned ii, limit = tap->expected_ids_cnt;
+
+       for (ii = 0; ii < limit; ii++)
        {
                if (tap->idcode == tap->expected_ids[ii])
                        return true;
@@ -968,11 +1008,11 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
        /* If none of the expected ids matched, warn */
        jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED",
                        tap->dotted_name, tap->idcode);
-       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       for (ii = 0; ii < limit; ii++)
        {
                char msg[32];
-               snprintf(msg, sizeof(msg), "expected %hhu of %hhu",
-                               ii + 1, tap->expected_ids_cnt);
+
+               snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, limit);
                jtag_examine_chain_display(LOG_LVL_ERROR, msg,
                                tap->dotted_name, tap->expected_ids[ii]);
        }
@@ -986,11 +1026,15 @@ static int jtag_examine_chain(void)
 {
        uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
        unsigned bit_count;
+       int retval;
 
        /* DR scan to collect BYPASS or IDCODE register contents.
         * Then make sure the scan data has both ones and zeroes.
         */
-       jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+       LOG_DEBUG("DR scan interrogation for IDCODE/BYPASS");
+       retval = jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+       if (retval != ERROR_OK)
+               return retval;
        if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
                return ERROR_JTAG_INIT_FAILED;
 
@@ -1010,7 +1054,7 @@ static int jtag_examine_chain(void)
 
                if ((idcode & 1) == 0)
                {
-                       /* LSB must not be 0, this indicates a device in bypass */
+                       /* Zero for LSB indicates a device in bypass */
                        LOG_WARNING("TAP %s does not have IDCODE",
                                        tap->dotted_name);
                        idcode = 0;
@@ -1022,7 +1066,8 @@ static int jtag_examine_chain(void)
                {
                        /* Friendly devices support IDCODE */
                        tap->hasidcode = true;
-                       jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
+                       jtag_examine_chain_display(LOG_LVL_INFO,
+                                       "tap/device found",
                                        tap->dotted_name, idcode);
 
                        bit_count += 32;
@@ -1031,7 +1076,7 @@ static int jtag_examine_chain(void)
 
                /* ensure the TAP ID matches what was expected */
                if (!jtag_examine_chain_match_tap(tap))
-                       return ERROR_JTAG_INIT_FAILED;
+                       retval = ERROR_JTAG_INIT_SOFT_FAIL;
        }
 
        /* Fail if too many TAPs were enabled for us to verify them all. */
@@ -1047,11 +1092,14 @@ static int jtag_examine_chain(void)
        if (jtag_examine_chain_end(idcode_buffer, bit_count,
                        8 * sizeof(idcode_buffer))) {
                LOG_ERROR("double-check your JTAG setup (interface, "
-                               "speed, TAPs, ...)");
+                               "speed, missing TAPs, ...)");
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       return ERROR_OK;
+       /* Return success or, for backwards compatibility if only
+        * some IDCODE values mismatched, a soft/continuable fault.
+        */
+       return retval;
 }
 
 /*
@@ -1109,15 +1157,20 @@ static int jtag_validate_ircapture(void)
                }
 
                /* Validate the two LSBs, which must be 01 per JTAG spec.
-                * REVISIT we might be able to verify some MSBs too, using
-                * ircapture/irmask attributes.
+                *
+                * Or ... more bits could be provided by TAP declaration.
+                * Plus, some taps (notably in i.MX series chips) violate
+                * this part of the JTAG spec, so their capture mask/value
+                * attributes might disable this test.
                 */
                val = buf_get_u32(ir_test, chain_pos, tap->ir_length);
-               if ((val & 0x3) != 1) {
-                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x..1",
+               if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
+                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x%0*x",
                                        jtag_tap_name(tap),
                                        (tap->ir_length + 7) / tap->ir_length,
-                                       val);
+                                       val,
+                                       (tap->ir_length + 7) / tap->ir_length,
+                                       (unsigned) tap->ir_capture_value);
 
                        retval = ERROR_JTAG_INIT_FAILED;
                        goto done;
@@ -1151,20 +1204,29 @@ done:
 
 void jtag_tap_init(jtag_tap_t *tap)
 {
+       unsigned ir_len_bits;
+       unsigned ir_len_bytes;
+
        assert(0 != tap->ir_length);
 
-       /// @todo fix, this allocates one byte per bit for all three fields!
-       tap->expected = malloc(tap->ir_length);
-       tap->expected_mask = malloc(tap->ir_length);
-       tap->cur_instr = malloc(tap->ir_length);
+       ir_len_bits = tap->ir_length;
+       ir_len_bytes = CEIL(ir_len_bits, 8);
 
-       /// @todo cope sanely with ir_length bigger than 32 bits
-       buf_set_u32(tap->expected, 0, tap->ir_length, tap->ir_capture_value);
-       buf_set_u32(tap->expected_mask, 0, tap->ir_length, tap->ir_capture_mask);
-       buf_set_ones(tap->cur_instr, tap->ir_length);
+       tap->expected = calloc(1, ir_len_bytes);
+       tap->expected_mask = calloc(1, ir_len_bytes);
+       tap->cur_instr = malloc(ir_len_bytes);
+
+       /// @todo cope better with ir_length bigger than 32 bits
+       if (ir_len_bits > 32)
+               ir_len_bits = 32;
+
+       buf_set_u32(tap->expected, 0, ir_len_bits, tap->ir_capture_value);
+       buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask);
 
-       // place TAP in bypass mode
+       // TAP will be in bypass mode after jtag_validate_ircapture()
        tap->bypass = 1;
+       buf_set_ones(tap->cur_instr, tap->ir_length);
+
        // register the reset callback for the TAP
        jtag_register_event_callback(&jtag_reset_callback, tap);
 
@@ -1248,18 +1310,37 @@ int jtag_init_inner(struct command_context_s *cmd_ctx)
        if ((retval = jtag_execute_queue()) != ERROR_OK)
                return retval;
 
-       /* examine chain first, as this could discover the real chain layout */
-       if (jtag_examine_chain() != ERROR_OK)
-       {
+       /* Examine DR values first.  This discovers problems which will
+        * prevent communication ... hardware issues like TDO stuck, or
+        * configuring the wrong number of (enabled) TAPs.
+        */
+       retval = jtag_examine_chain();
+       switch (retval) {
+       case ERROR_OK:
+               /* complete success */
+               break;
+       case ERROR_JTAG_INIT_SOFT_FAIL:
+               /* For backward compatibility reasons, try coping with
+                * configuration errors involving only ID mismatches.
+                * We might be able to talk to the devices.
+                */
                LOG_ERROR("Trying to use configured scan chain anyway...");
                issue_setup = false;
+               break;
+       default:
+               /* some hard error; already issued diagnostics */
+               return retval;
        }
 
-       if (jtag_validate_ircapture() != ERROR_OK)
-       {
-               LOG_WARNING("Errors during IR capture, continuing anyway...");
-               issue_setup = false;
-       }
+       /* Now look at IR values.  Problems here will prevent real
+        * communication.  They mostly mean that the IR length is
+        * wrong ... or that the IR capture value is wrong.  (The
+        * latter is uncommon, but easily worked around:  provide
+        * ircapture/irmask values during TAP setup.)
+        */
+       retval = jtag_validate_ircapture();
+       if (retval != ERROR_OK)
+               return retval;
 
        if (issue_setup)
                jtag_notify_event(JTAG_TAP_EVENT_SETUP);
@@ -1291,22 +1372,31 @@ 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 / TLR");
+       LOG_DEBUG("Initializing with hard TRST+SRST reset");
 
-       /* Reset can happen after a power cycle.
-        *
-        * Ideally we would only assert TRST or run TLR before the target reset.
+       /*
+        * This procedure is used by default when OpenOCD triggers a reset.
+        * It's now done through an overridable Tcl "init_reset" wrapper.
         *
-        * However w/srst_pulls_trst, trst is asserted together with the target
-        * reset whether we want it or not.
+        * This started out as a more powerful "get JTAG working" reset than
+        * jtag_init_inner(), applying TRST because some chips won't activate
+        * JTAG without a TRST cycle (presumed to be async, though some of
+        * those chips synchronize JTAG activation using TCK).
         *
-        * NB! Some targets have JTAG circuitry disabled until a
-        * trst & srst has been asserted.
+        * But some chips only activate JTAG as part of an SRST cycle; SRST
+        * got mixed in.  So it became a hard reset routine, which got used
+        * in more places, and which coped with JTAG reset being forced as
+        * part of SRST (srst_pulls_trst).
         *
-        * NB! here we assume nsrst/ntrst delay are sufficient!
+        * And even more corner cases started to surface:  TRST and/or SRST
+        * assertion timings matter; some chips need other JTAG operations;
+        * TRST/SRST sequences can need to be different from these, etc.
         *
-        * NB! order matters!!!! srst *can* disconnect JTAG circuitry
+        * Systems should override that wrapper to support system-specific
+        * requirements that this not-fully-generic code doesn't handle.
         *
+        * REVISIT once Tcl code can read the reset_config modes, this won't
+        * need to be a C routine at all...
         */
        jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */
        if (jtag_reset_config & RESET_HAS_SRST)
@@ -1332,9 +1422,15 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
 int jtag_init(struct command_context_s *cmd_ctx)
 {
        int retval;
+
        if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
                return retval;
 
+       /* guard against oddball hardware: force resets to be inactive */
+       jtag_add_reset(0, 0);
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+               return retval;
+
        if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
                return ERROR_FAIL;
 

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)