Update the jtag-examine_chain() logic to verify that there's no

garbage after the expected data (from the TAPs' BYPASS or IDCODE
registers).

NOTE that there was previously some code that looked like it was
trying to do this ... which didn't work, because it was looping
over the list of expected TAPs, and never checked *after* that
list completed!  That could hide some *nasty* reset issues...

Also replace a now-obsolete scanchain length test with one that
behaves correctly; and update reporting of unexpected IDCODEs.


git-svn-id: svn://svn.berlios.de/openocd/trunk@2739 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
dbrownell 2009-09-21 00:04:35 +00:00
parent 48e96a18ed
commit d20103cd93
1 changed files with 39 additions and 38 deletions

View File

@ -837,13 +837,18 @@ void jtag_sleep(uint32_t us)
alive_sleep(us/1000); 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 JTAG_MAX_CHAIN_SIZE 20
#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1) #define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12) #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28) #define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
#define END_OF_CHAIN_FLAG 0x000000ff
static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode) static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
{ {
scan_field_t field = { scan_field_t field = {
@ -855,7 +860,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod
// initialize to the end of chain ID value // initialize to the end of chain ID value
for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++) 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_plain_dr_scan(1, &field, TAP_DRPAUSE);
jtag_add_tlr(); jtag_add_tlr();
@ -899,7 +904,12 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg,
static bool jtag_idcode_is_final(uint32_t idcode) 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 +917,9 @@ static bool jtag_idcode_is_final(uint32_t idcode)
* all as expected, but a single JTAG device requires only 64 bits to be * all as expected, but a single JTAG device requires only 64 bits to be
* read back correctly. This can help identify and diagnose problems * read back correctly. This can help identify and diagnose problems
* with the JTAG chain earlier, gives more helpful/explicit error messages. * 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; bool triggered = false;
for (; count < max - 31; count += 32) for (; count < max - 31; count += 32)
@ -921,19 +932,14 @@ static void jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
count, (unsigned int)idcode); count, (unsigned int)idcode);
triggered = true; triggered = true;
} }
return triggered;
} }
static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap) static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
{ {
if (0 == tap->expected_ids_cnt) /* ignore expected BYPASS codes; warn otherwise */
{ if (0 == tap->expected_ids_cnt && !tap->idcode)
/// @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; return true;
}
/* Loop over the expected identification codes and test for a match */ /* Loop over the expected identification codes and test for a match */
uint8_t ii; uint8_t ii;
@ -944,7 +950,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
} }
/* If none of the expected ids matched, log an error */ /* 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); tap->dotted_name, tap->idcode);
for (ii = 0; ii < tap->expected_ids_cnt; ii++) for (ii = 0; ii < tap->expected_ids_cnt; ii++)
{ {
@ -962,10 +968,12 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
static int jtag_examine_chain(void) static int jtag_examine_chain(void)
{ {
uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4]; 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); jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE)) if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
@ -977,7 +985,7 @@ static int jtag_examine_chain(void)
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
} }
for (unsigned bit_count = 0; for (bit_count = 0;
tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31; tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;
tap = jtag_tap_next_enabled(tap)) tap = jtag_tap_next_enabled(tap))
{ {
@ -995,26 +1003,13 @@ static int jtag_examine_chain(void)
} }
else else
{ {
/* Friendly devices support IDCODE */
tap->hasidcode = true; 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", jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
tap->dotted_name, idcode); tap->dotted_name, idcode);
bit_count += 32; bit_count += 32;
} }
device_count++;
tap->idcode = idcode; tap->idcode = idcode;
// ensure the TAP ID does matches what was expected // ensure the TAP ID does matches what was expected
@ -1022,14 +1017,20 @@ static int jtag_examine_chain(void)
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
} }
/* see if number of discovered devices matches configuration */ /* Fail if too many TAPs were enabled for us to verify them all. */
if (device_count != jtag_tap_count_enabled()) if (tap) {
{ LOG_ERROR("Too many TAPs enabled; '%s' ignored.",
LOG_ERROR("number of discovered devices in JTAG chain (%i) " tap->dotted_name);
"does not match (enabled) configuration (%i), total taps: %d", return ERROR_JTAG_INIT_FAILED;
device_count, jtag_tap_count_enabled(), jtag_tap_count()); }
LOG_ERROR("check the config file and ensure proper JTAG communication"
" (connections, speed, ...)"); /* 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_JTAG_INIT_FAILED;
} }