return temp;
}
+/************/
+
+static bool jtag_poll = 1;
+
+bool is_jtag_poll_safe(void)
+{
+ /* Polling can be disabled explicitly with set_enabled(false).
+ * It is also implicitly disabled while TRST is active and
+ * while SRST is gating the JTAG clock.
+ */
+ if (!jtag_poll || jtag_trst != 0)
+ return false;
+ return jtag_srst == 0 || (jtag_reset_config & RESET_SRST_NO_GATING);
+}
+
+bool jtag_poll_get_enabled(void)
+{
+ return jtag_poll;
+}
+
+void jtag_poll_set_enabled(bool value)
+{
+ jtag_poll = value;
+}
+
+/************/
jtag_tap_t *jtag_all_taps(void)
{
tap_state_name(goal_state));
- if (goal_state == cur_state)
- ; /* nothing to do */
- else if (goal_state == TAP_RESET)
- {
+ /* If goal is RESET, be paranoid and force that that transition
+ * (e.g. five TCK cycles, TMS high). Else trust "cur_state".
+ */
+ if (goal_state == TAP_RESET)
jtag_add_tlr();
- }
+ else if (goal_state == cur_state)
+ /* nothing to do */ ;
+
else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state))
{
unsigned tms_bits = tap_get_tms_path(cur_state, goal_state);
for (; count < max - 31; count += 32)
{
uint32_t idcode = buf_get_u32(idcodes, count, 32);
- // do not trigger the warning if the data looks good
- if (!triggered && jtag_idcode_is_final(idcode))
+
+ /* do not trigger the warning if the data looks good */
+ if (jtag_idcode_is_final(idcode))
continue;
LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
count, (unsigned int)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++)
+ unsigned ii, limit = tap->expected_ids_cnt;
+
+ for (ii = 0; ii < limit; ii++)
{
if (tap->idcode == tap->expected_ids[ii])
return true;
/* 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++)
+ for (ii = 0; ii < limit; ii++)
{
char msg[32];
- snprintf(msg, sizeof(msg), "expected %hhu of %hhu",
- ii + 1, tap->expected_ids_cnt);
+
+ snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, limit);
jtag_examine_chain_display(LOG_LVL_ERROR, msg,
tap->dotted_name, tap->expected_ids[ii]);
}
/* DR scan to collect BYPASS or IDCODE register contents.
* Then make sure the scan data has both ones and zeroes.
*/
+ LOG_DEBUG("DR scan interrogation for IDCODE/BYPASS");
retval = jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
if (retval != ERROR_OK)
return retval;
(tap->ir_length + 7) / tap->ir_length,
val,
(tap->ir_length + 7) / tap->ir_length,
- tap->ir_capture_value);
+ (unsigned) tap->ir_capture_value);
retval = ERROR_JTAG_INIT_FAILED;
goto done;
void jtag_tap_init(jtag_tap_t *tap)
{
+ unsigned ir_len_bits;
+ unsigned ir_len_bytes;
+
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);
+ ir_len_bits = tap->ir_length;
+ ir_len_bytes = CEIL(ir_len_bits, 8);
- /// @todo cope sanely with ir_length bigger than 32 bits
- buf_set_u32(tap->expected, 0, tap->ir_length, tap->ir_capture_value);
- buf_set_u32(tap->expected_mask, 0, tap->ir_length, tap->ir_capture_mask);
- buf_set_ones(tap->cur_instr, tap->ir_length);
+ tap->expected = calloc(1, ir_len_bytes);
+ tap->expected_mask = calloc(1, ir_len_bytes);
+ tap->cur_instr = malloc(ir_len_bytes);
+
+ /// @todo cope better with ir_length bigger than 32 bits
+ if (ir_len_bits > 32)
+ ir_len_bits = 32;
- // place TAP in bypass mode
+ buf_set_u32(tap->expected, 0, ir_len_bits, tap->ir_capture_value);
+ buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask);
+
+ // TAP will be in bypass mode after jtag_validate_ircapture()
tap->bypass = 1;
+ buf_set_ones(tap->cur_instr, tap->ir_length);
+
// register the reset callback for the TAP
jtag_register_event_callback(&jtag_reset_callback, tap);
if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
return retval;
- LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / TLR");
+ LOG_DEBUG("Initializing with hard TRST+SRST reset");
- /* Reset can happen after a power cycle.
- *
- * Ideally we would only assert TRST or run TLR before the target reset.
+ /*
+ * This procedure is used by default when OpenOCD triggers a reset.
+ * It's now done through an overridable Tcl "init_reset" wrapper.
*
- * However w/srst_pulls_trst, trst is asserted together with the target
- * reset whether we want it or not.
+ * This started out as a more powerful "get JTAG working" reset than
+ * jtag_init_inner(), applying TRST because some chips won't activate
+ * JTAG without a TRST cycle (presumed to be async, though some of
+ * those chips synchronize JTAG activation using TCK).
*
- * NB! Some targets have JTAG circuitry disabled until a
- * trst & srst has been asserted.
+ * But some chips only activate JTAG as part of an SRST cycle; SRST
+ * got mixed in. So it became a hard reset routine, which got used
+ * in more places, and which coped with JTAG reset being forced as
+ * part of SRST (srst_pulls_trst).
*
- * NB! here we assume nsrst/ntrst delay are sufficient!
+ * And even more corner cases started to surface: TRST and/or SRST
+ * assertion timings matter; some chips need other JTAG operations;
+ * TRST/SRST sequences can need to be different from these, etc.
*
- * NB! order matters!!!! srst *can* disconnect JTAG circuitry
+ * Systems should override that wrapper to support system-specific
+ * requirements that this not-fully-generic code doesn't handle.
*
+ * REVISIT once Tcl code can read the reset_config modes, this won't
+ * need to be a C routine at all...
*/
jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */
if (jtag_reset_config & RESET_HAS_SRST)