aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2009-04-24 18:10:04 +0000
committeroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2009-04-24 18:10:04 +0000
commit479a65e946860f754869a82f2d793d64643fb85b (patch)
treecf2a1543248b9ed2339bfced312575d442fad55b
parent447a615dc33f324d44c73b282174be44e876cf41 (diff)
downloadriscv-openocd-479a65e946860f754869a82f2d793d64643fb85b.zip
riscv-openocd-479a65e946860f754869a82f2d793d64643fb85b.tar.gz
riscv-openocd-479a65e946860f754869a82f2d793d64643fb85b.tar.bz2
add jtag_debug_state_machine
git-svn-id: svn://svn.berlios.de/openocd/trunk@1525 b42882b7-edfa-0310-969c-e2dbd0fdcd60
-rw-r--r--src/jtag/jlink.c5
-rw-r--r--src/jtag/jtag.c85
-rw-r--r--src/jtag/jtag.h19
3 files changed, 109 insertions, 0 deletions
diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c
index 1269fa8..36395fd 100644
--- a/src/jtag/jlink.c
+++ b/src/jtag/jlink.c
@@ -114,6 +114,8 @@ static int jlink_get_version_info(void);
static void jlink_debug_buffer(u8 *buffer, int length);
#endif
+static enum tap_state jlink_last_state = TAP_RESET;
+
static jlink_jtag_t* jlink_jtag_handle;
/***************************************************************************/
@@ -681,6 +683,9 @@ static int jlink_tap_execute(void)
memcpy(usb_out_buffer + 4, tms_buffer, byte_length);
memcpy(usb_out_buffer + 4 + byte_length, tdi_buffer, byte_length);
+ jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer,
+ tap_length, jlink_last_state);
+
result = jlink_usb_message(jlink_jtag_handle, 4 + 2 * byte_length, byte_length);
if (result != byte_length)
{
diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c
index 24a8217..408f88f 100644
--- a/src/jtag/jtag.c
+++ b/src/jtag/jtag.c
@@ -3283,4 +3283,89 @@ static tap_state_t tap_state_by_name( const char *name )
return TAP_INVALID;
}
+#ifdef _DEBUG_JTAG_IO_
+
+#define JTAG_DEBUG_STATE_APPEND(buf, len, bit) \
+ do { buf[len] = bit ? '1' : '0'; } while(0)
+#define JTAG_DEBUG_STATE_PRINT(a, b, astr, bstr) \
+ DEBUG_JTAG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \
+ tap_state_name(a), tap_state_name(b), astr, bstr)
+
+tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
+ unsigned tap_bits, tap_state_t next_state)
+{
+ const u8 *tms_buffer;
+ const u8 *tdi_buffer;
+ unsigned tap_bytes;
+ unsigned cur_byte;
+ unsigned cur_bit;
+
+ unsigned tap_out_bits;
+ char tms_str[33];
+ char tdi_str[33];
+
+ tap_state_t last_state;
+
+ // set startstate (and possibly last, if tap_bits == 0)
+ last_state = next_state;
+ DEBUG_JTAG_IO("TAP/SM: START state: %s", tap_state_name(next_state));
+
+ tms_buffer = (const u8 *)tms_buf;
+ tdi_buffer = (const u8 *)tdi_buf;
+
+ tap_bytes = TAP_SCAN_BYTES(tap_bits);
+ DEBUG_JTAG_IO("TAP/SM: TMS bits: %u (bytes: %u)", tap_bits, tap_bytes);
+
+ tap_out_bits = 0;
+ for(cur_byte = 0; cur_byte < tap_bytes; cur_byte++)
+ {
+ for(cur_bit = 0; cur_bit < 8; cur_bit++)
+ {
+ // make sure we do not run off the end of the buffers
+ unsigned tap_bit = cur_byte * 8 + cur_bit;
+ if (tap_bit == tap_bits)
+ break;
+
+ // check and save TMS bit
+ tap_bit = !!(tms_buffer[cur_byte] & (1 << cur_bit));
+ JTAG_DEBUG_STATE_APPEND(tms_str, tap_out_bits, tap_bit);
+
+ // use TMS bit to find the next TAP state
+ next_state = tap_state_transition(last_state, tap_bit);
+
+ // check and store TDI bit
+ tap_bit = !!(tdi_buffer[cur_byte] & (1 << cur_bit));
+ JTAG_DEBUG_STATE_APPEND(tdi_str, tap_out_bits, tap_bit);
+
+ // increment TAP bits
+ tap_out_bits++;
+
+ // Only show TDO bits on state transitions, or
+ // after some number of bits in the same state.
+ if ((next_state == last_state) && (tap_out_bits < 32))
+ continue;
+
+ // terminate strings and display state transition
+ tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
+ JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
+
+ // reset state
+ last_state = next_state;
+ tap_out_bits = 0;
+ }
+ }
+
+ if (tap_out_bits)
+ {
+ // terminate strings and display state transition
+ tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
+ JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
+ }
+
+ DEBUG_JTAG_IO("TAP/SM: FINAL state: %s", tap_state_name(next_state));
+
+ return next_state;
+}
+#endif // _DEBUG_JTAG_IO_
+
/*-----</Cable Helper API>--------------------------------------*/
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index a14edb4..f418b73 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -206,6 +206,25 @@ tap_state_t tap_state_transition(tap_state_t current_state, bool tms);
*/
const char* tap_state_name(tap_state_t state);
+#ifdef _DEBUG_JTAG_IO_
+/**
+ * @brief Prints verbose TAP state transitions for the given TMS/TDI buffers.
+ * @param tms_buf must points to a buffer containing the TMS bitstream.
+ * @param tdi_buf must points to a buffer containing the TDI bitstream.
+ * @param tap_len must specify the length of the TMS/TDI bitstreams.
+ * @param start_tap_state must specify the current TAP state.
+ * @returns the final TAP state; pass as @a start_tap_state in following call.
+ */
+tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
+ unsigned tap_len, tap_state_t start_tap_state);
+#else
+static inline tap_state_t jtag_debug_state_machine(const void *tms_buf,
+ const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state)
+{
+ return start_tap_state;
+}
+#endif // _DEBUG_JTAG_IO_
+
/*-----</Cable Helper API>------------------------------------------*/