X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=b1d3ca0f1abb107b0aa1d4067ed7b83b79fe9151;hb=f64e924ba96d944259b284f8cc517e315e78acde;hp=bf4a9cc7f69a54c27a46d2d5d22e07c0977d8aea;hpb=0c4b119d3f8c218f4da0336fb9c25f856f52853e;p=openocd.git diff --git a/src/jtag/core.c b/src/jtag/core.c index bf4a9cc7f6..b1d3ca0f1a 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -837,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 = { @@ -855,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(); @@ -899,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; } /** @@ -907,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) @@ -921,19 +935,14 @@ 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; @@ -944,7 +953,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap) } /* If none of the expected ids matched, log an error */ - 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++) { @@ -958,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; @@ -977,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)) { @@ -995,26 +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->dotted_name, idcode); bit_count += 32; } - device_count++; tap->idcode = idcode; // ensure the TAP ID does matches what was expected @@ -1022,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; @@ -1055,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; @@ -1081,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; @@ -1114,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); @@ -1131,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); } @@ -1140,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); @@ -1211,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;