Updates to the initial scanchain validation code:
[fw/openocd] / src / jtag / core.c
index 6a314ece1d868dfc27932c887a688f06daf2f9d3..b1d3ca0f1abb107b0aa1d4067ed7b83b79fe9151 100644 (file)
@@ -60,9 +60,9 @@ static int jtag_error = ERROR_OK;
 
 static const char *jtag_event_strings[] =
 {
-       [JTAG_TRST_ASSERTED] = "JTAG controller reset (TLR or TRST)",
+       [JTAG_TRST_ASSERTED] = "TAP reset",
        [JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
-       [JTAG_TAP_EVENT_POST_RESET] = "post reset",
+       [JTAG_TAP_EVENT_POST_RESET] = "TAP post reset",
        [JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
 };
 
@@ -820,9 +820,6 @@ static int jtag_reset_callback(enum jtag_event event, void *priv)
 {
        jtag_tap_t *tap = priv;
 
-       LOG_DEBUG("TAP %s event %s", tap->dotted_name,
-                       jtag_event_strings[event]);
-
        if (event == JTAG_TRST_ASSERTED)
        {
                tap->enabled = !tap->disabled_after_reset;
@@ -840,13 +837,21 @@ void jtag_sleep(uint32_t us)
        alive_sleep(us/1000);
 }
 
-/// maximum number of JTAG devices expected in the chain
+/* Maximum number of enabled JTAG devices we expect in the scan chain,
+ * plus one (to detect garbage at the end).  Devices that don't support
+ * IDCODE take up fewer bits, possibly allowing a few more devices.
+ */
 #define JTAG_MAX_CHAIN_SIZE 20
 
 #define EXTRACT_MFG(X)  (((X) & 0xffe) >> 1)
 #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
 #define EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
 
+/* A reserved manufacturer ID is used in END_OF_CHAIN_FLAG, so we
+ * know that no valid TAP will have it as an IDCODE value.
+ */
+#define END_OF_CHAIN_FLAG      0x000000ff
+
 static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
 {
        scan_field_t field = {
@@ -858,7 +863,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod
 
        // initialize to the end of chain ID value
        for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
-               buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+               buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG);
 
        jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
        jtag_add_tlr();
@@ -902,7 +907,12 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg,
 
 static bool jtag_idcode_is_final(uint32_t idcode)
 {
-               return idcode == 0x000000FF || idcode == 0xFFFFFFFF;
+       /*
+        * Some devices, such as AVR8, will output all 1's instead
+        * of TDI input value at end of chain.  Allow those values
+        * instead of failing.
+        */
+       return idcode == END_OF_CHAIN_FLAG || idcode == 0xFFFFFFFF;
 }
 
 /**
@@ -910,8 +920,9 @@ static bool jtag_idcode_is_final(uint32_t idcode)
  * all as expected, but a single JTAG device requires only 64 bits to be
  * read back correctly.  This can help identify and diagnose problems
  * with the JTAG chain earlier, gives more helpful/explicit error messages.
+ * Returns TRUE iff garbage was found.
  */
-static void jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max)
+static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max)
 {
        bool triggered = false;
        for (; count < max - 31; count += 32)
@@ -924,35 +935,25 @@ static void jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
                                        count, (unsigned int)idcode);
                triggered = true;
        }
+       return triggered;
 }
 
 static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
 {
-       if (0 == tap->expected_ids_cnt)
-       {
-               /// @todo Enable LOG_INFO to ask for reports about unknown TAP IDs.
-#if 0
-               LOG_INFO("Uknown JTAG TAP ID: 0x%08x", tap->idcode)
-               LOG_INFO("Please report the chip name and reported ID code to the openocd project");
-#endif
+       /* ignore expected BYPASS codes; warn otherwise */
+       if (0 == tap->expected_ids_cnt && !tap->idcode)
                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++)
        {
                if (tap->idcode == tap->expected_ids[ii])
-                       break;
+                       return true;
        }
 
        /* If none of the expected ids matched, log an error */
-       if (ii != tap->expected_ids_cnt)
-       {
-               LOG_DEBUG("JTAG Tap/device matched");
-               return true;
-       }
-       jtag_examine_chain_display(LOG_LVL_ERROR, "got",
+       jtag_examine_chain_display(LOG_LVL_ERROR, "UNEXPECTED",
                        tap->dotted_name, tap->idcode);
        for (ii = 0; ii < tap->expected_ids_cnt; ii++)
        {
@@ -966,14 +967,17 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
 }
 
 /* Try to examine chain layout according to IEEE 1149.1 ยง12
+ * This is called a "blind interrogation" of the scan chain.
  */
 static int jtag_examine_chain(void)
 {
        uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
-       unsigned device_count = 0;
+       unsigned bit_count;
 
+       /* 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);
-
        if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
                return ERROR_JTAG_INIT_FAILED;
 
@@ -985,7 +989,7 @@ static int jtag_examine_chain(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       for (unsigned bit_count = 0;
+       for (bit_count = 0;
                        tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;
                        tap = jtag_tap_next_enabled(tap))
        {
@@ -994,7 +998,8 @@ static int jtag_examine_chain(void)
                if ((idcode & 1) == 0)
                {
                        /* LSB must not be 0, this indicates a device in bypass */
-                       LOG_WARNING("Tap/Device does not have IDCODE");
+                       LOG_WARNING("TAP %s does not have IDCODE",
+                                       tap->dotted_name);
                        idcode = 0;
                        tap->hasidcode = false;
 
@@ -1002,30 +1007,13 @@ static int jtag_examine_chain(void)
                }
                else
                {
+                       /* Friendly devices support IDCODE */
                        tap->hasidcode = true;
-
-                       /*
-                        * End of chain (invalid manufacturer ID) some devices, such
-                        * as AVR will output all 1's instead of TDI input value at
-                        * end of chain.
-                        */
-                       if (jtag_idcode_is_final(idcode))
-                       {
-                               jtag_examine_chain_end(idcode_buffer,
-                                               bit_count + 32, JTAG_MAX_CHAIN_SIZE * 32);
-                               break;
-                       }
-
                        jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
-                                       tap ? tap->dotted_name : "(not-named)",
-                                       idcode);
+                                       tap->dotted_name, idcode);
 
                        bit_count += 32;
                }
