XSVF: use svf_add_statemove()
[openocd.git] / src / svf / svf.c
index be2ae5a56a48a1487663bfac7d11d65ad7bcb9a8..dfbbde4bec03fa648518395dd801db43ba21b241 100644 (file)
@@ -1,22 +1,21 @@
-/***************************************************************************
- *      Copyright (C) 2009 by Simon Qian                                                                          *
- *      SimonQian@SimonQian.com                                                                                           *
- *                                                                         *
- *      This program is free software; you can redistribute it and/or modify  *
- *      it under the terms of the GNU General Public License as published by  *
- *      the Free Software Foundation; either version 2 of the License, or         *
- *      (at your option) any later version.                                                               *
- *                                                                                                                                                *
- *      This program is distributed in the hope that it will be useful,           *
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of            *
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
- *      GNU General Public License for more details.                                              *
- *                                                                                                                                                *
- *      You should have received a copy of the GNU General Public License         *
- *      along with this program; if not, write to the                                             *
- *      Free Software Foundation, Inc.,                                                                           *
- *      59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                         *
- ***************************************************************************/
+/*
+ * Copyright (C) 2009 by Simon Qian
+ * SimonQian@SimonQian.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
 
 
 /* The specification for SVF is available here:
@@ -32,8 +31,8 @@
 #include "config.h"
 #endif
 
-#include "svf.h"
 #include "jtag.h"
+#include "svf.h"
 #include "time_support.h"
 
 
@@ -98,24 +97,39 @@ typedef struct
        tap_state_t paths[8];
 }svf_statemove_t;
 
-svf_statemove_t svf_statemoves[] = 
+/*
+ * These paths are from the SVF specification for the STATE command, to be
+ * used when the STATE command only includes the final state.  The first
+ * element of the path is the "from" (current) state, and the last one is
+ * the "to" (target) state.
+ *
+ * All specified paths are the shortest ones in the JTAG spec, and are thus
+ * not (!!) exact matches for the paths used elsewhere in OpenOCD.  Note
+ * that PAUSE-to-PAUSE transitions all go through UPDATE and then CAPTURE,
+ * which has specific effects on the various registers; they are not NOPs.
+ *
+ * Paths to RESET are disabled here.  As elsewhere in OpenOCD, and in XSVF
+ * and many SVF implementations, we don't want to risk missing that state.
+ * To get to RESET, always we ignore the current state.
+ */
+static const svf_statemove_t svf_statemoves[] =
 {
        // from                 to                              num_of_moves,   paths[8]
 //     {TAP_RESET,             TAP_RESET,              1,                              {TAP_RESET}},
        {TAP_RESET,             TAP_IDLE,               2,                              {TAP_RESET, TAP_IDLE}},
        {TAP_RESET,             TAP_DRPAUSE,    6,                              {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
        {TAP_RESET,             TAP_IRPAUSE,    7,                              {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
-       
+
 //     {TAP_IDLE,              TAP_RESET,              4,                              {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
        {TAP_IDLE,              TAP_IDLE,               1,                              {TAP_IDLE}},
        {TAP_IDLE,              TAP_DRPAUSE,    5,                              {TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
        {TAP_IDLE,              TAP_IRPAUSE,    6,                              {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
-       
+
 //     {TAP_DRPAUSE,   TAP_RESET,              6,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
        {TAP_DRPAUSE,   TAP_IDLE,               4,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE}},
        {TAP_DRPAUSE,   TAP_DRPAUSE,    7,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
        {TAP_DRPAUSE,   TAP_IRPAUSE,    8,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
-       
+
 //     {TAP_IRPAUSE,   TAP_RESET,              6,                              {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
        {TAP_IRPAUSE,   TAP_IDLE,               4,                              {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_IDLE}},
        {TAP_IRPAUSE,   TAP_DRPAUSE,    7,                              {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
@@ -297,35 +311,33 @@ static const char* tap_state_svf_name(tap_state_t state)
        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;
 
+       /* when resetting, be paranoid and ignore current state */
+       if (state_to == TAP_RESET) {
+               jtag_add_tlr();
+               return ERROR_OK;
+       }
+
        for (index = 0; index < dimof(svf_statemoves); index++)
        {
-               if ((svf_statemoves[index].from == state_from) 
+               if ((svf_statemoves[index].from == state_from)
                        && (svf_statemoves[index].to == state_to))
                {
-                       if (TAP_RESET == state_from)
-                       {
-                               jtag_add_tlr();
-                               if (svf_statemoves[index].num_of_moves > 1)
-                               {
-                                       jtag_add_pathmove(svf_statemoves[index].num_of_moves - 1, svf_statemoves[index].paths + 1);
-                               }
-                       }
+                       /* recorded path includes current state ... avoid extra TCKs! */
+                       if (svf_statemoves[index].num_of_moves > 1)
+                               jtag_add_pathmove(svf_statemoves[index].num_of_moves - 1,
+                                               svf_statemoves[index].paths + 1);
                        else
-                       {
-                               if (svf_statemoves[index].num_of_moves > 0)
-                               {
-                                       jtag_add_pathmove(svf_statemoves[index].num_of_moves, svf_statemoves[index].paths);
-                               }
-                       }
+                               jtag_add_pathmove(svf_statemoves[index].num_of_moves,
+                                               svf_statemoves[index].paths);
                        return ERROR_OK;
                }
        }
-       LOG_ERROR("can not move to %s", tap_state_svf_name(state_to));
+       LOG_ERROR("SVF: can not move to %s", tap_state_svf_name(state_to));
        return ERROR_FAIL;
 }
 
@@ -607,9 +619,10 @@ static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_ar
        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)
@@ -655,8 +668,8 @@ static int svf_adjust_array_length(uint8_t **arr, int orig_bit_len, int new_bit_
 
 static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_len, int bit_len)
 {
-       int i, str_len = strlen(str), str_byte_len = (bit_len + 3) >> 2, loop_cnt;
-       uint8_t ch, need_write = 1;
+       int i, str_len = strlen(str), str_hbyte_len = (bit_len + 3) >> 2;
+       uint8_t ch = 0;
 
        if (ERROR_OK != svf_adjust_array_length(bin, orig_bit_len, bit_len))
        {
@@ -664,75 +677,54 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
                return ERROR_FAIL;
        }
 
-       if (str_byte_len > str_len)
-       {
-               loop_cnt = str_byte_len;
-       }
-       else
+       for (i = 0; i < str_hbyte_len; i++)
        {
-               loop_cnt = str_len;
-       }
-
-       for (i = 0; i < loop_cnt; i++)
-       {
-               if (i < str_len)
+               ch = 0;
+               while (str_len > 0)
                {
-                       ch = str[str_len - i - 1];
-                       if ((ch >= '0') && (ch <= '9'))
-                       {
-                               ch = ch - '0';
-                       }
-                       else if ((ch >= 'A') && (ch <= 'F'))
-                       {
-                               ch = ch - 'A' + 10;
-                       }
-                       else
+                       ch = str[--str_len];
+
+                       if (!isblank(ch))
                        {
-                               LOG_ERROR("invalid hex string");
-                               return ERROR_FAIL;
+                               if ((ch >= '0') && (ch <= '9'))
+                               {
+                                       ch = ch - '0';
+                                       break;
+                               }
+                               else if ((ch >= 'A') && (ch <= 'F'))
+                               {
+                                       ch = ch - 'A' + 10;
+                                       break;
+                               }
+                               else
+                               {
+                                       LOG_ERROR("invalid hex string");
+                                       return ERROR_FAIL;
+                               }
                        }
-               }
-               else
-               {
+
                        ch = 0;
                }
 
-               // check valid
-               if (i >= str_byte_len)
+               // write bin
+               if (i % 2)
                {
-                       // all data written, other data should be all '0's and needn't to be written
-                       need_write = 0;
-                       if (ch != 0)
-                       {
-                               LOG_ERROR("value execede length");
-                               return ERROR_FAIL;
-                       }
+                       // MSB
+                       (*bin)[i / 2] |= ch << 4;
                }
-               else if (i == (str_byte_len - 1))
+               else
                {
-                       // last data byte, written if valid
-                       if ((ch & ~((1 << (bit_len - 4 * i)) - 1)) != 0)
-                       {
-                               LOG_ERROR("value execede length");
-                               return ERROR_FAIL;
-                       }
+                       // LSB
+                       (*bin)[i / 2] = 0;
+                       (*bin)[i / 2] |= ch;
                }
+       }
 
-               if (need_write)
-               {
-                       // write bin
-                       if (i % 2)
-                       {
-                               // MSB
-                               (*bin)[i / 2] |= ch << 4;
-                       }
-                       else
-                       {
-                               // LSB
-                               (*bin)[i / 2] = 0;
-                               (*bin)[i / 2] |= ch;
-                       }
-               }
+       // check valid
+       if (str_len > 0 || (ch & ~((1 << (4 - (bit_len % 4))) - 1)) != 0)
+       {
+               LOG_ERROR("value execede length");
+               return ERROR_FAIL;
        }
 
        return ERROR_OK;
@@ -746,7 +738,7 @@ static int svf_check_tdo(void)
        {
                index = svf_check_tdo_para[i].buffer_offset;
                len = svf_check_tdo_para[i].bit_len;
-               if ((svf_check_tdo_para[i].enabled) 
+               if ((svf_check_tdo_para[i].enabled)
                        && buf_cmp_mask(&svf_tdi_buffer[index], &svf_tdo_buffer[index], &svf_mask_buffer[index], len))
                {
                        unsigned bitmask;
@@ -756,11 +748,11 @@ static int svf_check_tdo(void)
                        memcpy(&received, svf_tdi_buffer + index, sizeof(unsigned));
                        memcpy(&expected, svf_tdo_buffer + index, sizeof(unsigned));
                        memcpy(&tapmask, svf_mask_buffer + index, sizeof(unsigned));
-                       LOG_ERROR("tdo check error at line %d", 
+                       LOG_ERROR("tdo check error at line %d",
                                          svf_check_tdo_para[i].line_num);
-                       LOG_ERROR("read = 0x%X, want = 0x%X, mask = 0x%X", 
-                                         received & bitmask, 
-                                         expected & bitmask, 
+                       LOG_ERROR("read = 0x%X, want = 0x%X, mask = 0x%X",
+                                         received & bitmask,
+                                         expected & bitmask,
                                          tapmask & bitmask);
                        return ERROR_FAIL;
                }
@@ -1091,6 +1083,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        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;
@@ -1186,6 +1179,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        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;
@@ -1287,10 +1281,13 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                // 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
@@ -1299,7 +1296,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                // 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)
@@ -1343,10 +1340,13 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                if (!svf_tap_state_is_valid(path[i]))
                                {
                                        LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i]]);
+                                       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);
@@ -1369,6 +1369,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                else
                                {
                                        LOG_ERROR("%s is not valid state", svf_tap_state_name[path[num_of_argu - 1]]);
+                                       free(path);
                                        return ERROR_FAIL;
                                }
                        }
@@ -1385,10 +1386,10 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        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
                        {

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)