Factoring of jtag_examine_chain for maintainability:
[openocd.git] / src / jtag / jtag.c
index 292aa55aaecf557033cef348c148a4ade0b27587..96565d949e97c8761a5ae4ee029de20dce614731 100644 (file)
@@ -946,109 +946,168 @@ void jtag_sleep(u32 us)
 #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
 #define EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
 
-/* Try to examine chain layout according to IEEE 1149.1 §12
- */
-static int jtag_examine_chain(void)
+static int jtag_examine_chain_execute(u8 *idcode_buffer, unsigned num_idcode)
+{
+       scan_field_t field = {
+                       .tap = NULL,
+                       .num_bits = num_idcode * 32,
+                       .out_value = idcode_buffer,
+                       .in_value = idcode_buffer,
+               };
+
+       // 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);
+
+       jtag_add_plain_dr_scan(1, &field, TAP_RESET);
+       return jtag_execute_queue();
+}
+
+static bool jtag_examine_chain_check(u8 *idcodes, unsigned count)
 {
-       jtag_tap_t *tap;
-       scan_field_t field;
-       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
-       int i;
-       int bit_count;
-       int device_count = 0;
        u8 zero_check = 0x0;
        u8 one_check = 0xff;
 
-       field.tap = NULL;
-       field.num_bits = sizeof(idcode_buffer) * 8;
-       field.out_value = idcode_buffer;
-
-       field.in_value = idcode_buffer;
+       for (unsigned i = 0; i < count * 4; i++)
+       {
+               zero_check |= idcodes[i];
+               one_check &= idcodes[i];
+       }
 
+       /* if there wasn't a single non-zero bit or if all bits were one,
+        * the scan is not valid */
+       if (zero_check == 0x00 || one_check == 0xff)
+       {
+               LOG_ERROR("JTAG communication failure: check connection, "
+                       "JTAG interface, target power etc.");
+               return false;
+       }
+       return true;
+}
 
+static void jtag_examine_chain_display(enum log_levels level, const char *msg,
+               const char *name, u32 idcode)
+{
+       log_printf_lf(level, __FILE__, __LINE__, __FUNCTION__,
+                       "JTAG tap: %s %16.16s: 0x%08x "
+                       "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
+               name, msg, idcode,
+               EXTRACT_MFG(idcode), EXTRACT_PART(idcode), EXTRACT_VER(idcode) );
+}
 
+static bool jtag_idcode_is_final(u32 idcode)
+{
+               return idcode == 0x000000FF || idcode == 0xFFFFFFFF;
+}
 
-       for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+/**
+ * This helper checks that remaining bits in the examined chain data are
+ * 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.
+ */
+static void jtag_examine_chain_end(u8 *idcodes, unsigned count, unsigned max)
+{
+       bool triggered = false;
+       for ( ; count < max - 31; count += 32)
        {
-               buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+               u32 idcode = buf_get_u32(idcodes, count, 32);
+               // do not trigger the warning if the data looks good
+               if (!triggered && jtag_idcode_is_final(idcode))
+                       continue;
+               LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
+                               count, idcode);
+               triggered = true;
        }
+}
 
-       jtag_add_plain_dr_scan(1, &field, TAP_RESET);
-       jtag_execute_queue();
+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
+               return true;
+       }
 
-       for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
+       /* Loop over the expected identification codes and test for a match */
+       u8 ii;
+       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
        {
-               zero_check |= idcode_buffer[i];
-               one_check &= idcode_buffer[i];
+               if (tap->idcode == tap->expected_ids[ii])
+                       break;
        }
 
-       /* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */
-       if ((zero_check == 0x00) || (one_check == 0xff))
+       /* If none of the expected ids matched, log an error */
+       if (ii != tap->expected_ids_cnt)
        {
-               LOG_ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");
-               return ERROR_JTAG_INIT_FAILED;
+               LOG_INFO("JTAG Tap/device matched");
+               return true;
+       }
+       jtag_examine_chain_display(LOG_LVL_ERROR, "got",
+                       tap->dotted_name, tap->idcode);
+       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       {
+               char msg[32];
+               snprintf(msg, sizeof(msg), "expected %hhu of %hhu",
+                               ii + 1, tap->expected_ids_cnt);
+               jtag_examine_chain_display(LOG_LVL_ERROR, msg,
+                               tap->dotted_name, tap->expected_ids[ii]);
        }