-               device_count++;
-               if (!tap)
-                       continue;
-
                tap->idcode = idcode;
 
                // ensure the TAP ID does matches what was expected
@@ -1033,21 +1021,32 @@ static int jtag_examine_chain(void)
                        return ERROR_JTAG_INIT_FAILED;
        }
 
-       /* see if number of discovered devices matches configuration */
-       if (device_count != jtag_tap_count_enabled())
-       {
-               LOG_ERROR("number of discovered devices in JTAG chain (%i) "
-                               "does not match (enabled) configuration (%i), total taps: %d",
-                               device_count, jtag_tap_count_enabled(), jtag_tap_count());
-               LOG_ERROR("check the config file and ensure proper JTAG communication"
-                               " (connections, speed, ...)");
+       /* Fail if too many TAPs were enabled for us to verify them all. */
+       if (tap) {
+               LOG_ERROR("Too many TAPs enabled; '%s' ignored.",
+                               tap->dotted_name);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       /* After those IDCODE or BYPASS register values should be
+        * only the data we fed into the scan chain.
+        */
+       if (jtag_examine_chain_end(idcode_buffer, bit_count,
+                       8 * sizeof(idcode_buffer))) {
+               LOG_ERROR("double-check your JTAG setup (interface, "
+                               "speed, TAPs, ...)");
                return ERROR_JTAG_INIT_FAILED;
        }
 
        return ERROR_OK;
 }
 
-int jtag_validate_chain(void)
+/*
+ * Validate the date loaded by entry to the Capture-IR state, to help
+ * find errors related to scan chain configuration (wrong IR lengths)
+ * or communication.
+ */
+static int jtag_validate_ircapture(void)
 {
        jtag_tap_t *tap;
        int total_ir_length = 0;
@@ -1066,7 +1065,11 @@ int jtag_validate_chain(void)
        }
 
        total_ir_length += 2;
+
        ir_test = malloc(CEIL(total_ir_length, 8));
+       if (ir_test == NULL)
+               return ERROR_FAIL;
+
        buf_set_ones(ir_test, total_ir_length);
 
        field.tap = NULL;
@@ -1092,24 +1095,37 @@ int jtag_validate_chain(void)
                        break;
                }
 
