/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
+ * Copyright (C) 2009 Zachary T Welch *
+ * zw@superlucidity.net *
* *
- * Copyright (C) 2007,2008 Øyvind Harboe *
+ * Copyright (C) 2007,2008,2009 Øyvind Harboe *
* oyvind.harboe@zylin.com *
* *
* Copyright (C) 2009 SoftPLC Corporation *
* http://softplc.com *
* dick@softplc.com *
* *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
+ * Copyright (C) 2005 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
static const char *jtag_event_strings[] =
{
- [JTAG_TRST_ASSERTED] = "JTAG controller reset (TLR or TRST)",
+ [JTAG_TRST_ASSERTED] = "TAP reset",
+ [JTAG_TAP_EVENT_SETUP] = "TAP setup",
[JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
- [JTAG_TAP_EVENT_POST_RESET] = "post reset",
[JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
};
/*
* JTAG adapters must initialize with TRST and SRST de-asserted
- * (they're negative logic, so that means *high*)
+ * (they're negative logic, so that means *high*). But some
+ * hardware doesn't necessarily work that way ... so set things
+ * up so that jtag_init() always forces that state.
*/
-static int jtag_trst = 0;
-static int jtag_srst = 0;
+static int jtag_trst = -1;
+static int jtag_srst = -1;
/**
* List all TAPs that have been created.
/* how long the OpenOCD should wait before attempting JTAG communication after reset lines deasserted (in ms) */
static int jtag_nsrst_delay = 0; /* default to no nSRST delay */
static int jtag_ntrst_delay = 0; /* default to no nTRST delay */
+static int jtag_nsrst_assert_width = 0; /* width of assertion */
+static int jtag_ntrst_assert_width = 0; /* width of assertion */
typedef struct jtag_event_callback_s
{
tap_state_t state)
{
assert(state != TAP_RESET);
-
+
jtag_prelude(state);
int retval;
tap_state_t state)
{
assert(state != TAP_RESET);
-
+
jtag_prelude(state);
int retval;
tap_state_t end_state)
{
assert(end_state != TAP_RESET);
-
assert(end_state != TAP_INVALID);
cmd_queue_cur_state = end_state;
jtag_prelude(TAP_RESET);
jtag_set_error(interface_jtag_add_tlr());
- jtag_notify_reset();
-
+ /* NOTE: order here matches TRST path in jtag_add_reset() */
jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+ jtag_notify_event(JTAG_TRST_ASSERTED);
}
void jtag_add_pathmove(int num_states, const tap_state_t *path)
if (jtag_srst != new_srst) {
jtag_srst = new_srst;
if (jtag_srst)
+ {
LOG_DEBUG("SRST line asserted");
+ if (jtag_nsrst_assert_width)
+ jtag_add_sleep(jtag_nsrst_assert_width * 1000);
+ }
else {
LOG_DEBUG("SRST line released");
if (jtag_nsrst_delay)
} else if (jtag_trst != new_trst) {
jtag_trst = new_trst;
if (jtag_trst) {
- /* we just asserted nTRST, so we're now in TAP_RESET;
- * inform possible listeners about this
- *
- * REVISIT asserting TRST is less significant than
- * being in TAP_RESET ... both entries (TRST, TLR)
- * should trigger a callback.
- */
LOG_DEBUG("TRST line asserted");
tap_set_state(TAP_RESET);
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+ if (jtag_ntrst_assert_width)
+ jtag_add_sleep(jtag_ntrst_assert_width * 1000);
} else {
LOG_DEBUG("TRST line released");
if (jtag_ntrst_delay)
jtag_add_sleep(jtag_ntrst_delay * 1000);
- jtag_notify_reset();
+ /* We just asserted nTRST, so we're now in TAP_RESET.
+ * Inform possible listeners about this, now that
+ * JTAG instructions and data can be shifted. This
+ * sequence must match jtag_add_tlr().
+ */
+ jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+ jtag_notify_event(JTAG_TRST_ASSERTED);
}
}
}
{
jtag_tap_t *tap = priv;
- LOG_DEBUG("-");
-
if (event == JTAG_TRST_ASSERTED)
{
tap->enabled = !tap->disabled_after_reset;
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 = {
// 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();
* the scan is not valid */
if (zero_check == 0x00 || one_check == 0xff)
{
- LOG_ERROR("JTAG communication failure: check connection, "
- "JTAG interface, target power etc.");
+ LOG_ERROR("JTAG scan chain interrogation failed: all %s",
+ (zero_check == 0x00) ? "zeroes" : "ones");
+ LOG_ERROR("Check JTAG interface, timings, target power, etc.");
return false;
}
return true;
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;
}
/**
* 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)
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;
for (ii = 0; ii < tap->expected_ids_cnt; ii++)
{
if (tap->idcode == tap->expected_ids[ii])
- break;
- }
+ return true;
- /* If none of the expected ids matched, log an error */
- if (ii != tap->expected_ids_cnt)
- {
- LOG_DEBUG("JTAG Tap/device matched");
- return true;
+ /* treat "-expected-id 0" as a "don't-warn" wildcard */
+ if (0 == tap->expected_ids[ii])
+ return true;
}
- jtag_examine_chain_display(LOG_LVL_ERROR, "got",
+
+ /* If none of the expected ids matched, warn */
+ jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED",
tap->dotted_name, tap->idcode);
for (ii = 0; ii < tap->expected_ids_cnt; ii++)
{
}
/* 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;
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))
{
if ((idcode & 1) == 0)
{
/* LSB must not be 0, this indicates a device in bypass */
- LOG_WARNING("Tap/Device does not have IDCODE");
+ LOG_WARNING("TAP %s does not have IDCODE",
+ tap->dotted_name);
idcode = 0;
tap->hasidcode = false;
}
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 ? tap->dotted_name : "(not-named)",
- idcode);
+ tap->dotted_name, idcode);
bit_count += 32;
}
- device_count++;
- if (!tap)
- continue;
-
tap->idcode = idcode;
- // ensure the TAP ID does matches what was expected
+ /* ensure the TAP ID matches what was expected */
if (!jtag_examine_chain_match_tap(tap))
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.
+ *
+ * Entry state can be anything. On non-error exit, all TAPs are in
+ * bypass mode. On error exits, the scan chain is reset.
+ */
+static int jtag_validate_ircapture(void)
{
jtag_tap_t *tap;
int total_ir_length = 0;
uint8_t *ir_test = NULL;
scan_field_t field;
+ int val;
int chain_pos = 0;
+ int retval;
- tap = NULL;
- total_ir_length = 0;
- for (;;) {
- tap = jtag_tap_next_enabled(tap);
- if (tap == NULL) {
- break;
- }
- total_ir_length += tap->ir_length;
- }
+ for (tap = NULL, total_ir_length = 0;
+ (tap = jtag_tap_next_enabled(tap)) != NULL;
+ total_ir_length += tap->ir_length)
+ continue;
+ /* increase length to add 2 bit sentinel after scan */
total_ir_length += 2;
+
ir_test = malloc(CEIL(total_ir_length, 8));
+ if (ir_test == NULL)
+ return ERROR_FAIL;
+
+ /* after this scan, all TAPs will capture BYPASS instructions */
buf_set_ones(ir_test, total_ir_length);
field.tap = NULL;
field.out_value = ir_test;
field.in_value = ir_test;
+ jtag_add_plain_ir_scan(1, &field, TAP_IDLE);
- jtag_add_plain_ir_scan(1, &field, TAP_IRPAUSE);
- jtag_add_tlr();
-
- int retval;
+ LOG_DEBUG("IR capture validation scan");
retval = jtag_execute_queue();
if (retval != ERROR_OK)
- return retval;
+ goto done;
tap = NULL;
chain_pos = 0;
- int val;
+
for (;;) {
tap = jtag_tap_next_enabled(tap);
if (tap == NULL) {
break;
}
- 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))
- {
- 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;
+ /* Validate the two LSBs, which must be 01 per JTAG spec.
+ *
+ * Or ... more bits could be provided by TAP declaration.
+ * Plus, some taps (notably in i.MX series chips) violate
+ * this part of the JTAG spec, so their capture mask/value
+ * attributes might disable this test.
+ */
+ val = buf_get_u32(ir_test, chain_pos, tap->ir_length);
+ if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
+ LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x%0*x",
+ jtag_tap_name(tap),
+ (tap->ir_length + 7) / tap->ir_length,
+ val,
+ (tap->ir_length + 7) / tap->ir_length,
+ tap->ir_capture_value);
+
+ retval = ERROR_JTAG_INIT_FAILED;
+ goto done;
}
+ LOG_DEBUG("%s: IR capture 0x%0*x", jtag_tap_name(tap),
+ (tap->ir_length + 7) / tap->ir_length, val);
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;
+ retval = ERROR_JTAG_INIT_FAILED;
}
+done:
free(ir_test);
-
- return ERROR_OK;
+ if (retval != ERROR_OK) {
+ jtag_add_tlr();
+ jtag_execute_queue();
+ }
+ return retval;
}
{
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);
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);
}
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);
return ERROR_OK;
}
-static int jtag_init_inner(struct command_context_s *cmd_ctx)
+int jtag_init_inner(struct command_context_s *cmd_ctx)
{
jtag_tap_t *tap;
int retval;
+ bool issue_setup = true;
LOG_DEBUG("Init JTAG chain");
/* examine chain first, as this could discover the real chain layout */
if (jtag_examine_chain() != ERROR_OK)
{
- LOG_ERROR("trying to validate configured JTAG chain anyway...");
+ LOG_ERROR("Trying to use configured scan chain anyway...");
+ issue_setup = false;
}
- 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...");
+ issue_setup = false;
}
+ if (issue_setup)
+ jtag_notify_event(JTAG_TAP_EVENT_SETUP);
+ else
+ LOG_WARNING("Bypassing JTAG setup events due to errors");
+
+
return ERROR_OK;
}
int jtag_init(struct command_context_s *cmd_ctx)
{
int retval;
+
if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
return retval;
- if (jtag_init_inner(cmd_ctx) == ERROR_OK)
- {
- return ERROR_OK;
- }
- return jtag_init_reset(cmd_ctx);
+
+ /* guard against oddball hardware: force resets to be inactive */
+ jtag_add_reset(0, 0);
+ if ((retval = jtag_execute_queue()) != ERROR_OK)
+ return retval;
+
+ if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
+ return ERROR_FAIL;
+
+ return ERROR_OK;
}
unsigned jtag_get_speed_khz(void)
{
return jtag_ntrst_delay;
}
+
+
+void jtag_set_nsrst_assert_width(unsigned delay)
+{
+ jtag_nsrst_assert_width = delay;
+}
+unsigned jtag_get_nsrst_assert_width(void)
+{
+ return jtag_nsrst_assert_width;
+}
+void jtag_set_ntrst_assert_width(unsigned delay)
+{
+ jtag_ntrst_assert_width = delay;
+}
+unsigned jtag_get_ntrst_assert_width(void)
+{
+ return jtag_ntrst_assert_width;
+}