summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jtag/vsllink.c226
1 files changed, 142 insertions, 84 deletions
diff --git a/src/jtag/vsllink.c b/src/jtag/vsllink.c
index de4220f7..7c224443 100644
--- a/src/jtag/vsllink.c
+++ b/src/jtag/vsllink.c
@@ -44,7 +44,7 @@
#endif
#ifdef _DEBUG_JTAG_IO_
-#define DEBUG_JTAG_IO(expr ...) LOG_DEBUG(expr)
+#define DEBUG_JTAG_IO(expr ...) LOG_DEBUG(expr)
#else
#define DEBUG_JTAG_IO(expr ...)
#endif
@@ -54,7 +54,7 @@ u16 vsllink_pid;
u8 vsllink_bulkout;
u8 vsllink_bulkin;
-#define VSLLINK_USB_TIMEOUT 5000
+#define VSLLINK_USB_TIMEOUT 10000
static int VSLLINK_BufferSize = 1024;
@@ -76,7 +76,7 @@ static u8* vsllink_usb_out_buffer = NULL;
#define VSLLINK_CMD_HW_SWDCMD 0xA2
#define VSLLINK_CMDJTAGSEQ_TMSBYTE 0x00
-#define VSLLINK_CMDJTAGSEQ_TMS0BYTE 0x40
+#define VSLLINK_CMDJTAGSEQ_TMSCLOCK 0x40
#define VSLLINK_CMDJTAGSEQ_SCAN 0x80
#define VSLLINK_CMDJTAGSEQ_CMDMSK 0xC0
@@ -92,7 +92,7 @@ static u8* vsllink_usb_out_buffer = NULL;
#define JTAG_PINMSK_TDO (1 << 7)
-#define VSLLINK_TAP_MOVE(from, to) VSLLINK_tap_move[tap_move_map[from]][tap_move_map[to]]
+#define VSLLINK_TAP_MOVE(from, to) VSLLINK_tap_move[tap_move_map[from]][tap_move_map[to]]
/* VSLLINK_tap_move[i][j]: tap movement command to go from state i to state j
* 0: Test-Logic-Reset
@@ -206,6 +206,7 @@ void vsllink_end_state(enum tap_state state);
void vsllink_state_move(void);
void vsllink_path_move(int num_states, enum tap_state *path);
void vsllink_runtest(int num_cycles);
+void vsllink_stableclocks(int num_cycles, int tms);
void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, scan_command_t *command);
void vsllink_reset(int trst, int srst);
void vsllink_simple_command(u8 command);
@@ -257,7 +258,7 @@ int vsllink_execute_queue(void)
enum scan_type type;
u8 *buffer;
- DEBUG_JTAG_IO("--------------------------------------------------------------------------------");
+ DEBUG_JTAG_IO("--------------------------------- vsllink -------------------------------------");
vsllink_usb_out_buffer[0] = VSLLINK_CMD_HW_JTAGSEQCMD;
vsllink_usb_out_buffer_idx = 3;
@@ -332,7 +333,7 @@ int vsllink_execute_queue(void)
DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
vsllink_tap_execute();
-
+
if (cmd->cmd.reset->trst == 1)
{
cur_state = TAP_RESET;
@@ -348,9 +349,33 @@ int vsllink_execute_queue(void)
vsllink_tap_execute();
jtag_sleep(cmd->cmd.sleep->us);
break;
-
+
+ case JTAG_STABLECLOCKS:
+ DEBUG_JTAG_IO("add %d clocks", cmd->cmd.stableclocks->num_cycles);
+ switch(cur_state)
+ {
+ case TAP_RESET:
+ // tms should be '1' to stay in TAP_RESET mode
+ scan_size = 1;
+ break;
+ case TAP_DRSHIFT:
+ case TAP_IDLE:
+ case TAP_DRPAUSE:
+ case TAP_IRSHIFT:
+ case TAP_IRPAUSE:
+ // in other mode, tms should be '0'
+ scan_size = 0;
+ break; /* above stable states are OK */
+ default:
+ LOG_ERROR( "jtag_add_clocks() was called with TAP in non-stable state \"%s\"",
+ jtag_state_name(cur_state) );
+ exit(-1);
+ }
+ vsllink_stableclocks(cmd->cmd.stableclocks->num_cycles, scan_size);
+ break;
+
default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
+ LOG_ERROR("BUG: unknown JTAG command type encountered: %d", cmd->type);
exit(-1);
}
cmd = cmd->next;
@@ -752,91 +777,93 @@ void vsllink_path_move(int num_states, enum tap_state *path)
}
}
-void vsllink_runtest(int num_cycles)
+void vsllink_stableclocks(int num_cycles, int tms)
{
int tms_len;
- enum tap_state saved_end_state = end_state;
+ u16 tms_append_byte;
- if (cur_state != TAP_IDLE)
- {
- // enter into IDLE state
- vsllink_end_state(TAP_IDLE);
- vsllink_state_move();
- }
- else
+ if (vsllink_tms_data_len > 0)
{
- // cur_state == TAP_IDLE
- if (vsllink_tms_data_len > 0)
+ // 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 > 0)
+ {
+ // append '1' for tms
+ tms_append_byte = (u16)((((1 << num_cycles) - 1) << vsllink_tms_data_len) & 0xFFFF);
+ }
+ else
+ {
+ // append '0' for tms
+ tms_append_byte = 0;
+ }
+ if (tms_len <= 16)
{
- // 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)
+ // merge into last tms shift
+ if (tms_len < 8)
{
- // 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;
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] |= (u8)(tms_append_byte & 0xFF);
+ }
+ else if (tms_len == 8)
+ {
+ // end last tms shift command
+ // just reduce it, and append last tms byte
+ (*vsllink_tms_cmd_pos)--;
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= (u8)(tms_append_byte & 0xFF);
+ }
+ else if (tms_len < 16)
+ {
+ if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) < VSLLINK_CMDJTAGSEQ_LENMSK)
{
- // just add to vsllink_tms_data_len
- // same result if tun through
- //vsllink_tms_data_len += num_cycles;
+ // 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[vsllink_usb_out_buffer_idx++] |= (u8)(tms_append_byte & 0xFF);
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = (u8)(tms_append_byte >> 8);
}
- else if (tms_len == 8)
+ else
{
- // end last tms shift command
- // just reduce it, no need to append_tms
+ // 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)--;
- 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;
- }
-
- vsllink_tms_data_len = (vsllink_tms_data_len + num_cycles) & 7;
- if (vsllink_tms_data_len == 0)
- {
- vsllink_tms_cmd_pos = NULL;
+ // append last tms byte and move the command pointer to the next empty position
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= (u8)(tms_append_byte & 0xFF);
+ // 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] = (u8)(tms_append_byte >> 8);
}
- num_cycles = 0;
}
- else
+ else if (tms_len == 16)
{
- vsllink_usb_out_buffer_idx++;
- vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = 0;
+ // end last tms shift command
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= (u8)(tms_append_byte & 0xFF);
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (u8)(tms_append_byte >> 8);
+ }
- num_cycles -= 16 - vsllink_tms_data_len;
- vsllink_tms_data_len = 0;
+ vsllink_tms_data_len = tms_len & 7;
+ if (vsllink_tms_data_len == 0)
+ {
vsllink_tms_cmd_pos = NULL;
}
+ num_cycles = 0;
+ }
+ else
+ {
+ // more shifts will be needed
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= (u8)(tms_append_byte & 0xFF);
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (u8)(tms_append_byte >> 8);
+
+ 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
@@ -860,7 +887,15 @@ void vsllink_runtest(int num_cycles)
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;
+ // LSB of the command byte is the tms value when do the shifting
+ if (tms > 0)
+ {
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSCLOCK | 1;
+ }
+ else
+ {
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSCLOCK;
+ }
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;
@@ -873,20 +908,42 @@ void vsllink_runtest(int num_cycles)
if (tms_len > 0xFFFF)
{
vsllink_tap_execute();
- vsllink_usb_out_buffer[0] = VSLLINK_CMD_HW_JTAGSEQCMD;
- vsllink_usb_out_buffer_idx = 3;
}
}
+ // post-process
vsllink_tms_data_len = num_cycles & 7;
if (vsllink_tms_data_len > 0)
{
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;
+ if (tms > 0)
+ {
+ // append '1' for tms
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = (1 << vsllink_tms_data_len) - 1;
+ }
+ else
+ {
+ // append '0' for tms
+ vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0x00;
+ }
}
}
+}
+
+void vsllink_runtest(int num_cycles)
+{
+ enum tap_state saved_end_state = end_state;
+
+ if (cur_state != TAP_IDLE)
+ {
+ // enter into IDLE state
+ vsllink_end_state(TAP_IDLE);
+ vsllink_state_move();
+ }
+
+ vsllink_stableclocks(num_cycles, 0);
// post-process
// set end_state
@@ -1122,8 +1179,6 @@ void vsllink_tap_ensure_space(int scans, int bytes)
if (scans > available_scans || bytes > available_bytes)
{
vsllink_tap_execute();
- vsllink_usb_out_buffer[0] = VSLLINK_CMD_HW_JTAGSEQCMD;
- vsllink_usb_out_buffer_idx = 3;
}
}
@@ -1238,7 +1293,10 @@ int vsllink_tap_execute(void)
vsllink_tap_init();
}
-
+
+ vsllink_usb_out_buffer[0] = VSLLINK_CMD_HW_JTAGSEQCMD;
+ vsllink_usb_out_buffer_idx = 3;
+
return ERROR_OK;
}