X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fsvf%2Fsvf.c;h=62e2324883a9c2acb5f215f115879f688eb81046;hb=838cd58e24a18102b8a140df9fa993fe65706828;hp=e01b9332c4d2ae2612a1a944bc51b8e0abc9d24b;hpb=75e37b5348161c97285b808e792976870c383f4c;p=openocd.git diff --git a/src/svf/svf.c b/src/svf/svf.c index e01b9332c4..62e2324883 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -31,9 +31,9 @@ #include "config.h" #endif -#include "jtag.h" +#include #include "svf.h" -#include "time_support.h" +#include // 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; @@ -274,7 +272,7 @@ static unsigned svf_get_mask_u32(int bitlen) 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) { @@ -282,18 +280,18 @@ int svf_add_statemove(tap_state_t state_to) 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; } } @@ -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"); @@ -687,22 +723,22 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l 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", @@ -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 { @@ -1463,10 +1495,10 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str) static const struct command_registration svf_command_handlers[] = { { .name = "svf", - .handler = &handle_svf_command, + .handler = handle_svf_command, .mode = COMMAND_EXEC, .help = "Runs a SVF file.", - .usage = "", + .usage = "filename ['quiet']", }, COMMAND_REGISTRATION_DONE };