summaryrefslogtreecommitdiff
path: root/src/xsvf
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-10-29 12:42:41 -0700
committerDavid Brownell <dbrownell@users.sourceforge.net>2009-10-29 12:42:41 -0700
commit0c4d5b8b1f8da402a1de675ad4c2d479edf372b8 (patch)
tree6fc34da265ab7a075d71387bc99ddde68035cedd /src/xsvf
parentb628207ea6dd39280ebdd8b66a1ac869350c6d00 (diff)
downloadopenocd+libswd-0c4d5b8b1f8da402a1de675ad4c2d479edf372b8.tar.gz
openocd+libswd-0c4d5b8b1f8da402a1de675ad4c2d479edf372b8.tar.bz2
openocd+libswd-0c4d5b8b1f8da402a1de675ad4c2d479edf372b8.tar.xz
openocd+libswd-0c4d5b8b1f8da402a1de675ad4c2d479edf372b8.zip
XSVF: bugfix handling state paths
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>
Diffstat (limited to 'src/xsvf')
-rw-r--r--src/xsvf/xsvf.c115
1 files changed, 100 insertions, 15 deletions
diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c
index d00c47c6..719470ee 100644
--- a/src/xsvf/xsvf.c
+++ b/src/xsvf/xsvf.c
@@ -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;