+               /* 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.
+                */
                val = buf_get_u32(ir_test, chain_pos, 2);
-               /* Only fail this check if we have IDCODE for this device */
-               if ((val != 0x1)&&(tap->hasidcode))
-               {
+               if (val != 1) {
                        char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
-                       LOG_ERROR("Could not validate JTAG scan chain, IR mismatch, scan returned 0x%s. tap=%s pos=%d expected 0x1 got %0x", cbuf, jtag_tap_name(tap), chain_pos, val);
-                       free(cbuf);
-                       free(ir_test);
-                       return ERROR_JTAG_INIT_FAILED;
+
+                       LOG_ERROR("%s: IR capture error; saw 0x%s not 0x..1",
+                                       jtag_tap_name(tap), cbuf);
+
+                       /* Fail only if we have IDCODE for this device.
+                        * REVISIT -- why not fail-always?
+                        */
+                       if (tap->hasidcode) {
+                               free(cbuf);
+                               free(ir_test);
+                               return ERROR_JTAG_INIT_FAILED;
+                       }
                }
                chain_pos += tap->ir_length;
        }
 
+       /* verify the '11' sentinel we wrote is returned at the end */
        val = buf_get_u32(ir_test, chain_pos, 2);
        if (val != 0x3)
        {
                char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
-               LOG_ERROR("Could not validate end of JTAG scan chain, IR mismatch, scan returned 0x%s. pos=%d expected 0x3 got %0x", cbuf, chain_pos, val);
+
+               LOG_ERROR("IR capture error at bit %d, saw 0x%s not 0x...3",
+                               chain_pos, cbuf);
                free(cbuf);
                free(ir_test);
                return ERROR_JTAG_INIT_FAILED;
@@ -1125,6 +1141,7 @@ void jtag_tap_init(jtag_tap_t *tap)
 {
        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);
@@ -1142,7 +1159,8 @@ void jtag_tap_init(jtag_tap_t *tap)
        LOG_DEBUG("Created Tap: %s @ abs position %d, "
                        "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
                                tap->abs_chain_position, tap->ir_length,
-                         (unsigned int)(tap->ir_capture_value), (unsigned int)(tap->ir_capture_mask));
+                               (unsigned) tap->ir_capture_value,
+                               (unsigned) tap->ir_capture_mask);
        jtag_tap_add(tap);
 }
 
@@ -1151,6 +1169,7 @@ void jtag_tap_free(jtag_tap_t *tap)
        jtag_unregister_event_callback(&jtag_reset_callback, tap);
 
        /// @todo is anything missing? no memory leaks please
+       free((void *)tap->expected);
        free((void *)tap->expected_ids);
        free((void *)tap->chip);
        free((void *)tap->tapname);
@@ -1222,9 +1241,9 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx)
                LOG_ERROR("trying to validate configured JTAG chain anyway...");
        }
 
-       if (jtag_validate_chain() != ERROR_OK)
+       if (jtag_validate_ircapture() != ERROR_OK)
        {
-               LOG_WARNING("Could not validate JTAG chain, continuing anyway...");
+               LOG_WARNING("Errors during IR capture, continuing anyway...");
        }
 
        return ERROR_OK;