X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=96565d949e97c8761a5ae4ee029de20dce614731;hb=b550f70100794d8dfa91d2760324041828836f82;hp=292aa55aaecf557033cef348c148a4ade0b27587;hpb=861f52ff16417bf3077a236b866d906636424d2c;p=openocd.git diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 292aa55aae..96565d949e 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -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; }