rename jtag_nsrst_delay as adapter_nsrst_delay
[fw/openocd] / src / svf / svf.c
index 45f34936dbaed7658f3df520892af9c87feec2be..6e951e24f65ecb6368294a4754af4aa485ad191d 100644 (file)
@@ -31,9 +31,9 @@
 #include "config.h"
 #endif
 
-#include "jtag.h"
+#include <jtag/jtag.h>
 #include "svf.h"
-#include "time_support.h"
+#include <helper/time_support.h>
 
 
 // SVF command
@@ -216,8 +216,6 @@ static char *svf_command_buffer = NULL;
 static int svf_command_buffer_size = 0;
 static int svf_line_number = 1;
 
-static struct jtag_tap *tap = NULL;
-
 #define SVF_MAX_BUFFER_SIZE_TO_COMMIT  (4 * 1024)
 static uint8_t *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL;
 static int svf_buffer_index = 0, svf_buffer_size = 0;
@@ -310,7 +308,7 @@ COMMAND_HANDLER(handle_svf_command)
 
        if ((CMD_ARGC < 1) || (CMD_ARGC > (1 + SVF_NUM_OF_OPTIONS)))
        {
-               command_print(cmd_ctx, "usage: svf <file> [quiet]");
+               command_print(CMD_CTX, "usage: svf <file> [quiet]");
                return ERROR_FAIL;
        }
 
