@deffn Command {pathmove} start_state [next_state ...]
Start by moving to @var{start_state}, which
must be one of the @emph{stable} states.
+Unless it is the only state given, this will often be the
+current state, so that no TCK transitions are needed.
Then, in a series of single state transitions
(conforming to the JTAG state machine) shift to
each @var{next_state} in sequence, one per TCK cycle.
The @var{tap_state} names used by OpenOCD in the @command{drscan},
@command{irscan}, and @command{pathmove} commands are the same
-as those used in SVF boundary scan documents, except that some
-versions of SVF use @sc{idle} instead of @sc{run/idle}.
+as those used in SVF boundary scan documents, except that
+SVF uses @sc{idle} instead of @sc{run/idle}.
@itemize @bullet
@item @b{RESET} ... @emph{stable} (with TMS high);
messages are logged for comments and some retries.
@end deffn
+The OpenOCD sources also include two utility scripts
+for working with XSVF; they are not currently installed
+after building the software.
+You may find them useful:
+
+@itemize
+@item @emph{svf2xsvf} ... converts SVF files into the extended XSVF
+syntax understood by the @command{xsvf} command; see notes below.
+@item @emph{xsvfdump} ... converts XSVF files into a text output format;
+understands the OpenOCD extensions.
+@end itemize
+
+The input format accepts a handful of non-standard extensions.
+These include three opcodes corresponding to SVF extensions
+from Lattice Semiconductor (LCOUNT, LDELAY, LDSR), and
+two opcodes supporting a more accurate translation of SVF
+(XTRST, XWAITSTATE).
+If @emph{xsvfdump} shows a file is using those opcodes, it
+probably will not be usable with other XSVF tools.
+
+
@node TFTP
@chapter TFTP
@cindex TFTP
* @return ERROR_OK on success, or an error code on failure.
*
* Moves from the current state to the goal \a state.
- *
- * This needs to be handled according to the xsvf spec, see the XSTATE
- * command description. From the XSVF spec, pertaining to XSTATE:
- *
- * For special states known as stable states (Test-Logic-Reset,
- * Run-Test/Idle, Pause-DR, Pause- IR), an XSVF interpreter follows
- * predefined TAP state paths when the starting state is a stable state
- * and when the XSTATE specifies a new stable state. See the STATE
- * command in the [Ref 5] for the TAP state paths between stable
- * states.
- *
- * For non-stable states, XSTATE should specify a state that is only one
- * TAP state transition distance from the current TAP state to avoid
- * undefined TAP state paths. A sequence of multiple XSTATE commands can
- * be issued to transition the TAP through a specific state path.
- *
- * @note Unless @c tms_bits holds a path that agrees with [Ref 5] in the
- * above spec, then this code is not fully conformant to the xsvf spec.
- * This puts a burden on tap_get_tms_path() function from the xsvf spec.
- * If in doubt, you should confirm that that burden is being met.
- *
- * Otherwise, @a goal_state must be immediately reachable in one clock
- * cycle, and does not need to be a stable state.
+ * Both states must be stable.
*/
extern int jtag_add_statemove(tap_state_t goal_state);
#include "config.h"
#endif
-#include "svf.h"
#include "jtag.h"
+#include "svf.h"
#include "time_support.h"
return ret;
}
-static int svf_add_statemove(tap_state_t state_to)
+int svf_add_statemove(tap_state_t state_to)
{
tap_state_t state_from = cmd_queue_cur_state;
uint8_t index;
return ERROR_OK;
}
-static int svf_tap_state_is_stable(tap_state_t state)
+bool svf_tap_state_is_stable(tap_state_t state)
{
- return ((TAP_RESET == state) || (TAP_IDLE == state) || (TAP_DRPAUSE == state) || (TAP_IRPAUSE == state));
+ return (TAP_RESET == state) || (TAP_IDLE == state)
+ || (TAP_DRPAUSE == state) || (TAP_IRPAUSE == state);
}
static int svf_tap_state_is_valid(tap_state_t state)
field.num_bits = i;
field.out_value = &svf_tdi_buffer[svf_buffer_index];
field.in_value = &svf_tdi_buffer[svf_buffer_index];
+ /* NOTE: doesn't use SVF-specified state paths */
jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state);
svf_buffer_index += (i + 7) >> 3;
field.num_bits = i;
field.out_value = &svf_tdi_buffer[svf_buffer_index];
field.in_value = &svf_tdi_buffer[svf_buffer_index];
+ /* NOTE: doesn't use SVF-specified state paths */
jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state);
svf_buffer_index += (i + 7) >> 3;
// run_state and end_state is checked to be stable state
// TODO: do runtest
#if 1
+ /* FIXME handle statemove failures */
+ int retval;
+
// enter into run_state if necessary
if (cmd_queue_cur_state != svf_para.runtest_run_state)
{
- svf_add_statemove(svf_para.runtest_run_state);
+ retval = svf_add_statemove(svf_para.runtest_run_state);
}
// call jtag_add_clocks
// move to end_state if necessary
if (svf_para.runtest_end_state != svf_para.runtest_run_state)
{
- svf_add_statemove(svf_para.runtest_end_state);
+ retval = svf_add_statemove(svf_para.runtest_end_state);
}
#else
if (svf_para.runtest_run_state != TAP_IDLE)
free(path);
return ERROR_FAIL;
}
+ /* OpenOCD refuses paths containing TAP_RESET */
if (TAP_RESET == path[i])
{
+ /* FIXME last state MUST be stable! */
if (i > 0)
{
jtag_add_pathmove(i, path);
state = svf_find_string_in_array(argus[1], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
if (svf_tap_state_is_stable(state))
{
- // TODO: move to state
+ LOG_DEBUG("\tmove to %s by svf_add_statemove",
+ svf_tap_state_name[state]);
+ /* FIXME handle statemove failures */
svf_add_statemove(state);
-
- LOG_DEBUG("\tmove to %s by svf_add_statemove", svf_tap_state_name[state]);
}
else
{
extern int svf_register_commands(struct command_context_s *cmd_ctx);
+/**
+ * svf_add_statemove() moves from the current state to @a goal_state.
+ *
+ * @param goal_state The final TAP state.
+ * @return ERROR_OK on success, or an error code on failure.
+ *
+ * The current and goal states must satisfy svf_tap_state_is_stable().
+ * State transition paths used by this routine are those given in the
+ * SVF specification for single-argument STATE commands (and also used
+ * for various other state transitions).
+ */
+extern int svf_add_statemove(tap_state_t goal_state);
+
+/**
+ * svf_tap_state_is_stable() returns true for stable non-SHIFT states
+ *
+ * @param state The TAP state in question
+ * @return true iff the state is stable and not a SHIFT state.
+ */
+extern bool svf_tap_state_is_stable(tap_state_t state);
+
#endif /* SVF_H */
AM_CPPFLAGS = \
-I$(top_srcdir)/src/server \
-I$(top_srcdir)/src/helper \
+ -I$(top_srcdir)/src/svf \
-I$(top_srcdir)/src/jtag
METASOURCES = AUTO
#include "xsvf.h"
#include "jtag.h"
+#include "svf.h"
/* XSVF commands, from appendix B of xapp503.pdf */
/* See page 19 of XSVF spec regarding opcode "XSDR" */
if (xruntest)
{
- jtag_add_statemove(TAP_IDLE);
+ result = svf_add_statemove(TAP_IDLE);
if (runtest_requires_tck)
jtag_add_clocks(xruntest);
jtag_add_sleep(xruntest);
}
else if (xendir != TAP_DRPAUSE) /* we are already in TAP_DRPAUSE */
- jtag_add_statemove(xenddr);
+ result = svf_add_statemove(xenddr);
}
break;
LOG_DEBUG("XSTATE 0x%02X %s", uc, tap_state_name(mystate));
- /* there is no need for the lookahead code that was here since we
- queue up the jtag commands anyway. This is a simple way to handle
- the XSTATE.
- */
+ /* NOTE: the current state is SVF-stable! */
+
+ /* no change == NOP */
+ if (mystate == cmd_queue_cur_state
+ && mystate != TAP_RESET)
+ break;
- if (jtag_add_statemove(mystate) != ERROR_OK)
+ /* Hand off to SVF? */
+ if (svf_tap_state_is_stable(mystate))
{
- /* For special states known as stable states
- (Test-Logic-Reset, Run-Test/Idle, Pause-DR, Pause- IR),
- an XSVF interpreter follows predefined TAP state paths
- when the starting state is a stable state and when the
- XSTATE specifies a new stable state (see the STATE
- command in the [Ref 5] for the TAP state paths between
- stable states). For non-stable states, XSTATE should
- specify a state that is only one TAP state transition
- distance from the current TAP state to avoid undefined
- TAP state paths. A sequence of multiple XSTATE commands
- can be issued to transition the TAP through a specific
- state path.
- */
-
- LOG_ERROR("XSTATE %s is not reachable from current state %s in one clock cycle",
- tap_state_name(mystate),
- tap_state_name(cmd_queue_cur_state)
-);
+ result = svf_add_statemove(mystate);
+ if (result != ERROR_OK)
+ unsupported = 1;
+ break;
}
+
+ /*
+ * A sequence of XSTATE transitions, each TAP
+ * state adjacent to the previous one.
+ *
+ * NOTE: OpenOCD requires something that XSVF
+ * doesn't: the last TAP state in the path
+ * must be stable.
+ *
+ * FIXME Implement path collection; submit via
+ * jtag_add_pathmove() after teaching it to
+ * report errors.
+ */
+ LOG_ERROR("XSVF: 'XSTATE %s' ... NYET",
+ tap_state_name(mystate));
+ unsupported = 1;
}
break;
}
else
{
- jtag_add_statemove(wait_state);
+ /* FIXME handle statemove errors ... */
+ result = svf_add_statemove(wait_state);
jtag_add_sleep(delay);
- jtag_add_statemove(end_state);
+ result = svf_add_statemove(end_state);
}
}
break;
* be issuing a number of clocks in this state. This set of allowed states is also
* determined by the SVF RUNTEST command's allowed states.
*/
- if (wait_state != TAP_IRPAUSE && wait_state != TAP_DRPAUSE && wait_state != TAP_RESET && wait_state != TAP_IDLE)
+ if (!svf_tap_state_is_stable(wait_state))
{
- LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"", tap_state_name(wait_state));
+ LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"",
+ tap_state_name(wait_state));
unsupported = 1;
+ /* REVISIT "break" so we won't run? */
}
- jtag_add_statemove(wait_state);
+ /* FIXME handle statemove errors ... */
+ result = svf_add_statemove(wait_state);
jtag_add_clocks(clock_count);
jtag_add_sleep(usecs);
- jtag_add_statemove(end_state);
+ result = svf_add_statemove(end_state);
}
break;
break;
}
+ /* NOTE: loop_state must be stable! */
loop_state = xsvf_to_tap(state);
loop_clocks = be_to_h_u32(clock_buf);
loop_usecs = be_to_h_u32(usecs_buf);
{
scan_field_t field;
- jtag_add_statemove(loop_state);
+ result = svf_add_statemove(loop_state);
jtag_add_clocks(loop_clocks);
jtag_add_sleep(loop_usecs);
LOG_DEBUG("xsvf failed, setting taps to reasonable state");
/* upon error, return the TAPs to a reasonable state */
- jtag_add_statemove(TAP_IDLE);
- jtag_execute_queue();
+ result = svf_add_statemove(TAP_IDLE);
+ result = jtag_execute_queue();
break;
}
}