Include assert.h in system.h to promote tree-wide use of assertions.
[fw/openocd] / src / xsvf / xsvf.c
index 17dec493891b8c75392ac82a5e5a185cc2dd11ae..2400ae39a5e67c95f071e6b0e1be09f6e9243e5c 100644 (file)
 #endif
 
 #include "xsvf.h"
-
 #include "jtag.h"
-#include "command.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <assert.h>
-
-#include <sys/time.h>
-#include <time.h>
 
 
 /* XSVF commands, from appendix B of xapp503.pdf  */
@@ -177,13 +163,13 @@ static tap_state_t xsvf_to_tap( int xsvf_state )
 /**
  * Function xsvf_add_statemove
  * moves from the current state to the goal \a state. This needs
- * to be handled according to the xsvf spec, which has nothing
- * to do with the JTAG spec or OpenOCD as such.
- *
- * Implemented via jtag_add_pathmove().
+ * to be handled according to the xsvf spec, see the XSTATE command
+ * description.
  */
-static void xsvf_add_statemove(tap_state_t goal_state)
+static int xsvf_add_statemove(tap_state_t goal_state)
 {
+       int retval = ERROR_OK;
+
        tap_state_t moves[8];
        tap_state_t cur_state = cmd_queue_cur_state;
        int i;
@@ -194,29 +180,69 @@ static void xsvf_add_statemove(tap_state_t goal_state)
                tap_state_name(cur_state),
                tap_state_name(goal_state) );
 
+
+       /*      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.
+       */
+
        if (goal_state==cur_state )
-               return;
+               ;       /* nothing to do */
 
-       if( goal_state==TAP_RESET )
+       else if( goal_state==TAP_RESET )
        {
                jtag_add_tlr();
-               return;
        }
 
-       tms_bits  = tap_get_tms_path(cur_state, goal_state);
-       tms_count = tap_get_tms_path_len(cur_state, goal_state);
+       else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) )
+       {
+               /*      note: unless tms_bits holds a path that agrees with [Ref 5] in 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.
+               */
+
+               tms_bits  = tap_get_tms_path(cur_state, goal_state);
+               tms_count = tap_get_tms_path_len(cur_state, goal_state);
+
+               assert( (unsigned) tms_count < DIM(moves) );
+
+               for (i=0;   i<tms_count;   i++, tms_bits>>=1)
+               {
+                       bool bit = tms_bits & 1;
+
+                       cur_state = tap_state_transition(cur_state, bit);
+                       moves[i] = cur_state;
+               }
 
-       assert( (unsigned) tms_count < DIM(moves) );
+               jtag_add_pathmove(tms_count, moves);
+       }
 
-       for (i=0;   i<tms_count;   i++, tms_bits>>=1)
+       /*      else state must be immediately reachable in one clock cycle, and does not
+               need to be a stable state.
+       */
+       else if( tap_state_transition(cur_state, true)  == goal_state
+               ||   tap_state_transition(cur_state, false) == goal_state )
        {
-               bool bit = tms_bits & 1;
+               /* move a single state */
+               moves[0] = goal_state;
+               jtag_add_pathmove( 1, moves );
+       }
 
-               cur_state = tap_state_transition(cur_state, bit);
-               moves[i] = cur_state;
+       else
+       {
+               retval = ERROR_FAIL;
        }
 
-       jtag_add_pathmove(tms_count, moves);
+       return retval;
 }
 
 
@@ -461,16 +487,18 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
                                        field.tap = tap;
                                        field.num_bits = xsdrsize;
                                        field.out_value = dr_out_buf;
-                                       
-                                       field.in_value = NULL;
-
-                                       jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
+                                       field.in_value = calloc(CEIL(field.num_bits, 8), 1);
 
                                        if (tap == NULL)
                                                jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
                                        else
                                                jtag_add_dr_scan(1, &field, TAP_DRPAUSE);
 
+                                       jtag_check_value_mask(&field, dr_in_buf, dr_in_mask);
+
+                                       free(field.in_value);
+
+
                                        /* LOG_DEBUG("FLUSHING QUEUE"); */
                                        result = jtag_execute_queue();
                                        if (result == ERROR_OK)
@@ -557,7 +585,32 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
 
                                LOG_DEBUG("XSTATE 0x%02X %s", uc, tap_state_name(mystate) );
 
-                               xsvf_add_statemove( 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.
+                               */
+
+                               if( xsvf_add_statemove( mystate ) != ERROR_OK )
+                               {
+                                       /*      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)
+                                               );
+                               }
                        }
                        break;
 
@@ -648,11 +701,11 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
                                        field.tap = tap;
                                        field.num_bits = bitcount;
                                        field.out_value = ir_buf;
-                                       
+
                                        field.in_value = NULL;
+
+
                                        
-                                       
-                                       field.in_handler = NULL;
 
                                        if (tap == NULL)
                                                jtag_add_plain_ir_scan(1, &field, my_end_state);
@@ -703,7 +756,7 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
 
                                comment[sizeof(comment)-1] = 0;         /* regardless, terminate */
                                if (verbose)
-                                       LOG_USER("\"# %s\"", comment);
+                                       LOG_USER("# %s", comment);
                        }
                        break;
 
@@ -879,18 +932,21 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
                                        field.tap = tap;
                                        field.num_bits = xsdrsize;
                                        field.out_value = dr_out_buf;
-                                       
-                                       field.in_value = NULL;
+                                       field.in_value = calloc(CEIL(field.num_bits, 8), 1);
 
                                        if (attempt > 0 && verbose)
                                                LOG_USER("LSDR retry %d", attempt);
 
-                                       jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
                                        if (tap == NULL)
                                                jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
                                        else
                                                jtag_add_dr_scan(1, &field, TAP_DRPAUSE);
 
+                                       jtag_check_value_mask(&field, dr_in_buf, dr_in_mask);
+
+                                       free(field.in_value);
+
+
                                        /* LOG_DEBUG("FLUSHING QUEUE"); */
                                        result = jtag_execute_queue();
                                        if(result == ERROR_OK)