+       return false;
+}
+
+/* Try to examine chain layout according to IEEE 1149.1 §12
+ */
+static int jtag_examine_chain(void)
+{
+       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+       int device_count = 0;
+
+       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;
 
        /* point at the 1st tap */
-       tap = jtag_tap_next_enabled(NULL);
-       if( tap == NULL ){
+       jtag_tap_t *tap = jtag_tap_next_enabled(NULL);
+       if (tap == NULL)
+       {
                LOG_ERROR("JTAG: No taps enabled?");
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
+       for (unsigned bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
        {
                u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
                if ((idcode & 1) == 0)
                {
                        /* LSB must not be 0, this indicates a device in bypass */
                        LOG_WARNING("Tap/Device does not have IDCODE");
-                       idcode=0;
+                       idcode = 0;
 
                        bit_count += 1;
                }
                else
                {
-                       u32 manufacturer;
-                       u32 part;
-                       u32 version;
-
-                       /* some devices, such as AVR will output all 1's instead of TDI
-                       input value at end of chain. */
-                       if ((idcode == 0x000000FF)||(idcode == 0xFFFFFFFF))
+                       /*
+                        * 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))
                        {
-                               int unexpected=0;
-                               /* End of chain (invalid manufacturer ID)
-                                *
-                                * The JTAG examine is the very first thing that happens
-                                *
-                                * A single JTAG device requires only 64 bits to be read back correctly.
-                                *
-                                * The code below adds a check that the rest of the data scanned (640 bits)
-                                * are all as expected. This helps diagnose/catch problems with the JTAG chain
-                                *
-                                * earlier and gives more helpful/explicit error messages.
-                                */
-                               for (bit_count += 32; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;bit_count += 32)
-                               {
-                                       idcode = buf_get_u32(idcode_buffer, bit_count, 32);
-                                       if (unexpected||((idcode != 0x000000FF)&&(idcode != 0xFFFFFFFF)))
-                                       {
-                                               LOG_WARNING("Unexpected idcode after end of chain! %d 0x%08x", bit_count, idcode);
-                                               unexpected = 1;
-                                       }
-                               }
-
+                               jtag_examine_chain_end(idcode_buffer,
+                                               bit_count + 32, JTAG_MAX_CHAIN_SIZE * 32);
                                break;
                        }
 
-                       manufacturer = EXTRACT_MFG(idcode);
-                       part = EXTRACT_PART(idcode);
-                       version = EXTRACT_VER(idcode);
-
-                       LOG_INFO("JTAG tap: %s tap/device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)",
-                                        ((tap != NULL) ? (tap->dotted_name) : "(not-named)"),
-                               idcode, manufacturer, part, version);
+                       jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
+                                       tap ? tap->dotted_name : "(not-named)",
+                                       idcode);
 
                        bit_count += 32;
                }
@@ -1058,56 +1117,21 @@ static int jtag_examine_chain(void)
 
                tap->idcode = idcode;
 
-               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
-                       tap = jtag_tap_next_enabled(tap);
-                       continue;
-               }
-                       /* Loop over the expected identification codes and test for a match */
-               u8 ii;
-               for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
-                       if (tap->idcode == tap->expected_ids[ii]) {
-                               break;
-                       }
-               }
+               // ensure the TAP ID does matches what was expected
+               if (!jtag_examine_chain_match_tap(tap))
+                       return ERROR_JTAG_INIT_FAILED;
 
-               /* If none of the expected ids matched, log an error */
-               if (ii != tap->expected_ids_cnt)
-               {
-                       LOG_INFO("JTAG Tap/device matched");
-                       tap = jtag_tap_next_enabled(tap);
-                       continue;
-               }
-               LOG_ERROR("JTAG tap: %s             got: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
-                               tap->dotted_name,
-                               idcode,
-                               EXTRACT_MFG( tap->idcode ),
-                               EXTRACT_PART( tap->idcode ),
-                               EXTRACT_VER( tap->idcode ) );
-               for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
-                       LOG_ERROR("JTAG tap: %s expected %hhu of %hhu: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
-                                       tap->dotted_name,
-                                       ii + 1,
-                                       tap->expected_ids_cnt,
-                                       tap->expected_ids[ii],
-                                       EXTRACT_MFG( tap->expected_ids[ii] ),
-                                       EXTRACT_PART( tap->expected_ids[ii] ),
-                                       EXTRACT_VER( tap->expected_ids[ii] ) );
-               }
-               return ERROR_JTAG_INIT_FAILED;
+               tap = jtag_tap_next_enabled(tap);
        }
 
        /* 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) doesn't 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, ...)");
+               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, ...)");
                return ERROR_JTAG_INIT_FAILED;
        }
 

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)