@@ -333,7 +331,7 @@ COMMAND_HANDLER(handle_svf_command)
 
        if ((svf_fd = open(CMD_ARGV[0], O_RDONLY)) < 0)
        {
-               command_print(cmd_ctx, "file \"%s\" not found", CMD_ARGV[0]);
+               command_print(CMD_CTX, "file \"%s\" not found", CMD_ARGV[0]);
 
                // no need to free anything now
                return ERROR_FAIL;
@@ -392,7 +390,7 @@ COMMAND_HANDLER(handle_svf_command)
 
        while (ERROR_OK == svf_read_command_from_file(svf_fd))
        {
-               if (ERROR_OK != svf_run_command(cmd_ctx, svf_command_buffer))
+               if (ERROR_OK != svf_run_command(CMD_CTX, svf_command_buffer))
                {
                        LOG_ERROR("fail to run command at line %d", svf_line_number);
                        ret = ERROR_FAIL;
@@ -410,7 +408,7 @@ COMMAND_HANDLER(handle_svf_command)
        }
 
        // print time
-       command_print(cmd_ctx, "%lld ms used", timeval_ms() - time_ago);
+       command_print(CMD_CTX, "%lld ms used", timeval_ms() - time_ago);
 
 free_all:
 
@@ -457,11 +455,11 @@ free_all:
 
        if (ERROR_OK == ret)
        {
-               command_print(cmd_ctx, "svf file programmed successfully for %d commands", command_num);
+               command_print(CMD_CTX, "svf file programmed successfully for %d commands", command_num);
        }
        else
        {
-               command_print(cmd_ctx, "svf file programmed failed");
+               command_print(CMD_CTX, "svf file programmed failed");
        }
 
        return ret;
@@ -470,7 +468,8 @@ free_all:
 #define SVFP_CMD_INC_CNT                       1024
 static int svf_read_command_from_file(int fd)
 {
-       char ch, *tmp_buffer = NULL;
+       unsigned char ch;
+       char *tmp_buffer = NULL;
        int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
 
        while (!cmd_ok && (read(fd, &ch, 1) > 0))
@@ -499,31 +498,55 @@ static int svf_read_command_from_file(int fd)
                case '\r':
                        slash = 0;
                        comment = 0;
-                       break;
+                       /* Don't save '\r' and '\n' if no data is parsed */
+                       if (!cmd_pos)
+                               break;
                default:
                        if (!comment)
                        {
-                               if (cmd_pos >= svf_command_buffer_size - 1)
+                               /* The parsing code currently expects a space
+                                * before parentheses -- "TDI (123)".  Also a
+                                * space afterwards -- "TDI (123) TDO(456)".
+                                * But such spaces are optional... instead of
+                                * parser updates, cope with that by adding the
+                                * spaces as needed.
+                                *
+                                * Ensure there are 3 bytes available, for:
+                                *  - current character
+                                *  - added space.
+                                *  - terminating NUL ('\0')
+                                */
+                               if ((cmd_pos + 2) >= svf_command_buffer_size)
                                {
-                                       tmp_buffer = (char*)malloc(svf_command_buffer_size + SVFP_CMD_INC_CNT);         // 1 more byte for '\0'
+                                       /* REVISIT use realloc(); simpler */
+                                       tmp_buffer = malloc(
+                                                       svf_command_buffer_size
+                                                       + SVFP_CMD_INC_CNT);
                                        if (NULL == tmp_buffer)
                                        {
                                                LOG_ERROR("not enough memory");
                                                return ERROR_FAIL;
                                        }
                                        if (svf_command_buffer_size > 0)
-                                       {
-                                               memcpy(tmp_buffer, svf_command_buffer, svf_command_buffer_size);
-                                       }
+                                               memcpy(tmp_buffer,
+                                                       svf_command_buffer,
+                                                       svf_command_buffer_size);
                                        if (svf_command_buffer != NULL)
-                                       {
                                                free(svf_command_buffer);
-                                       }
                                        svf_command_buffer = tmp_buffer;
                                        svf_command_buffer_size += SVFP_CMD_INC_CNT;
                                        tmp_buffer = NULL;
                                }
+
+                               /* insert a space before '(' */
+                               if ('(' == ch)
+                                       svf_command_buffer[cmd_pos++] = ' ';
+
                                svf_command_buffer[cmd_pos++] = (char)toupper(ch);
+
+                               /* insert a space after ')' */
+                               if (')' == ch)
+                                       svf_command_buffer[cmd_pos++] = ' ';
                        }
                        break;
                }
@@ -542,25 +565,30 @@ static int svf_read_command_from_file(int fd)
 
 static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
 {
-       int pos = 0, num = 0, space_found = 1;
+       int pos = 0, num = 0, space_found = 1, in_bracket = 0;
 
        while (pos < len)
        {
                switch (str[pos])
                {
-               case '\n':
-               case '\r':
                case '!':
                case '/':
                        LOG_ERROR("fail to parse svf command");
                        return ERROR_FAIL;
-                       break;
-               case ' ':
-                       space_found = 1;
-                       str[pos] = '\0';
-                       break;
+               case '(':
+                       in_bracket = 1;
+                       goto parse_char;
+               case ')':
+                       in_bracket = 0;
+                       goto parse_char;
                default:
-                       if (space_found)
+parse_char:
+                       if (!in_bracket && isspace((int) str[pos]))
+                       {
+                               space_found = 1;
+                               str[pos] = '\0';
+                       }
+                       else if (space_found)
                        {
                                argus[num++] = &str[pos];
                                space_found = 0;
@@ -628,6 +656,7 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
                return ERROR_FAIL;
        }
 
+       /* fill from LSB (end of str) to MSB (beginning of str) */
        for (i = 0; i < str_hbyte_len; i++)
        {
                ch = 0;
@@ -635,7 +664,13 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
                {
                        ch = str[--str_len];
 
-                       if (!isblank(ch))
+                       /* Skip whitespace.  The SVF specification (rev E) is
+                        * deficient in terms of basic lexical issues like
+                        * where whitespace is allowed.  Long bitstrings may
+                        * require line ends for correctness, since there is
+                        * a hard limit on line length.
+                        */
+                       if (!isspace(ch))
                        {
                                if ((ch >= '0') && (ch <= '9'))
                                {
@@ -671,11 +706,12 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
                }
        }
 
-       // consume optional leading '0' characters
-       while (str_len > 0 && str[str_len - 1] == '0')
+       /* consume optional leading '0' MSBs or whitespace */
+       while (str_len > 0 && ((str[str_len - 1] == '0')
+                               || isspace((int) str[str_len - 1])))
                str_len--;
 
-       // check valid
+       /* check validity: we must have consumed everything */
        if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0)
        {
                LOG_ERROR("value execeeds length");
@@ -844,7 +880,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                        // TODO: set jtag speed to
                        if (svf_para.frequency > 0)
                        {
-                               command_run_linef(cmd_ctx, "jtag_khz %d", (int)svf_para.frequency / 1000);
+                               command_run_linef(cmd_ctx, "adapter_khz %d", (int)svf_para.frequency / 1000);
                                LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
                        }
                }
@@ -1044,12 +1080,11 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                        {
                                svf_add_check_para(0, svf_buffer_index, i);
                        }
-                       field.tap = tap;
                        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);
+                       jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, svf_para.dr_end_state);
 
                        svf_buffer_index += (i + 7) >> 3;
                }
@@ -1140,12 +1175,12 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                        {
                                svf_add_check_para(0, svf_buffer_index, i);
                        }
-                       field.tap = tap;
                        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);
+                       jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value,
+                                       svf_para.ir_end_state);
 
                        svf_buffer_index += (i + 7) >> 3;
                }
@@ -1350,12 +1385,9 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                                        return ERROR_FAIL;
                                }
                        }
-                       // no need to keep this memory, in jtag_add_pathmove, path will be duplicated
-                       if (NULL != path)
-                       {
-                               free(path);
-                               path = NULL;
-                       }
+
+                       free(path);
+                       path = NULL;
                }
                else
                {
@@ -1460,11 +1492,18 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
        return ERROR_OK;
 }
 
+static const struct command_registration svf_command_handlers[] = {
+       {
+               .name = "svf",
+               .handler = handle_svf_command,
+               .mode = COMMAND_EXEC,
+               .help = "Runs a SVF file.",
+               .usage = "filename ['quiet']",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
 int svf_register_commands(struct command_context *cmd_ctx)
 {
-       register_command(cmd_ctx, NULL, "svf",
-                       &handle_svf_command, COMMAND_EXEC,
-                       "run svf <file>");
-
-       return ERROR_OK;
+       return register_commands(cmd_ctx, NULL, svf_command_handlers);
 }