From 479a65e946860f754869a82f2d793d64643fb85b Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 24 Apr 2009 18:10:04 +0000 Subject: [PATCH] add jtag_debug_state_machine git-svn-id: svn://svn.berlios.de/openocd/trunk@1525 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/jtag/jlink.c | 5 +++ src/jtag/jtag.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ src/jtag/jtag.h | 19 +++++++++++ 3 files changed, 109 insertions(+) diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c index 1269fa846..36395fd82 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 24a8217d4..408f88fa5 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_ + /*-------------------------------------------*/ diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index a14edb481..f418b7310 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_ + /*-----------------------------------------------*/