diff options
author | kc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2009-01-19 07:13:02 +0000 |
---|---|---|
committer | kc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2009-01-19 07:13:02 +0000 |
commit | c8bc0bb1aee7e7280229a6ec0c104a8fb512782f (patch) | |
tree | 184934c96da1b155b17cf21027064eed0676c48f | |
parent | 2aed5dd40b42f8381d62658522a7ada453e22022 (diff) | |
download | openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.tar.gz openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.tar.bz2 openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.tar.xz openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.zip |
SVF player courtesy of Simon Qian <simonqian@SimonQian.com>
git-svn-id: svn://svn.berlios.de/openocd/trunk@1339 b42882b7-edfa-0310-969c-e2dbd0fdcd60
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/ecosboard.c | 1 | ||||
-rw-r--r-- | src/jtag/vsllink.c | 535 | ||||
-rw-r--r-- | src/openocd.c | 2 | ||||
-rw-r--r-- | src/svf/Makefile.am | 5 | ||||
-rw-r--r-- | src/svf/Makefile.in | 406 | ||||
-rw-r--r-- | src/svf/svf.c | 1305 | ||||
-rw-r--r-- | src/svf/svf.h | 27 |
9 files changed, 2049 insertions, 242 deletions
diff --git a/configure.in b/configure.in index f0011989..79e546e8 100644 --- a/configure.in +++ b/configure.in @@ -705,4 +705,4 @@ fi AC_MSG_RESULT([$EXEEXT_FOR_BUILD]) AC_SUBST(EXEEXT_FOR_BUILD) -AC_OUTPUT(Makefile src/Makefile src/helper/Makefile src/jtag/Makefile src/xsvf/Makefile src/target/Makefile src/server/Makefile src/flash/Makefile src/pld/Makefile doc/Makefile) +AC_OUTPUT(Makefile src/Makefile src/helper/Makefile src/jtag/Makefile src/xsvf/Makefile src/svf/Makefile src/target/Makefile src/server/Makefile src/flash/Makefile src/pld/Makefile doc/Makefile) diff --git a/src/Makefile.am b/src/Makefile.am index 0e0f50e4..24333e31 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,8 +11,8 @@ openocd_SOURCES = $(MAINFILE) openocd.c # set the include path found by configure INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/helper \ - -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target -I$(top_srcdir)/src/xsvf -I$(top_srcdir)/src/server \ - -I$(top_srcdir)/src/flash -I$(top_srcdir)/src/pld $(all_includes) + -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target -I$(top_srcdir)/src/xsvf -I$(top_srcdir)/src/svf \ + -I$(top_srcdir)/src/server -I$(top_srcdir)/src/flash -I$(top_srcdir)/src/pld $(all_includes) # pass path to prefix path openocd_CPPFLAGS = \ @@ -23,7 +23,7 @@ openocd_CPPFLAGS = \ # the library search path. openocd_LDFLAGS = $(all_libraries) -SUBDIRS = helper jtag xsvf target server flash pld +SUBDIRS = helper jtag xsvf svf target server flash pld if IS_MINGW MINGWLDADD = -lwsock32 @@ -61,7 +61,7 @@ endif -openocd_LDADD = $(top_builddir)/src/xsvf/libxsvf.a \ +openocd_LDADD = $(top_builddir)/src/xsvf/libxsvf.a $(top_builddir)/src/svf/libsvf.a \ $(top_builddir)/src/target/libtarget.a $(top_builddir)/src/jtag/libjtag.a \ $(top_builddir)/src/helper/libhelper.a \ $(top_builddir)/src/server/libserver.a $(top_builddir)/src/helper/libhelper.a \ diff --git a/src/ecosboard.c b/src/ecosboard.c index 725a3f36..859d045b 100644 --- a/src/ecosboard.c +++ b/src/ecosboard.c @@ -26,6 +26,7 @@ #include "jtag.h" #include "configuration.h" #include "xsvf.h" +#include "svf.h" #include "target.h" #include "flash.h" #include "nand.h" diff --git a/src/jtag/vsllink.c b/src/jtag/vsllink.c index 88a59d78..de4220f7 100644 --- a/src/jtag/vsllink.c +++ b/src/jtag/vsllink.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2007 by Simon Qian <SimonQian@SimonQian.com> * + * 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 * @@ -49,17 +49,12 @@ #define DEBUG_JTAG_IO(expr ...) #endif -#define VID 0x03EB -#define PID 0x2103 -#define VSLLINK_WRITE_ENDPOINT 0x02 -#define VSLLINK_READ_ENDPOINT 0x82 +u16 vsllink_vid; +u16 vsllink_pid; +u8 vsllink_bulkout; +u8 vsllink_bulkin; -u16 vsllink_vid = VID; -u16 vsllink_pid = PID; -u8 vsllink_bulkout = VSLLINK_WRITE_ENDPOINT; -u8 vsllink_bulkin = VSLLINK_READ_ENDPOINT; - -#define VSLLINK_USB_TIMEOUT 1000 +#define VSLLINK_USB_TIMEOUT 5000 static int VSLLINK_BufferSize = 1024; @@ -77,8 +72,11 @@ static u8* vsllink_usb_out_buffer = NULL; #define VSLLINK_CMD_GET_PORT 0x91 #define VSLLINK_CMD_SET_PORTDIR 0x92 #define VSLLINK_CMD_HW_JTAGSEQCMD 0xA0 +#define VSLLINK_CMD_HW_JTAGHLCMD 0xA1 +#define VSLLINK_CMD_HW_SWDCMD 0xA2 #define VSLLINK_CMDJTAGSEQ_TMSBYTE 0x00 +#define VSLLINK_CMDJTAGSEQ_TMS0BYTE 0x40 #define VSLLINK_CMDJTAGSEQ_SCAN 0x80 #define VSLLINK_CMDJTAGSEQ_CMDMSK 0xC0 @@ -109,21 +107,21 @@ static u8* vsllink_usb_out_buffer = NULL; u8 VSLLINK_tap_move[6][6] = { /* TLR RTI SD PD SI PI */ - {0xff, 0x00, 0x2f, 0x0a, 0x37, 0x16}, /* TLR */ + {0xff, 0x7f, 0x2f, 0x0a, 0x37, 0x16}, /* TLR */ {0xff, 0x00, 0x45, 0x05, 0x4b, 0x0b}, /* RTI */ {0xff, 0x61, 0x00, 0x01, 0x0f, 0x2f}, /* SD */ - {0xff, 0x60, 0x40, 0x17, 0x3c, 0x2f}, /* PD */ + {0xff, 0x60, 0x40, 0x5c, 0x3c, 0x5e}, /* PD */ {0xff, 0x61, 0x07, 0x17, 0x00, 0x01}, /* SI */ - {0xff, 0x60, 0x38, 0x17, 0x40, 0x2f} /* PI */ + {0xff, 0x60, 0x38, 0x5c, 0x40, 0x5e} /* PI */ }; -u8 VSLLINK_TAP_MOVE_FROM_E1[6] = +typedef struct insert_insignificant_operation { -// TLR RTI SD PD SI PI - 0xff, 0x60, 0x38, 0x5c, 0x3c, 0x5E -}; + unsigned char insert_value; + unsigned char insert_position; +}insert_insignificant_operation_t; -u8 VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[7][6][2] = +insert_insignificant_operation_t VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[6][6] = { /* stuff offset */ {/* TLR */ @@ -175,6 +173,19 @@ u8 VSLLINK_BIT_MSK[8] = 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f }; +typedef struct +{ + int length; /* Number of bits to read */ + int offset; + scan_command_t *command; /* Corresponding scan command */ + u8 *buffer; +} pending_scan_result_t; + +#define MAX_PENDING_SCAN_RESULTS 256 + +static int pending_scan_results_length; +static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; + /* External interface functions */ int vsllink_execute_queue(void); int vsllink_speed(int speed); @@ -219,8 +230,8 @@ int vsllink_usb_read(vsllink_jtag_t *vsllink_jtag); void vsllink_debug_buffer(u8 *buffer, int length); -int vsllink_tms_data_len = 0; -u8* vsllink_tms_cmd_pos; +static int vsllink_tms_data_len = 0; +static u8* vsllink_tms_cmd_pos; vsllink_jtag_t* vsllink_jtag_handle; @@ -255,7 +266,7 @@ int vsllink_execute_queue(void) switch (cmd->type) { case JTAG_END_STATE: - DEBUG_JTAG_IO("end_state: %i", cmd->cmd.end_state->end_state); + DEBUG_JTAG_IO("end_state: %s", jtag_state_name(cmd->cmd.end_state->end_state)); if (cmd->cmd.end_state->end_state != -1) { @@ -264,9 +275,9 @@ int vsllink_execute_queue(void) break; case JTAG_RUNTEST: - DEBUG_JTAG_IO( "runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \ - cmd->cmd.runtest->end_state); - + DEBUG_JTAG_IO( "runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, \ + jtag_state_name(cmd->cmd.runtest->end_state)); + if (cmd->cmd.runtest->end_state != -1) { vsllink_end_state(cmd->cmd.runtest->end_state); @@ -275,7 +286,7 @@ int vsllink_execute_queue(void) break; case JTAG_STATEMOVE: - DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); + DEBUG_JTAG_IO("statemove end in %s", jtag_state_name(cmd->cmd.statemove->end_state)); if (cmd->cmd.statemove->end_state != -1) { @@ -285,9 +296,9 @@ int vsllink_execute_queue(void) break; case JTAG_PATHMOVE: - DEBUG_JTAG_IO("pathmove: %i states, end in %i", \ + DEBUG_JTAG_IO("pathmove: %i states, end in %s", \ cmd->cmd.pathmove->num_states, \ - cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + jtag_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); vsllink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); break; @@ -301,11 +312,11 @@ int vsllink_execute_queue(void) scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); if (cmd->cmd.scan->ir_scan) { - DEBUG_JTAG_IO("JTAG Scan write IR(%d bits), end in %d:", scan_size, cmd->cmd.scan->end_state); + DEBUG_JTAG_IO("JTAG Scan write IR(%d bits), end in %s:", scan_size, jtag_state_name(cmd->cmd.scan->end_state)); } else { - DEBUG_JTAG_IO("JTAG Scan write DR(%d bits), end in %d:", scan_size, cmd->cmd.scan->end_state); + DEBUG_JTAG_IO("JTAG Scan write DR(%d bits), end in %s:", scan_size, jtag_state_name(cmd->cmd.scan->end_state)); } #ifdef _DEBUG_JTAG_IO_ @@ -470,8 +481,7 @@ int vsllink_init(void) vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_PORTDIR; vsllink_usb_out_buffer[1] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST | JTAG_PINMSK_USR1 | JTAG_PINMSK_USR2; vsllink_usb_out_buffer[2] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST; - result = vsllink_usb_write(vsllink_jtag_handle, 3); - if (result != 3) + if (vsllink_usb_write(vsllink_jtag_handle, 3) != 3) { LOG_ERROR("VSLLink USB send data error"); exit(-1); @@ -490,6 +500,17 @@ int vsllink_quit(void) { if ((vsllink_usb_in_buffer != NULL) && (vsllink_usb_out_buffer != NULL)) { + // Set all pins to input + vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_PORTDIR; + vsllink_usb_out_buffer[1] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST | JTAG_PINMSK_USR1 | JTAG_PINMSK_USR2; + vsllink_usb_out_buffer[2] = 0; + if (vsllink_usb_write(vsllink_jtag_handle, 3) != 3) + { + LOG_ERROR("VSLLink USB send data error"); + exit(-1); + } + + // disconnect vsllink_simple_command(VSLLINK_CMD_DISCONN); vsllink_usb_close(vsllink_jtag_handle); } @@ -506,24 +527,29 @@ int vsllink_quit(void) } // when vsllink_tms_data_len > 0, vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] is the byte that need to be appended. -// length of VSLLINK_CMDJTAGSEQ_TMSBYTE has been set. -void VSLLINK_add_tms_from_RTI(enum tap_state state) +// length of VSLLINK_CMDJTAGSEQ_TMSBYTE has been set, no need to set it here. +void vsllink_append_tms(void) { - u8 tms_scan = VSLLINK_TAP_MOVE(TAP_IDLE, state); + u8 tms_scan = VSLLINK_TAP_MOVE(cur_state, end_state); u16 tms2; - if ((cur_state != TAP_IDLE) || (state == TAP_IDLE) || (vsllink_tms_data_len <= 0) || (vsllink_tms_data_len >= 8) || (vsllink_tms_cmd_pos == NULL)) + if (((cur_state != TAP_RESET) && (cur_state != TAP_IDLE) && (cur_state != TAP_DRPAUSE) && (cur_state != TAP_IRPAUSE)) || \ + (vsllink_tms_data_len <= 0) || (vsllink_tms_data_len >= 8) || \ + (vsllink_tms_cmd_pos == NULL)) { LOG_ERROR("There MUST be some bugs in the driver"); exit(-1); } - tms2 = (tms_scan & VSLLINK_BIT_MSK[VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]]) << vsllink_tms_data_len; - if (VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][0] == 1) + tms2 = (tms_scan & VSLLINK_BIT_MSK[VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position]) << \ + vsllink_tms_data_len; + if (VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_value == 1) { - tms2 |= VSLLINK_BIT_MSK[8 - vsllink_tms_data_len] << (vsllink_tms_data_len + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]); + tms2 |= VSLLINK_BIT_MSK[8 - vsllink_tms_data_len] << \ + (vsllink_tms_data_len + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position); } - tms2 |= (tms_scan >> VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]) << (8 + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]); + tms2 |= (tms_scan >> VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position) << \ + (8 + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position); vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= (tms2 >> 0) & 0xff; vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms2 >> 8) & 0xff; @@ -553,7 +579,7 @@ void vsllink_state_move(void) { if (vsllink_tms_data_len > 0) { - VSLLINK_add_tms_from_RTI(end_state); + vsllink_append_tms(); } else { @@ -577,26 +603,32 @@ void vsllink_add_path(int start, int num, enum tap_state *path) { if (i > 0) { - vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0; - } - else - { - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0; + vsllink_usb_out_buffer_idx++; } + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0; } if (path[i - start] == tap_transitions[cur_state].high) { vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] |= 1 << (i & 7); } + else if (path[i - start] == tap_transitions[cur_state].low) + { + // nothing to do + } else { - LOG_ERROR("BUG: %d -> %d isn't a valid TAP transition", cur_state, path[i]); + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", jtag_state_name(cur_state), jtag_state_name(path[i])); exit(-1); } - - cur_state = path[i]; + cur_state = path[i - start]; } + if ((i > 0) && ((i & 7) == 0)) + { + vsllink_usb_out_buffer_idx++; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0; + } + end_state = cur_state; } @@ -606,42 +638,68 @@ void vsllink_path_move(int num_states, enum tap_state *path) if (vsllink_tms_data_len > 0) { - if ((vsllink_tms_data_len + num_states) < 8) - { - vsllink_add_path(vsllink_tms_data_len, num_states, path); - num_states = 0; - } - else if ((vsllink_tms_data_len + num_states) < 16) + // there are vsllink_tms_data_len more tms bits to be shifted + // so there are vsllink_tms_data_len + num_states tms bits in all + tms_len = vsllink_tms_data_len + num_states; + if (tms_len <= 16) { - if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) \ - < VSLLINK_CMDJTAGSEQ_LENMSK) + // merge into last tms shift + if (tms_len < 8) { - *vsllink_tms_cmd_pos++; + // just append tms data to the last tms byte vsllink_add_path(vsllink_tms_data_len, num_states, path); } - else + else if (tms_len == 8) { - // need a new VSLLINK_CMDJTAGSEQ_TMSBYTE command - // if vsllink_tms_data_len > 0, length of VSLLINK_CMDJTAGSEQ_TMSBYTE MUST be > 1(tms_len > 2) - *vsllink_tms_cmd_pos--; - vsllink_add_path(vsllink_tms_data_len, 8 - vsllink_tms_data_len, path); - vsllink_usb_out_buffer_idx++; - vsllink_tap_ensure_space(0, 3); - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1; - vsllink_tms_cmd_pos = vsllink_usb_out_buffer + vsllink_usb_out_buffer_idx; - vsllink_add_path(vsllink_tms_data_len, num_states + vsllink_tms_data_len - 8, path + 8 - vsllink_tms_data_len); + // end last tms shift command + (*vsllink_tms_cmd_pos)--; + vsllink_add_path(vsllink_tms_data_len, num_states, path); + } + else if (tms_len < 16) + { + if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) < VSLLINK_CMDJTAGSEQ_LENMSK) + { + // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most + // there is enought tms length in the current tms shift command + (*vsllink_tms_cmd_pos)++; + vsllink_add_path(vsllink_tms_data_len, num_states, path); + } + else + { + // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most + // not enough tms length in the current tms shift command + // so a new command should be added + // first decrease byte length of last tms shift command + (*vsllink_tms_cmd_pos)--; + // append tms data to the last tms byte + vsllink_add_path(vsllink_tms_data_len, 8 - vsllink_tms_data_len, path); + path += 8 - vsllink_tms_data_len; + // add new command(3 bytes) + vsllink_tap_ensure_space(0, 3); + vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1; + vsllink_add_path(0, num_states - (8 - vsllink_tms_data_len), path); + } } + else if (tms_len == 16) + { + // end last tms shift command + vsllink_add_path(vsllink_tms_data_len, num_states, path); + } + vsllink_tms_data_len = (vsllink_tms_data_len + num_states) & 7; + if (vsllink_tms_data_len == 0) + { + vsllink_tms_cmd_pos = NULL; + } num_states = 0; } else { vsllink_add_path(vsllink_tms_data_len, 16 - vsllink_tms_data_len, path); - path_idx = 16 - vsllink_tms_data_len; - vsllink_usb_out_buffer_idx++; - num_states -= 16 - vsllink_tms_data_len; path += 16 - vsllink_tms_data_len; + num_states -= 16 - vsllink_tms_data_len; vsllink_tms_data_len = 0; vsllink_tms_cmd_pos = NULL; } @@ -677,14 +735,16 @@ void vsllink_path_move(int num_states, enum tap_state *path) { if (tms_len < (VSLLINK_CMDJTAGSEQ_LENMSK + 1)) { - vsllink_usb_out_buffer[tms_cmd_pos]++; - vsllink_usb_out_buffer = vsllink_usb_out_buffer + tms_cmd_pos; + vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[tms_cmd_pos]; + (*vsllink_tms_cmd_pos)++; } else { vsllink_usb_out_buffer[tms_cmd_pos]--; + tms_len = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; vsllink_tap_ensure_space(0, 3); + vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1; vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = tms_len; } @@ -694,164 +754,147 @@ void vsllink_path_move(int num_states, enum tap_state *path) void vsllink_runtest(int num_cycles) { - int i = 0, j; - int tms_len, first_tms = 0, tms_cmd_pos = 0; + int tms_len; enum tap_state saved_end_state = end_state; if (cur_state != TAP_IDLE) { + // enter into IDLE state vsllink_end_state(TAP_IDLE); - - if (vsllink_tms_data_len > 0) - { - VSLLINK_add_tms_from_RTI(end_state); - } - else - { - first_tms = 1; - } + vsllink_state_move(); } - - if (vsllink_tms_data_len > 0) + else { // cur_state == TAP_IDLE - if ((vsllink_tms_data_len + num_cycles) < 8) - { - vsllink_tms_data_len += num_cycles; - num_cycles = 0; - } - else if ((vsllink_tms_data_len + num_cycles) < 16) - { - if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) \ - < VSLLINK_CMDJTAGSEQ_LENMSK) - { - *vsllink_tms_cmd_pos++; - vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0; - } - else - { - // need a new VSLLINK_CMDJTAGSEQ_TMSBYTE command - // if vsllink_tms_data_len > 0, length of VSLLINK_CMDJTAGSEQ_TMSBYTE MUST be > 1(tms_len > 2) - *vsllink_tms_cmd_pos--; - vsllink_tap_ensure_space(0, 3); - vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1; - vsllink_tms_cmd_pos = vsllink_usb_out_buffer + vsllink_usb_out_buffer_idx; - vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0; - } - vsllink_tms_data_len = (vsllink_tms_data_len + num_cycles) & 7; - num_cycles = 0; - } - else - { - vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0; - vsllink_usb_out_buffer_idx++; - - num_cycles -= 16 - vsllink_tms_data_len; - vsllink_tms_data_len = 0; - vsllink_tms_cmd_pos = NULL; - } - } - - tms_len = ((num_cycles + 7) >> 3) + first_tms; - if (tms_len > 0) - { - // Normal operation, don't need to append tms data - vsllink_tms_data_len = num_cycles & 7; - if (vsllink_tms_data_len > 0) { - tms_len += 1; - } - // tms_len includes the length of tms byte to append - - // Make sure there is enough space - // 1 more byte maybe needed for the last tms move - vsllink_tap_ensure_space(0, (tms_len / VSLLINK_CMDJTAGSEQ_LENMSK) + tms_len + 1); - - while(tms_len > 0) - { - if (tms_len > (VSLLINK_CMDJTAGSEQ_LENMSK + 1)) + // there are vsllink_tms_data_len more tms bits to be shifted + // so there are vsllink_tms_data_len + num_cycles tms bits in all + tms_len = vsllink_tms_data_len + num_cycles; + if (tms_len <= 16) { - i = VSLLINK_CMDJTAGSEQ_LENMSK + 1; - } - else - { - i = tms_len; - } - - tms_cmd_pos = vsllink_usb_out_buffer_idx; - - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | (i - 1); + // merge into last tms shift + if (tms_len < 8) + { + // just add to vsllink_tms_data_len + // same result if tun through + //vsllink_tms_data_len += num_cycles; + } + else if (tms_len == 8) + { + // end last tms shift command + // just reduce it, no need to append_tms + (*vsllink_tms_cmd_pos)--; + vsllink_usb_out_buffer_idx++; + } + else if (tms_len < 16) + { + if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) < VSLLINK_CMDJTAGSEQ_LENMSK) + { + // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most + // there is enought tms length in the current tms shift command + // increase the tms byte length by 1 and set the last byte to 0 + (*vsllink_tms_cmd_pos)++; + vsllink_usb_out_buffer_idx++; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0; + } + else + { + // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most + // not enough tms length in the current tms shift command + // so a new command should be added + // first decrease byte length of last tms shift command + (*vsllink_tms_cmd_pos)--; + // move the command pointer to the next empty position + vsllink_usb_out_buffer_idx++; + // add new command(3 bytes) + vsllink_tap_ensure_space(0, 3); + vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1; + vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0; + } + } + else if (tms_len == 16) + { + // end last tms shift command + vsllink_usb_out_buffer_idx++; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = 0; + } - if (first_tms) - { - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(cur_state, end_state); - first_tms = 0; - j = i - 1; + vsllink_tms_data_len = (vsllink_tms_data_len + num_cycles) & 7; + if (vsllink_tms_data_len == 0) + { + vsllink_tms_cmd_pos = NULL; + } + num_cycles = 0; } else { - j = i; - } - - while (j-- > 0) - { + vsllink_usb_out_buffer_idx++; vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = 0; - } - tms_len -= i; + num_cycles -= 16 - vsllink_tms_data_len; + vsllink_tms_data_len = 0; + vsllink_tms_cmd_pos = NULL; + } } + } + // from here vsllink_tms_data_len == 0 or num_cycles == 0 - // post process vsllink_usb_out_buffer_idx - if (vsllink_tms_data_len > 0) + if (vsllink_tms_data_len > 0) + { + // num_cycles == 0 + // no need to shift + if (num_cycles > 0) { - vsllink_usb_out_buffer_idx -= 2; + LOG_ERROR("There MUST be some bugs in the driver"); + exit(-1); } - - // Set end_state - vsllink_end_state(saved_end_state); - cur_state = TAP_IDLE; - if (saved_end_state != TAP_IDLE) + } + else + { + // get number of bytes left to be sent + tms_len = num_cycles >> 3; + if (tms_len > 0) { - if (vsllink_tms_data_len > 0) - { - VSLLINK_add_tms_from_RTI(end_state); - } - else + vsllink_tap_ensure_space(1, 5); + // if tms_len > 0, vsllink_tms_data_len == 0 + // so just add new command + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMS0BYTE; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 0) & 0xff; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 8) & 0xff; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 16) & 0xff; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 24) & 0xff; + + vsllink_usb_in_want_length += 1; + pending_scan_results_buffer[pending_scan_results_length].buffer = NULL; + pending_scan_results_length++; + + if (tms_len > 0xFFFF) { - if (i < (VSLLINK_CMDJTAGSEQ_LENMSK + 1)) - { - vsllink_usb_out_buffer[tms_cmd_pos]++; - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(TAP_IDLE, end_state); - } - else - { - vsllink_tap_ensure_space(0, 2); - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE; - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(TAP_IDLE, end_state); - } + vsllink_tap_execute(); + vsllink_usb_out_buffer[0] = VSLLINK_CMD_HW_JTAGSEQCMD; + vsllink_usb_out_buffer_idx = 3; } - cur_state = saved_end_state; } + vsllink_tms_data_len = num_cycles & 7; if (vsllink_tms_data_len > 0) { - vsllink_tms_cmd_pos = vsllink_usb_out_buffer + tms_cmd_pos; + vsllink_tap_ensure_space(0, 3); + vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0; } } - else - { - // Set end_state if no RTI shifts - vsllink_end_state(saved_end_state); - cur_state = TAP_IDLE; - if (saved_end_state != TAP_IDLE) - { - vsllink_tap_ensure_space(0, 2); - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE; - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(TAP_IDLE, end_state); - cur_state = saved_end_state; - } + // post-process + // set end_state + vsllink_end_state(saved_end_state); + cur_state = TAP_IDLE; + if (end_state != TAP_IDLE) + { + vsllink_state_move(); } } @@ -861,6 +904,11 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s u8 bits_left, tms_tmp, tdi_len; int i; + if (0 == scan_size ) + { + return; + } + tdi_len = ((scan_size + 7) >> 3); if ((tdi_len + 7) > VSLLINK_BufferSize) { @@ -877,10 +925,27 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s { if (cur_state == end_state) { - *vsllink_tms_cmd_pos--; - tms_tmp = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; - vsllink_tap_ensure_space(1, tdi_len + 7); + // already in IRSHIFT or DRSHIFT state + // merge tms data in the last tms shift command into next scan command + if(*vsllink_tms_cmd_pos < 1) + { + LOG_ERROR("There MUST be some bugs in the driver"); + exit(-1); + } + else if(*vsllink_tms_cmd_pos < 2) + { + tms_tmp = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; + vsllink_usb_out_buffer_idx--; + } + else + { + tms_tmp = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx]; + *vsllink_tms_cmd_pos -= 2; + } + vsllink_tap_ensure_space(1, tdi_len + 7); + // VSLLINK_CMDJTAGSEQ_SCAN ored by 1 means that tms_before is valid + // which is merged from the last tms shift command vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_SCAN | 1; vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = ((tdi_len + 1) >> 0) & 0xff; vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = ((tdi_len + 1)>> 8) & 0xff; @@ -898,10 +963,11 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s vsllink_tap_append_scan(scan_size - vsllink_tms_data_len, buffer, command, vsllink_tms_data_len); scan_size -= 8 - vsllink_tms_data_len; + vsllink_tms_data_len = 0; } else { - VSLLINK_add_tms_from_RTI(end_state); + vsllink_append_tms(); vsllink_tap_ensure_space(1, tdi_len + 5); vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_SCAN; @@ -939,7 +1005,7 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s if (cur_state != end_state) { - vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE_FROM_E1[tap_move_map[end_state]]; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(cur_state, end_state); } else { @@ -1041,19 +1107,6 @@ int vsllink_handle_usb_bulkout_command(struct command_context_s *cmd_ctx, char * /***************************************************************************/ /* VSLLink tap functions */ -typedef struct -{ - int length; /* Number of bits to read */ - int offset; - scan_command_t *command; /* Corresponding scan command */ - u8 *buffer; -} pending_scan_result_t; - -#define MAX_PENDING_SCAN_RESULTS 256 - -static int pending_scan_results_length; -static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; - void vsllink_tap_init(void) { vsllink_usb_out_buffer_idx = 0; @@ -1101,7 +1154,7 @@ void vsllink_tap_append_scan(int length, u8 *buffer, scan_command_t *command, in } /* Pad and send a tap sequence to the device, and receive the answer. - * For the purpose of padding we assume that we are in idle or pause state. */ + * For the purpose of padding we assume that we are in reset or idle or pause state. */ int vsllink_tap_execute(void) { int i; @@ -1110,13 +1163,17 @@ int vsllink_tap_execute(void) if (vsllink_tms_data_len > 0) { + if((cur_state != TAP_RESET) && (cur_state != TAP_IDLE) && (cur_state != TAP_IRPAUSE) && (cur_state != TAP_DRPAUSE)) + { + LOG_WARNING("%s is not in RESET or IDLE or PAUSR state", jtag_state_name(cur_state)); + } + if (vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] & (1 << (vsllink_tms_data_len - 1))) { // last tms bit is '1' - // the only possible state is TLR, no need to control the number of shifts in RLT - // There MUST be some errors in the code - LOG_ERROR("last tms bit is '1'"); - exit(-1); + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= 0xFF << vsllink_tms_data_len; + vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = 0xFF; + vsllink_tms_data_len = 0; } else { @@ -1146,27 +1203,31 @@ int vsllink_tap_execute(void) int length = pending_scan_result->length; int offset = pending_scan_result->offset; scan_command_t *command = pending_scan_result->command; + + if (buffer != NULL) + { + // IRSHIFT or DRSHIFT + buf_set_buf(vsllink_usb_in_buffer, first * 8 + offset, buffer, 0, length); + first += (length + offset + 7) >> 3; - /* Copy to buffer */ - buf_set_buf(vsllink_usb_in_buffer, first * 8 + offset, buffer, 0, length); - first += (length + offset + 7) >> 3; - - DEBUG_JTAG_IO("JTAG scan read(%d bits):", length); + DEBUG_JTAG_IO("JTAG scan read(%d bits):", length); #ifdef _DEBUG_JTAG_IO_ - vsllink_debug_buffer(buffer, (length + 7) >> 3); + vsllink_debug_buffer(buffer, (length + 7) >> 3); #endif - if (jtag_read_buffer(buffer, command) != ERROR_OK) - { - vsllink_tap_init(); - return ERROR_JTAG_QUEUE_FAILED; - } - - if (pending_scan_result->buffer != NULL) - { + if (jtag_read_buffer(buffer, command) != ERROR_OK) + { + vsllink_tap_init(); + return ERROR_JTAG_QUEUE_FAILED; + } + free(pending_scan_result->buffer); pending_scan_result->buffer = NULL; } + else + { + first++; + } } } else diff --git a/src/openocd.c b/src/openocd.c index df4f8a9f..96b48b80 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -35,6 +35,7 @@ #include "jtag.h" #include "configuration.h" #include "xsvf.h" +#include "svf.h" #include "target.h" #include "flash.h" #include "nand.h" @@ -209,6 +210,7 @@ command_context_t *setup_command_handler(void) log_register_commands(cmd_ctx); jtag_register_commands(cmd_ctx); xsvf_register_commands(cmd_ctx); + svf_register_commands(cmd_ctx); target_register_commands(cmd_ctx); flash_register_commands(cmd_ctx); nand_register_commands(cmd_ctx); diff --git a/src/svf/Makefile.am b/src/svf/Makefile.am new file mode 100644 index 00000000..fa789d66 --- /dev/null +++ b/src/svf/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES = -I$(top_srcdir)/src/server -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag $(all_includes) +METASOURCES = AUTO +noinst_LIBRARIES = libsvf.a +noinst_HEADERS = svf.h +libsvf_a_SOURCES = svf.c diff --git a/src/svf/Makefile.in b/src/svf/Makefile.in new file mode 100644 index 00000000..adb85453 --- /dev/null +++ b/src/svf/Makefile.in @@ -0,0 +1,406 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/svf +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libsvf_a_AR = $(AR) $(ARFLAGS) +libsvf_a_LIBADD = +am_libsvf_a_OBJECTS = svf.$(OBJEXT) +libsvf_a_OBJECTS = $(am_libsvf_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libsvf_a_SOURCES) +DIST_SOURCES = $(libsvf_a_SOURCES) +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I$(top_srcdir)/src/server -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag $(all_includes) +METASOURCES = AUTO +noinst_LIBRARIES = libsvf.a +noinst_HEADERS = svf.h +libsvf_a_SOURCES = svf.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/svf/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/svf/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libsvf.a: $(libsvf_a_OBJECTS) $(libsvf_a_DEPENDENCIES) + -rm -f libsvf.a + $(libsvf_a_AR) libsvf.a $(libsvf_a_OBJECTS) $(libsvf_a_LIBADD) + $(RANLIB) libsvf.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svf.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/svf/svf.c b/src/svf/svf.c new file mode 100644 index 00000000..baa00885 --- /dev/null +++ b/src/svf/svf.c @@ -0,0 +1,1305 @@ +/*************************************************************************** + * 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: + * http://www.asset-intertech.com/support/svf.pdf + * Below, this document is refered to as the "SVF spec". + * + * The specification for XSVF is available here: + * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf + * Below, this document is refered to as the "XSVF spec". + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "svf.h" + +#include "jtag.h" +#include "command.h" +#include "log.h" + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> + +#include <sys/time.h> +#include <time.h> + +// SVF command +typedef enum +{ + ENDDR, + ENDIR, + FREQUENCY, + HDR, + HIR, + PIO, + PIOMAP, + RUNTEST, + SDR, + SIR, + STATE, + TDR, + TIR, + TRST, +}svf_command_t; + +const char *svf_command_name[14] = +{ + "ENDDR", + "ENDIR", + "FREQUENCY", + "HDR", + "HIR", + "PIO", + "PIOMAP", + "RUNTEST", + "SDR", + "SIR", + "STATE", + "TDR", + "TIR", + "TRST" +}; + +typedef enum +{ + TRST_ON, + TRST_OFF, + TRST_Z, + TRST_ABSENT +}trst_mode_t; + +const char *svf_trst_mode_name[4] = +{ + "ON", + "OFF", + "Z", + "ABSENT" +}; + +char *svf_tap_state_name[16]; + +#define XXR_TDI (1 << 0) +#define XXR_TDO (1 << 1) +#define XXR_MASK (1 << 2) +#define XXR_SMASK (1 << 3) +typedef struct +{ + int len; + int data_mask; + u8 *tdi; + u8 *tdo; + u8 *mask; + u8 *smask; +}svf_xxr_para_t; + +typedef struct +{ + float frequency; + tap_state_t ir_end_state; + tap_state_t dr_end_state; + tap_state_t runtest_run_state; + tap_state_t runtest_end_state; + trst_mode_t trst_mode; + + svf_xxr_para_t hir_para; + svf_xxr_para_t hdr_para; + svf_xxr_para_t tir_para; + svf_xxr_para_t tdr_para; + svf_xxr_para_t sir_para; + svf_xxr_para_t sdr_para; +}svf_para_t; + +svf_para_t svf_para; +const svf_para_t svf_para_init = +{ +// frequency, ir_end_state, dr_end_state, runtest_run_state, runtest_end_state, trst_mode + 0, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TRST_Z, +// hir_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// hdr_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// tir_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// tdr_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// sir_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// sdr_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +}; + +typedef struct +{ + int line_num; // used to record line number of the check operation + // so more information could be printed + int enabled; // check is enabled or not + int buffer_offset; // buffer_offset to buffers + int bit_len; // bit length to check +}svf_check_tdo_para_t; + +#define SVF_CHECK_TDO_PARA_SIZE 1024 +static svf_check_tdo_para_t *svf_check_tdo_para = NULL; +static int svf_check_tdo_para_index = 0; + +#define dimof(a) (sizeof(a) / sizeof((a)[0])) + +static int svf_read_command_from_file(int fd); +static int svf_check_tdo(void); +static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len); +static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str); +static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +static int svf_fd = 0; +static char *svf_command_buffer = NULL; +static int svf_command_buffer_size = 0; +static int svf_line_number = 1; + +static jtag_tap_t *tap = NULL; + +#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; + + +int svf_register_commands(struct command_context_s *cmd_ctx) +{ + register_command(cmd_ctx, NULL, "svf", handle_svf_command, + COMMAND_EXEC, "run svf <file>"); + + return ERROR_OK; +} + +void svf_free_xxd_para(svf_xxr_para_t *para) +{ + if (NULL != para) + { + if (para->tdi != NULL) + { + free(para->tdi); + para->tdi = NULL; + } + if (para->tdo != NULL) + { + free(para->tdo); + para->tdo = NULL; + } + if (para->mask != NULL) + { + free(para->mask); + para->mask = NULL; + } + if (para->smask != NULL) + { + free(para->smask); + para->smask = NULL; + } + } +} + +static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + int command_num = 0, i; + int ret = ERROR_OK; + + if (argc < 1) + { + command_print(cmd_ctx, "usage: svf <file>"); + return ERROR_FAIL; + } + + if ((svf_fd = open(args[0], O_RDONLY)) < 0) + { + command_print(cmd_ctx, "file \"%s\" not found", args[0]); + return ERROR_FAIL; + } + + LOG_USER("svf processing file: \"%s\"", args[0]); + + // init + svf_line_number = 1; + svf_command_buffer_size = 0; + + svf_check_tdo_para_index = 0; + svf_check_tdo_para = malloc(sizeof(svf_check_tdo_para_t) * SVF_CHECK_TDO_PARA_SIZE); + if (NULL == svf_check_tdo_para) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + + svf_buffer_index = 0; + // double the buffer size + // in case current command cannot be commited, and next command is a bit scan command + // here is 32K bits for this big scan command, it should be enough + // buffer will be reallocated if buffer size is not enough + svf_tdi_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT); + if (NULL == svf_tdi_buffer) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + svf_tdo_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT); + if (NULL == svf_tdo_buffer) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + svf_mask_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT); + if (NULL == svf_mask_buffer) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + svf_buffer_size = 2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT; + + memcpy(&svf_para, &svf_para_init, sizeof(svf_para)); + for (i = 0; i < dimof(svf_tap_state_name); i++) + { + svf_tap_state_name[i] = (char *)jtag_state_name(i); + } + // TAP_RESET + jtag_add_tlr(); + + while ( ERROR_OK == svf_read_command_from_file(svf_fd) ) + { + 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; + break; + } + command_num++; + } + if (ERROR_OK != jtag_execute_queue()) + { + ret = ERROR_FAIL; + } + else if (ERROR_OK != svf_check_tdo()) + { + ret = ERROR_FAIL; + } + +free_all: + + close(svf_fd); + svf_fd = 0; + + // free buffers + if (svf_command_buffer) + { + free(svf_command_buffer); + svf_command_buffer = NULL; + svf_command_buffer_size = 0; + } + if (svf_check_tdo_para) + { + free(svf_check_tdo_para); + svf_check_tdo_para = NULL; + svf_check_tdo_para_index = 0; + } + if (svf_tdi_buffer) + { + free(svf_tdi_buffer); + svf_tdi_buffer = NULL; + } + if (svf_tdo_buffer) + { + free(svf_tdo_buffer); + svf_tdo_buffer = NULL; + } + if (svf_mask_buffer) + { + free(svf_mask_buffer); + svf_mask_buffer = NULL; + } + svf_buffer_index = 0; + svf_buffer_size = 0; + + svf_free_xxd_para(&svf_para.hdr_para); + svf_free_xxd_para(&svf_para.hir_para); + svf_free_xxd_para(&svf_para.tdr_para); + svf_free_xxd_para(&svf_para.tir_para); + svf_free_xxd_para(&svf_para.sdr_para); + svf_free_xxd_para(&svf_para.sir_para); + + if (ERROR_OK == ret) + { + command_print(cmd_ctx, "svf file programmed successfully for %d commands", command_num); + } + else + { + 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; + int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0; + + while (!cmd_ok && (read(fd, &ch, 1) > 0) ) + { + switch(ch) + { + case '!': + slash = 0; + comment = 1; + break; + case '/': + if (++slash == 2) + { + comment = 1; + } + break; + case ';': + slash = 0; + if (!comment) + { + cmd_ok = 1; + } + break; + case '\n': + svf_line_number++; + case '\r': + slash = 0; + comment = 0; + break; + default: + if (!comment) + { + if (cmd_pos >= svf_command_buffer_size - 1) + { + tmp_buffer = (char*)malloc(svf_command_buffer_size + SVFP_CMD_INC_CNT); // 1 more byte for '\0' + 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); + } + 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; + } + svf_command_buffer[cmd_pos++] = (char)toupper(ch); + } + break; + } + } + + if (cmd_ok) + { + svf_command_buffer[cmd_pos] = '\0'; + return ERROR_OK; + } + else + { + return ERROR_FAIL; + } +} + +static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu) +{ + int pos = 0, num = 0, space_found = 1; + + 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; + default: + if (space_found) + { + argus[num++] = &str[pos]; + space_found = 0; + } + break; + } + pos++; + } + + *num_of_argu = num; + + return ERROR_OK; +} + +static int svf_tap_state_is_stable(tap_state_t 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) +{ + return ((state >= 0) && (state < sizeof(svf_tap_state_name))); +} + +static int svf_find_string_in_array(char *str, char **strs, int num_of_element) +{ + int i; + + for (i = 0; i < num_of_element; i++) + { + if (!strcmp(str, strs[i])) + { + return i; + } + } + return 0xFF; +} + +static int svf_adjust_array_length(u8 **arr, int orig_bit_len, int new_bit_len) +{ + int new_byte_len = (new_bit_len + 7) >> 3; + + if ((NULL == *arr) || (((orig_bit_len + 7) >> 3) < ((new_bit_len + 7) >> 3))) + { + if (*arr != NULL) + { + free(*arr); + *arr = NULL; + } + *arr = (u8*)malloc(new_byte_len); + if (NULL == *arr) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memset(*arr, 0, new_byte_len); + } + return ERROR_OK; +} + +static int svf_copy_hexstring_to_binary(char *str, u8 **bin, int orig_bit_len, int bit_len) +{ + int i, str_len = strlen(str), str_byte_len = (bit_len + 3) >> 2, loop_cnt; + u8 ch, need_write = 1; + + if (ERROR_OK != svf_adjust_array_length(bin, orig_bit_len, bit_len)) + { + LOG_ERROR("fail to adjust length of array"); + return ERROR_FAIL; + } + + if (str_byte_len > str_len) + { + loop_cnt = str_byte_len; + } + else + { + loop_cnt = str_len; + } + + for (i = 0; i < loop_cnt; i++) + { + if (i < str_len) + { + 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 + { + LOG_ERROR("invalid hex string"); + return ERROR_FAIL; + } + } + else + { + ch = 0; + } + + // check valid + if (i >= str_byte_len) + { + // 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; + } + } + else if (i == (str_byte_len - 1)) + { + // last data byte, written if valid + if ((ch & ~((1 << (bit_len - 4 * i)) - 1)) != 0) + { + LOG_ERROR("value execede length"); + return ERROR_FAIL; + } + } + + if (need_write) + { + // write bin + if (i % 2) + { + // MSB + (*bin)[i / 2] |= ch << 4; + } + else + { + // LSB + (*bin)[i / 2] = 0; + (*bin)[i / 2] |= ch; + } + } + } + + return ERROR_OK; +} + +static int svf_check_tdo(void) +{ + int i, j, byte_len, index; + + for (i = 0; i < svf_check_tdo_para_index; i++) + { + if (svf_check_tdo_para[i].enabled) + { + byte_len = (svf_check_tdo_para[i].bit_len + 7) >> 3; + index = svf_check_tdo_para[i].buffer_offset; + for (j = 0; j < byte_len; j++) + { + if ((svf_tdi_buffer[index + j] & svf_mask_buffer[index + j]) != svf_tdo_buffer[index + j]) + { + LOG_ERROR("tdo check error at line %d, read = 0x%X, want = 0x%X, mask = 0x%X", + svf_check_tdo_para[i].line_num, + (*(int*)(svf_tdi_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1), + (*(int*)(svf_tdo_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1), + (*(int*)(svf_mask_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1)); + return ERROR_FAIL; + } + } + } + } + svf_check_tdo_para_index = 0; + + return ERROR_OK; +} + +static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len) +{ + if (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE) + { + LOG_ERROR("toooooo many operation undone"); + return ERROR_FAIL; + } + + svf_check_tdo_para[svf_check_tdo_para_index].line_num = svf_line_number; + svf_check_tdo_para[svf_check_tdo_para_index].bit_len = bit_len; + svf_check_tdo_para[svf_check_tdo_para_index].enabled = enabled; + svf_check_tdo_para[svf_check_tdo_para_index].buffer_offset = buffer_offset; + svf_check_tdo_para_index++; + + 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); +extern jtag_command_t **last_comand_pointer; + +static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) +{ + char *argus[256], command; + int num_of_argu = 0, i; + + // tmp variable + int i_tmp; + + // not good to use this + jtag_command_t **last_cmd; + + // for RUNTEST + int run_count; + float min_time, max_time; + // for XXR + svf_xxr_para_t *xxr_para_tmp; + u8 **pbuffer_tmp; + scan_field_t field; + // for STATE + tap_state_t *path = NULL, state; + + LOG_DEBUG("%s", cmd_str); + + if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu)) + { + return ERROR_FAIL; + } + + command = svf_find_string_in_array(argus[0], (char **)svf_command_name, dimof(svf_command_name)); + switch(command) + { + case ENDDR: + case ENDIR: + if (num_of_argu != 2) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + i_tmp = svf_find_string_in_array(argus[1], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (svf_tap_state_is_stable(i_tmp)) + { + if (command == ENDIR) + { + svf_para.ir_end_state = i_tmp; + LOG_DEBUG("\tir_end_state = %s", svf_tap_state_name[svf_para.ir_end_state]); + } + else + { + svf_para.dr_end_state = i_tmp; + LOG_DEBUG("\tdr_end_state = %s", svf_tap_state_name[svf_para.dr_end_state]); + } + } + else + { + LOG_ERROR("%s is not valid state", argus[1]); + return ERROR_FAIL; + } + break; + case FREQUENCY: + if ((num_of_argu != 1) && (num_of_argu != 3)) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + if (1 == num_of_argu) + { + // TODO: set jtag speed to full speed + svf_para.frequency = 0; + } + else + { + if (strcmp(argus[2], "HZ")) + { + LOG_ERROR("HZ not found in FREQUENCY command"); + return ERROR_FAIL; + } + svf_para.frequency = atof(argus[1]); + // TODO: set jtag speed to + if (svf_para.frequency > 0) + { + command_run_linef(cmd_ctx, "jtag_khz %d", (int)svf_para.frequency / 1000); + LOG_DEBUG("\tfrequency = %f", svf_para.frequency); + } + } + break; + case HDR: + xxr_para_tmp = &svf_para.hdr_para; + goto XXR_common; + case HIR: + xxr_para_tmp = &svf_para.hir_para; + goto XXR_common; + case TDR: + xxr_para_tmp = &svf_para.tdr_para; + goto XXR_common; + case TIR: + xxr_para_tmp = &svf_para.tir_para; + goto XXR_common; + case SDR: + xxr_para_tmp = &svf_para.sdr_para; + goto XXR_common; + case SIR: + xxr_para_tmp = &svf_para.sir_para; + goto XXR_common; + XXR_common: + // XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] + if ((num_of_argu > 10) || (num_of_argu % 2)) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + i_tmp = xxr_para_tmp->len; + xxr_para_tmp->len = atoi(argus[1]); + LOG_DEBUG("\tlength = %d", xxr_para_tmp->len); + 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] != ')')) + { + LOG_ERROR("data section error"); + return ERROR_FAIL; + } + argus[i + 1][strlen(argus[i + 1]) - 1] = '\0'; + // TDI, TDO, MASK, SMASK + if (!strcmp(argus[i], "TDI")) + { + // TDI + pbuffer_tmp = &xxr_para_tmp->tdi; + xxr_para_tmp->data_mask |= XXR_TDI; + } + else if (!strcmp(argus[i], "TDO")) + { + // TDO + pbuffer_tmp = &xxr_para_tmp->tdo; + xxr_para_tmp->data_mask |= XXR_TDO; + } + else if (!strcmp(argus[i], "MASK")) + { + // MASK + pbuffer_tmp = &xxr_para_tmp->mask; + xxr_para_tmp->data_mask |= XXR_MASK; + } + else if (!strcmp(argus[i], "SMASK")) + { + // SMASK + pbuffer_tmp = &xxr_para_tmp->smask; + xxr_para_tmp->data_mask |= XXR_SMASK; + } + else + { + LOG_ERROR("unknow parameter: %s", argus[i]); + return ERROR_FAIL; + } + if (ERROR_OK != svf_copy_hexstring_to_binary(&argus[i + 1][1], pbuffer_tmp, i_tmp, xxr_para_tmp->len)) + { + LOG_ERROR("fail to parse hex value"); + return ERROR_FAIL; + } + LOG_DEBUG("\t%s = 0x%X", argus[i], (**(int**)pbuffer_tmp) & ((1 << (xxr_para_tmp->len)) - 1)); + } + // If a command changes the length of the last scan of the same type and the MASK parameter is absent, + // the mask pattern used is all cares + if (!(xxr_para_tmp->data_mask & XXR_MASK) && (i_tmp != xxr_para_tmp->len)) + { + // MASK not defined and length changed + if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len)) + { + LOG_ERROR("fail to adjust length of array"); + return ERROR_FAIL; + } + buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len); + } + // do scan if necessary + if (SDR == command) + { + // check buffer size first, reallocate if necessary + i = svf_para.hdr_para.len + svf_para.sdr_para.len + svf_para.tdr_para.len; + if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) + { +#if 1 + // simply print error message + LOG_ERROR("buffer is not enough, report to author"); + return ERROR_FAIL; +#else + u8 *buffer_tmp; + + // reallocate buffer + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdi_buffer, svf_buffer_index); + // svf_tdi_buffer isn't NULL here + free(svf_tdi_buffer); + svf_tdi_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdo_buffer, svf_buffer_index); + // svf_tdo_buffer isn't NULL here + free(svf_tdo_buffer); + svf_tdo_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_mask_buffer, svf_buffer_index); + // svf_mask_buffer isn't NULL here + free(svf_mask_buffer); + svf_mask_buffer = buffer_tmp; + + buffer_tmp = NULL; + svf_buffer_size = svf_buffer_index + ((i + 7) >> 3); +#endif + } + + // assemble dr data + i = 0; + buf_set_buf(svf_para.hdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hdr_para.len); + i += svf_para.hdr_para.len; + buf_set_buf(svf_para.sdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sdr_para.len); + i += svf_para.sdr_para.len; + buf_set_buf(svf_para.tdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tdr_para.len); + i += svf_para.tdr_para.len; + + // add check data + if (svf_para.sdr_para.data_mask & XXR_TDO) + { + // assemble dr mask data + i = 0; + buf_set_buf(svf_para.hdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hdr_para.len); + i += svf_para.hdr_para.len; + buf_set_buf(svf_para.sdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sdr_para.len); + i += svf_para.sdr_para.len; + buf_set_buf(svf_para.tdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tdr_para.len); + i += svf_para.tdr_para.len; + // assemble dr check data + i = 0; + buf_set_buf(svf_para.hdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hdr_para.len); + i += svf_para.hdr_para.len; + buf_set_buf(svf_para.sdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sdr_para.len); + i += svf_para.sdr_para.len; + buf_set_buf(svf_para.tdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tdr_para.len); + i += svf_para.tdr_para.len; + + svf_add_check_para(1, svf_buffer_index, i); + } + else + { + 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.out_mask = NULL; + field.in_value = &svf_tdi_buffer[svf_buffer_index]; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state); + + svf_buffer_index += (i + 7) >> 3; + } + else if (SIR == command) + { + // check buffer size first, reallocate if necessary + i = svf_para.hir_para.len + svf_para.sir_para.len + svf_para.tir_para.len; + if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) + { +#if 1 + // simply print error message + LOG_ERROR("buffer is not enough, report to author"); + return ERROR_FAIL; +#else + u8 *buffer_tmp; + + // reallocate buffer + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdi_buffer, svf_buffer_index); + // svf_tdi_buffer isn't NULL here + free(svf_tdi_buffer); + svf_tdi_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdo_buffer, svf_buffer_index); + // svf_tdo_buffer isn't NULL here + free(svf_tdo_buffer); + svf_tdo_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_mask_buffer, svf_buffer_index); + // svf_mask_buffer isn't NULL here + free(svf_mask_buffer); + svf_mask_buffer = buffer_tmp; + + buffer_tmp = NULL; + svf_buffer_size = svf_buffer_index + ((i + 7) >> 3); +#endif + } + + // assemble ir data + i = 0; + buf_set_buf(svf_para.hir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hir_para.len); + i += svf_para.hir_para.len; + buf_set_buf(svf_para.sir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sir_para.len); + i += svf_para.sir_para.len; + buf_set_buf(svf_para.tir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tir_para.len); + i += svf_para.tir_para.len; + + // add check data + if (svf_para.sir_para.data_mask & XXR_TDO) + { + // assemble dr mask data + i = 0; + buf_set_buf(svf_para.hir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hir_para.len); + i += svf_para.hir_para.len; + buf_set_buf(svf_para.sir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sir_para.len); + i += svf_para.sir_para.len; + buf_set_buf(svf_para.tir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tir_para.len); + i += svf_para.tir_para.len; + // assemble dr check data + i = 0; + buf_set_buf(svf_para.hir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hir_para.len); + i += svf_para.hir_para.len; + buf_set_buf(svf_para.sir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sir_para.len); + i += svf_para.sir_para.len; + buf_set_buf(svf_para.tir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tir_para.len); + i += svf_para.tir_para.len; + + svf_add_check_para(1, svf_buffer_index, i); + } + else + { + 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.out_mask = NULL; + field.in_value = &svf_tdi_buffer[svf_buffer_index]; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state); + + svf_buffer_index += (i + 7) >> 3; + } + break; + case PIO: + case PIOMAP: + LOG_ERROR("PIO and PIOMAP are not supported"); + return ERROR_FAIL; + break; + case RUNTEST: + // RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time SEC]] [ENDSTATE end_state] + // RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE end_state] + if ((num_of_argu < 3) && (num_of_argu > 11)) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + // init + run_count = 0; + min_time = 0; + max_time = 0; + i = 1; + // run_state + i_tmp = svf_find_string_in_array(argus[i], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (svf_tap_state_is_valid(i_tmp)) + { + if (svf_tap_state_is_stable(i_tmp)) + { + svf_para.runtest_run_state = i_tmp; + + // When a run_state is specified, the new run_state becomes the default end_state + svf_para.runtest_end_state = i_tmp; + LOG_DEBUG("\trun_state = %s", svf_tap_state_name[svf_para.runtest_run_state]); + i++; + } + else + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[i_tmp]); + return ERROR_FAIL; + } + } + // run_count run_clk + if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC")) + { + if (!strcmp(argus[i + 1], "TCK")) + { + // clock source is TCK + run_count = atoi(argus[i]); + LOG_DEBUG("\trun_count@TCK = %d", run_count); + } + else + { + LOG_ERROR("%s not supported for clock", argus[i + 1]); + return ERROR_FAIL; + } + i += 2; + } + // min_time SEC + if (((i + 2) <= num_of_argu) && !strcmp(argus[i + 1], "SEC")) + { + min_time = atof(argus[i]); + LOG_DEBUG("\tmin_time = %fs", min_time); + i += 2; + } + // MAXIMUM max_time SEC + if (((i + 3) <= num_of_argu) && !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC")) + { + max_time = atof(argus[i + 1]); + LOG_DEBUG("\tmax_time = %fs", max_time); + i += 3; + } + // ENDSTATE end_state + if (((i + 2) <= num_of_argu) && !strcmp(argus[i], "ENDSTATE")) + { + i_tmp = svf_find_string_in_array(argus[i + 1], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (svf_tap_state_is_stable(i_tmp)) + { + svf_para.runtest_end_state = i_tmp; + LOG_DEBUG("\tend_state = %s", svf_tap_state_name[svf_para.runtest_end_state]); + } + else + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[i_tmp]); + return ERROR_FAIL; + } + i += 2; + } + // calculate run_count + if ((0 == run_count) && (min_time > 0)) + { + run_count = min_time * svf_para.frequency; + } + // all parameter should be parsed + if (i == num_of_argu) + { + if (run_count > 0) + { + // TODO: do runtest + 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); + } + } + else + { + LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed", i, num_of_argu); + return ERROR_FAIL; + } + break; + case STATE: + // STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state + if (num_of_argu < 2) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + if (num_of_argu > 2) + { + // STATE pathstate1 ... stable_state + path = (tap_state_t *)malloc((num_of_argu - 1) * sizeof(tap_state_t)); + if (NULL == path) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + for (i = 1; 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])) + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i - 1]]); + return ERROR_FAIL; + } + if (TAP_RESET == path[i - 1]) + { + LOG_ERROR("TAP_RESET is not allowed in pathmove"); + return ERROR_FAIL; + } + } + 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 - 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; + } + if (NULL != path) + { + free(path); + path = NULL; + } + } + else + { + // STATE stable_state + 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 + 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 = state; + + LOG_DEBUG("\tmove to %s by state_move", svf_tap_state_name[state]); + } + else + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[state]); + return ERROR_FAIL; + } + } + break; + case TRST: + // TRST trst_mode + if (num_of_argu != 2) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + if (svf_para.trst_mode != TRST_ABSENT) + { + 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: + jtag_add_reset(1, 0); + break; + case TRST_OFF: + jtag_add_reset(1, 1); + break; + case TRST_Z: + break; + case TRST_ABSENT: + break; + default: + LOG_ERROR("unknown TRST mode: %s", argus[1]); + return ERROR_FAIL; + } + svf_para.trst_mode = i_tmp; + LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name[svf_para.trst_mode]); + } + else + { + LOG_ERROR("can not accpet TRST command if trst_mode is ABSENT"); + return ERROR_FAIL; + } + break; + default: + LOG_ERROR("invalid svf command: %s", argus[0]); + return ERROR_FAIL; + break; + } + + if (debug_level >= LOG_LVL_DEBUG) + { + // for convenient debugging, execute tap if possible + if ((svf_buffer_index > 0) && \ + (((command != STATE) && (command != RUNTEST)) || \ + ((command == STATE) && (num_of_argu == 2)))) + { + // there is data to be executed + if (ERROR_OK != jtag_execute_queue()) + { + return ERROR_FAIL; + } + // output debug info + if ((SIR == command) || (SDR == command)) + { + 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 + { + // for fast executing, execute tap if necessary + // half of the buffer is for the next command + if (((svf_buffer_index >= SVF_MAX_BUFFER_SIZE_TO_COMMIT) || (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE / 2)) && \ + (((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 ERROR_OK; +} diff --git a/src/svf/svf.h b/src/svf/svf.h new file mode 100644 index 00000000..822cad22 --- /dev/null +++ b/src/svf/svf.h @@ -0,0 +1,27 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef SVF_H +#define SVF_H + +#include "command.h" + +extern int svf_register_commands(struct command_context_s *cmd_ctx); + +#endif /* SVF_H */ |