|
|
@@ -37,6 +37,7 @@ |
|
|
|
#include "jtag.h" |
|
|
|
#include "command.h" |
|
|
|
#include "log.h" |
|
|
|
#include "time_support.h" |
|
|
|
|
|
|
|
#include <ctype.h> |
|
|
|
#include <stdlib.h> |
|
|
@@ -187,10 +188,12 @@ static int svf_command_buffer_size = 0; |
|
|
|
static int svf_line_number = 1; |
|
|
|
|
|
|
|
static jtag_tap_t *tap = NULL; |
|
|
|
static tap_state_t last_state = TAP_RESET; |
|
|
|
|
|
|
|
#define SVF_MAX_BUFFER_SIZE_TO_COMMIT (4 * 1024) |
|
|
|
static u8 *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL; |
|
|
|
static int svf_buffer_index = 0, svf_buffer_size = 0; |
|
|
|
static int svf_quiet = 0; |
|
|
|
|
|
|
|
|
|
|
|
int svf_register_commands(struct command_context_s *cmd_ctx) |
|
|
@@ -230,23 +233,47 @@ void svf_free_xxd_para(svf_xxr_para_t *para) |
|
|
|
|
|
|
|
static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) |
|
|
|
{ |
|
|
|
#define SVF_NUM_OF_OPTIONS 1 |
|
|
|
int command_num = 0, i; |
|
|
|
int ret = ERROR_OK; |
|
|
|
long long time_ago; |
|
|
|
|
|
|
|
if (argc < 1) |
|
|
|
if ((argc < 1) || (argc > (1 + SVF_NUM_OF_OPTIONS))) |
|
|
|
{ |
|
|
|
command_print(cmd_ctx, "usage: svf <file>"); |
|
|
|
command_print(cmd_ctx, "usage: svf <file> [quiet]"); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
// parse variant |
|
|
|
svf_quiet = 0; |
|
|
|
for (i = 1; i < argc; i++) |
|
|
|
{ |
|
|
|
if (!strcmp(args[i], "quiet")) |
|
|
|
{ |
|
|
|
svf_quiet = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
LOG_ERROR("unknown variant for svf: %s", args[i]); |
|
|
|
|
|
|
|
// no need to free anything now |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if ((svf_fd = open(args[0], O_RDONLY)) < 0) |
|
|
|
{ |
|
|
|
command_print(cmd_ctx, "file \"%s\" not found", args[0]); |
|
|
|
|
|
|
|
// no need to free anything now |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
LOG_USER("svf processing file: \"%s\"", args[0]); |
|
|
|
|
|
|
|
// get time |
|
|
|
time_ago = timeval_ms(); |
|
|
|
|
|
|
|
// init |
|
|
|
svf_line_number = 1; |
|
|
|
svf_command_buffer_size = 0; |
|
|
@@ -315,6 +342,9 @@ static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char |
|
|
|
ret = ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
// print time |
|
|
|
command_print(cmd_ctx, "%d ms used", timeval_ms() - time_ago); |
|
|
|
|
|
|
|
free_all: |
|
|
|
|
|
|
|
close(svf_fd); |
|
|
@@ -655,6 +685,22 @@ static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len) |
|
|
|
return ERROR_OK; |
|
|
|
} |
|
|
|
|
|
|
|
static int svf_execute_tap(void) |
|
|
|
{ |
|
|
|
if (ERROR_OK != jtag_execute_queue()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
else if (ERROR_OK != svf_check_tdo()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
svf_buffer_index = 0; |
|
|
|
|
|
|
|
return ERROR_OK; |
|
|
|
} |
|
|
|
|
|
|
|
// not good to use this |
|
|
|
extern jtag_command_t** jtag_get_last_command_p(void); |
|
|
|
extern void* cmd_queue_alloc(size_t size); |
|
|
@@ -681,7 +727,10 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
// for STATE |
|
|
|
tap_state_t *path = NULL, state; |
|
|
|
|
|
|
|
LOG_DEBUG("%s", cmd_str); |
|
|
|
if (!svf_quiet) |
|
|
|
{ |
|
|
|
LOG_USER("%s", svf_command_buffer); |
|
|
|
} |
|
|
|
|
|
|
|
if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu)) |
|
|
|
{ |
|
|
@@ -736,6 +785,10 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
LOG_ERROR("HZ not found in FREQUENCY command"); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
if (ERROR_OK != svf_execute_tap()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
svf_para.frequency = atof(argus[1]); |
|
|
|
// TODO: set jtag speed to |
|
|
|
if (svf_para.frequency > 0) |
|
|
@@ -776,7 +829,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
xxr_para_tmp->data_mask = 0; |
|
|
|
for (i = 2; i < num_of_argu; i += 2) |
|
|
|
{ |
|
|
|
if ((argus[i + 1][0] != '(') || (argus[i + 1][strlen(argus[i + 1]) - 1] != ')')) |
|
|
|
if ((strlen(argus[i + 1]) < 3) || (argus[i + 1][0] != '(') || (argus[i + 1][strlen(argus[i + 1]) - 1] != ')')) |
|
|
|
{ |
|
|
|
LOG_ERROR("data section error"); |
|
|
|
return ERROR_FAIL; |
|
|
@@ -931,6 +984,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state); |
|
|
|
|
|
|
|
svf_buffer_index += (i + 7) >> 3; |
|
|
|
last_state = svf_para.dr_end_state; |
|
|
|
} |
|
|
|
else if (SIR == command) |
|
|
|
{ |
|
|
@@ -1031,6 +1085,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state); |
|
|
|
|
|
|
|
svf_buffer_index += (i + 7) >> 3; |
|
|
|
last_state = svf_para.ir_end_state; |
|
|
|
} |
|
|
|
break; |
|
|
|
case PIO: |
|
|
@@ -1126,14 +1181,50 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
{ |
|
|
|
if (run_count > 0) |
|
|
|
{ |
|
|
|
// run_state and end_state is checked to be stable state |
|
|
|
// TODO: do runtest |
|
|
|
#if 1 |
|
|
|
// enter into run_state if necessary |
|
|
|
if (last_state != svf_para.runtest_run_state) |
|
|
|
{ |
|
|
|
last_cmd = jtag_get_last_command_p(); |
|
|
|
*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t)); |
|
|
|
last_comand_pointer = &((*last_cmd)->next); |
|
|
|
(*last_cmd)->next = NULL; |
|
|
|
(*last_cmd)->type = JTAG_STATEMOVE; |
|
|
|
(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t)); |
|
|
|
(*last_cmd)->cmd.statemove->end_state = svf_para.runtest_run_state; |
|
|
|
|
|
|
|
cmd_queue_end_state = cmd_queue_cur_state = (*last_cmd)->cmd.statemove->end_state; |
|
|
|
} |
|
|
|
|
|
|
|
// call jtag_add_clocks |
|
|
|
jtag_add_clocks(run_count); |
|
|
|
|
|
|
|
if (svf_para.runtest_end_state != svf_para.runtest_run_state) |
|
|
|
{ |
|
|
|
// move to end_state |
|
|
|
last_cmd = jtag_get_last_command_p(); |
|
|
|
*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t)); |
|
|
|
last_comand_pointer = &((*last_cmd)->next); |
|
|
|
(*last_cmd)->next = NULL; |
|
|
|
(*last_cmd)->type = JTAG_STATEMOVE; |
|
|
|
(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t)); |
|
|
|
(*last_cmd)->cmd.statemove->end_state = svf_para.runtest_end_state; |
|
|
|
|
|
|
|
cmd_queue_end_state = cmd_queue_cur_state = (*last_cmd)->cmd.statemove->end_state; |
|
|
|
} |
|
|
|
last_state = svf_para.runtest_end_state; |
|
|
|
#else |
|
|
|
if (svf_para.runtest_run_state != TAP_IDLE) |
|
|
|
{ |
|
|
|
// RUNTEST can only executed in TAP_IDLE |
|
|
|
LOG_ERROR("cannot runtest in %s state", svf_tap_state_name[svf_para.runtest_run_state]); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
jtag_add_runtest(run_count, svf_para.runtest_end_state); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
@@ -1158,32 +1249,45 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
LOG_ERROR("not enough memory"); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
for (i = 1; i < num_of_argu; i++) |
|
|
|
num_of_argu--; // num of path |
|
|
|
i_tmp = 1; // path is from patameter 1 |
|
|
|
for (i = 0; i < num_of_argu; i++) |
|
|
|
{ |
|
|
|
path[i - 1] = svf_find_string_in_array(argus[i], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); |
|
|
|
if (!svf_tap_state_is_valid(path[i - 1])) |
|
|
|
path[i] = svf_find_string_in_array(argus[i_tmp++], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); |
|
|
|
if (!svf_tap_state_is_valid(path[i])) |
|
|
|
{ |
|
|
|
LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i - 1]]); |
|
|
|
LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i]]); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
if (TAP_RESET == path[i - 1]) |
|
|
|
if (TAP_RESET == path[i]) |
|
|
|
{ |
|
|
|
LOG_ERROR("TAP_RESET is not allowed in pathmove"); |
|
|
|
return ERROR_FAIL; |
|
|
|
if (i > 0) |
|
|
|
{ |
|
|
|
jtag_add_pathmove(i, path); |
|
|
|
} |
|
|
|
jtag_add_tlr(); |
|
|
|
num_of_argu -= i + 1; |
|
|
|
i = -1; |
|
|
|
} |
|
|
|
} |
|
|
|
if (svf_tap_state_is_stable(path[num_of_argu - 1])) |
|
|
|
if (num_of_argu > 0) |
|
|
|
{ |
|
|
|
// last state MUST be stable state |
|
|
|
// TODO: call path_move |
|
|
|
jtag_add_pathmove(num_of_argu - 1, path); |
|
|
|
LOG_DEBUG("\tmove to %s by path_move", svf_tap_state_name[path[num_of_argu - 1]]); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
LOG_ERROR("%s is not valid state", svf_tap_state_name[path[num_of_argu - 1]]); |
|
|
|
return ERROR_FAIL; |
|
|
|
// execute last path if necessary |
|
|
|
if (svf_tap_state_is_stable(path[num_of_argu - 1])) |
|
|
|
{ |
|
|
|
// last state MUST be stable state |
|
|
|
// TODO: call path_move |
|
|
|
jtag_add_pathmove(num_of_argu, path); |
|
|
|
last_state = path[num_of_argu - 1]; |
|
|
|
LOG_DEBUG("\tmove to %s by path_move", svf_tap_state_name[path[num_of_argu - 1]]); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
LOG_ERROR("%s is not valid state", svf_tap_state_name[path[num_of_argu - 1]]); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
} |
|
|
|
// no need to keep this memory, in jtag_add_pathmove, path will be duplicated |
|
|
|
if (NULL != path) |
|
|
|
{ |
|
|
|
free(path); |
|
|
@@ -1205,6 +1309,9 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t)); |
|
|
|
(*last_cmd)->cmd.statemove->end_state = state; |
|
|
|
|
|
|
|
cmd_queue_end_state = cmd_queue_cur_state = (*last_cmd)->cmd.statemove->end_state; |
|
|
|
last_state = state; |
|
|
|
|
|
|
|
LOG_DEBUG("\tmove to %s by state_move", svf_tap_state_name[state]); |
|
|
|
} |
|
|
|
else |
|
|
@@ -1223,16 +1330,20 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
} |
|
|
|
if (svf_para.trst_mode != TRST_ABSENT) |
|
|
|
{ |
|
|
|
if (ERROR_OK != svf_execute_tap()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
i_tmp = svf_find_string_in_array(argus[1], (char **)svf_trst_mode_name, dimof(svf_trst_mode_name)); |
|
|
|
switch (i_tmp) |
|
|
|
{ |
|
|
|
case TRST_ON: |
|
|
|
last_state = TAP_RESET; |
|
|
|
jtag_add_reset(1, 0); |
|
|
|
break; |
|
|
|
case TRST_OFF: |
|
|
|
jtag_add_reset(1, 1); |
|
|
|
break; |
|
|
|
case TRST_Z: |
|
|
|
case TRST_OFF: |
|
|
|
jtag_add_reset(0, 0); |
|
|
|
break; |
|
|
|
case TRST_ABSENT: |
|
|
|
break; |
|
|
@@ -1262,22 +1373,17 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
(((command != STATE) && (command != RUNTEST)) || \ |
|
|
|
((command == STATE) && (num_of_argu == 2)))) |
|
|
|
{ |
|
|
|
// there is data to be executed |
|
|
|
if (ERROR_OK != jtag_execute_queue()) |
|
|
|
if (ERROR_OK != svf_execute_tap()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
// output debug info |
|
|
|
if ((SIR == command) || (SDR == command)) |
|
|
|
{ |
|
|
|
// in debug mode, data is from index 0 |
|
|
|
LOG_DEBUG("\tTDO read = 0x%X", (*(int*)svf_tdi_buffer) & ((1 << (svf_check_tdo_para[0].bit_len)) - 1)); |
|
|
|
} |
|
|
|
if (ERROR_OK != svf_check_tdo()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
svf_buffer_index = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
@@ -1288,16 +1394,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) |
|
|
|
(((command != STATE) && (command != RUNTEST)) || \ |
|
|
|
((command == STATE) && (num_of_argu == 2)))) |
|
|
|
{ |
|
|
|
if (ERROR_OK != jtag_execute_queue()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
else if (ERROR_OK != svf_check_tdo()) |
|
|
|
{ |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
|
|
|
|
svf_buffer_index = 0; |
|
|
|
return svf_execute_tap(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|