Update the jtag-examine_chain() logic to verify that there's
no garbage after the expected (from the TAPs' BYPASS or IDCODE
registers). Such garbage normally indicates a TAP that wasn't
configured; although this also handles the case observed with
some AVR8 cores, where instead of shifting TDI they shift ones.
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 didn't check *after* that
list completed.
Also do a better job of ignoring devices that don't support the
IDCODE instruction; and replace a now-obsolete scanchain length
test with one that behaves correctly.
---
Behaved for me in light testing; but I'll wait for feedback,
in case there's something I missed.
src/jtag/core.c | 73 ++++++++++++++++++++++++++++--------------------------
1 file changed, 38 insertions(+), 35 deletions(-)
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -837,13 +837,18 @@ 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)
+#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 +860,7 @@ static int jtag_examine_chain_execute(ui
// 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 +904,12 @@ static void jtag_examine_chain_display(e
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_
* 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,6 +932,7 @@ static void jtag_examine_chain_end(uint8
count, (unsigned int)idcode);
triggered = true;
}
+ return triggered;
}
static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
@@ -962,10 +974,12 @@ static bool jtag_examine_chain_match_tap
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 +991,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))
{
@@ -992,29 +1006,15 @@ static int jtag_examine_chain(void)
tap->hasidcode = false;
bit_count += 1;
+ continue;
}
- else
- {
- 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);
+ /* Friendly devices support IDCODE */
+ tap->hasidcode = true;
+ jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
+ tap->dotted_name, idcode);
- bit_count += 32;
- }
- device_count++;
+ bit_count += 32;
tap->idcode = idcode;
// ensure the TAP ID does matches what was expected
@@ -1022,17 +1022,20 @@ 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)))
+ return ERROR_JTAG_INIT_FAILED;
+
return ERROR_OK;
}
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development