vsllink support for stable clocks by Simon Qian <simonqian@SimonQian.com>
authorkc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Fri, 23 Jan 2009 07:02:47 +0000 (07:02 +0000)
committerkc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Fri, 23 Jan 2009 07:02:47 +0000 (07:02 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@1356 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/jtag/vsllink.c

index de4220f798af8a38b6697ce73c2f478e60e3960b..7c2244434eb86371ad4e043cd5130c5177ae742c 100644 (file)
@@ -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;
 }