#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
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;
int svf_add_statemove(tap_state_t state_to)
{
tap_state_t state_from = cmd_queue_cur_state;
- uint8_t index;
+ unsigned index_var;
/* when resetting, be paranoid and ignore current state */
if (state_to == TAP_RESET) {
return ERROR_OK;
}
- for (index = 0; index < ARRAY_SIZE(svf_statemoves); index++)
+ for (index_var = 0; index_var < ARRAY_SIZE(svf_statemoves); index_var++)
{
- if ((svf_statemoves[index].from == state_from)
- && (svf_statemoves[index].to == state_to))
+ if ((svf_statemoves[index_var].from == state_from)
+ && (svf_statemoves[index_var].to == state_to))
{
/* 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);
+ if (svf_statemoves[index_var].num_of_moves > 1)
+ jtag_add_pathmove(svf_statemoves[index_var].num_of_moves - 1,
+ svf_statemoves[index_var].paths + 1);
else
- jtag_add_pathmove(svf_statemoves[index].num_of_moves,
- svf_statemoves[index].paths);
+ jtag_add_pathmove(svf_statemoves[index_var].num_of_moves,
+ svf_statemoves[index_var].paths);
return ERROR_OK;
}
}
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;
}
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;
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;
}
// 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:
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;
#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))
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;
}
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;
return ERROR_FAIL;
}
+ /* fill from LSB (end of str) to MSB (beginning of str) */
for (i = 0; i < str_hbyte_len; i++)
{
ch = 0;
{
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'))
{
}
}
- // 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");
static int svf_check_tdo(void)
{
- int i, len, index;
+ int i, len, index_var;
for (i = 0; i < svf_check_tdo_para_index; i++)
{
- index = svf_check_tdo_para[i].buffer_offset;
+ index_var = svf_check_tdo_para[i].buffer_offset;
len = svf_check_tdo_para[i].bit_len;
if ((svf_check_tdo_para[i].enabled)
- && buf_cmp_mask(&svf_tdi_buffer[index], &svf_tdo_buffer[index], &svf_mask_buffer[index], len))
+ && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], &svf_mask_buffer[index_var], len))
{
unsigned bitmask;
unsigned received, expected, tapmask;
bitmask = svf_get_mask_u32(svf_check_tdo_para[i].bit_len);
- memcpy(&received, svf_tdi_buffer + index, sizeof(unsigned));
- memcpy(&expected, svf_tdo_buffer + index, sizeof(unsigned));
- memcpy(&tapmask, svf_mask_buffer + index, sizeof(unsigned));
+ memcpy(&received, svf_tdi_buffer + index_var, sizeof(unsigned));
+ memcpy(&expected, svf_tdo_buffer + index_var, sizeof(unsigned));
+ memcpy(&tapmask, svf_mask_buffer + index_var, sizeof(unsigned));
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",
// 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);
}
}
{
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;
}
{
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;
}
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
{
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);
}