XSVF: bugfix handling state paths
authorDavid Brownell <dbrownell@users.sourceforge.net>
Thu, 29 Oct 2009 19:42:41 +0000 (12:42 -0700)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Thu, 29 Oct 2009 19:42:41 +0000 (12:42 -0700)
Implement XSVF support for detailed state path transitions,
by collecting sequences of XSTATE transitions into paths
and then calling pathmove().

It seems that the Xilinx tools want to force state-by-state
transitions instead of relying on the standardized SVF paths.
Like maybe there are XSVF tools not implementing SVF paths,
which are all that we support using svf_statemove().

So from IRPAUSE, instead of just issuing "XSTATE DRPAUSE"
they will issue XSTATES for each intermediate state: first
IREXIT2, then IRUPDATE, DRSELECT, DRCAPTURE, DREXIT1, and
finally DRPAUSE.  This works now.

Handling of paths that go *through* reset is a trifle dodgey,
but it should be safe.

Tested-by: Wookey <wookey@wookware.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/xsvf/xsvf.c

index d00c47c6dd55d69b32fe27da2d1756bf8c64bfb8..719470ee0d79d37aee4a13282b516d0c2266298b 100644 (file)
@@ -211,9 +211,16 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
        int             tdo_mismatch = 0;
        int             result;
        int             verbose = 1;
-       char*   filename;
+       char            *filename;
 
-       int             runtest_requires_tck = 0;       /* a flag telling whether to clock TCK during waits, or simply sleep, controled by virt2 */
+       bool            collecting_path = false;
+       tap_state_t     path[XSTATE_MAX_PATH];
+       unsigned        pathlen = 0;
+
+       /* a flag telling whether to clock TCK during waits,
+        * or simply sleep, controled by virt2
+        */
+       int             runtest_requires_tck = 0;
 
 
        /* use NULL to indicate a "plain" xsvf file which accounts for
@@ -263,9 +270,88 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
 
        while (read(xsvf_fd, &opcode, 1) > 0)
        {
-               /* record the position of the just read opcode within the file */
+               /* record the position of this opcode within the file */
                file_offset = lseek(xsvf_fd, 0, SEEK_CUR) - 1;
 
+               /* maybe collect another state for a pathmove();
+                * or terminate a path.
+                */
+               if (collecting_path) {
+                       tap_state_t     mystate;
+                       uint8_t         uc;
+
+                       switch (opcode) {
+                       case XCOMMENT:
+                               /* ignore/show comments between XSTATE ops */
+                               break;
+                       case XSTATE:
+                               /* try to collect another transition */
+                               if (pathlen == XSTATE_MAX_PATH) {
+                                       LOG_ERROR("XSVF: path too long");
+                                       do_abort = 1;
+                                       break;
+                               }
+
+                               if (read(xsvf_fd, &uc, 1) < 0)
+                               {
+                                       do_abort = 1;
+                                       break;
+                               }
+
+                               mystate = xsvf_to_tap(uc);
+                               path[pathlen++] = mystate;
+
+                               LOG_DEBUG("XSTATE 0x%02X %s", uc,
+                                               tap_state_name(mystate));
+
+                               /* If path is incomplete, collect more */
+                               if (!svf_tap_state_is_stable(mystate))
+                                       continue;
+
+                               /* Else execute the path transitions we've
+                                * collected so far.
+                                *
+                                * NOTE:  Punting on the saved path is not
+                                * strictly correct, but we must to do this
+                                * unless jtag_add_pathmove() stops rejecting
+                                * paths containing RESET.  This is probably
+                                * harmless, since there aren't many options
+                                * for going from a stable state to reset;
+                                * at the worst, we may issue extra clocks
+                                * once we get to RESET.
+                                */
+                               if (mystate == TAP_RESET) {
+                                       LOG_WARNING("XSVF: dodgey RESET");
+                                       path[0] = mystate;
+                               }
+
+                               /* FALL THROUGH */
+                       default:
+                               /* Execute the path we collected
+                                *
+                                * NOTE: OpenOCD requires something that XSVF
+                                * doesn't:  the last TAP state in the path
+                                * must be stable.  In practice, tools that
+                                * create XSVF seem to follow that rule too.
+                                */
+                               collecting_path = false;
+
+                               if (path[0] == TAP_RESET)
+                                       jtag_add_tlr();
+                               else
+                                       jtag_add_pathmove(pathlen, path);
+
+                               result = jtag_get_error();
+                               if (result != ERROR_OK) {
+                                       LOG_ERROR("XSVF: pathmove error %d",
+                                                       result);
+                                       do_abort = 1;
+                                       break;
+                               }
+                               continue;
+                       }
+               }
+
                switch (opcode)
                {
                case XCOMPLETE:
@@ -500,6 +586,12 @@ 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));
 
+                               if (mystate == TAP_INVALID) {
+                                       LOG_ERROR("XSVF: bad XSTATE %02x", uc);
+                                       do_abort = 1;
+                                       break;
+                               }
+
                                /* NOTE: the current state is SVF-stable! */
 
                                /* no change == NOP */
@@ -518,19 +610,12 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
 
                                /*
                                 * 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.
+                                * state adjacent to the previous one.  Start
+                                * collecting them.
                                 */
-                               LOG_ERROR("XSVF: 'XSTATE %s' ... NYET",
-                                               tap_state_name(mystate));
-                               unsupported = 1;
+                               collecting_path = true;
+                               pathlen = 1;
+                               path[0] = mystate;
                        }
                        break;
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)