- fixed arm926 cp15 command bug (thanks to Vincent Palatin for this patch)
[openocd.git] / src / jtag / ft2232.c
index 7d2fac08900a0f4123d107fb7535d89dce7fe6f5..2a8c7387aab7099360dff52adacdc83ce2ba71b9 100644 (file)
@@ -70,10 +70,12 @@ int ft2232_init(void);
 int ft2232_quit(void);
 
 int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 char *ft2232_device_desc = NULL;
+char *ft2232_serial = NULL;
 char *ft2232_layout = NULL;
 u16 ft2232_vid = 0x0403;
 u16 ft2232_pid = 0x6010;
@@ -90,11 +92,13 @@ typedef struct ft2232_layout_s
 int usbjtag_init(void);
 int jtagkey_init(void);
 int olimex_jtag_init(void);
+int m5960_init(void);
 
 /* reset procedures for supported layouts */
 void usbjtag_reset(int trst, int srst);
 void jtagkey_reset(int trst, int srst);
 void olimex_jtag_reset(int trst, int srst);
+void m5960_reset(int trst, int srst);
 
 /* blink procedures for layouts that support a blinking led */
 void olimex_jtag_blink(void);
@@ -104,8 +108,11 @@ ft2232_layout_t ft2232_layouts[] =
        {"usbjtag", usbjtag_init, usbjtag_reset, NULL},
        {"jtagkey", jtagkey_init, jtagkey_reset, NULL},
        {"jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL},
+       {"oocdlink", jtagkey_init, jtagkey_reset, NULL},
        {"signalyzer", usbjtag_init, usbjtag_reset, NULL},
+       {"evb_lm3s811", usbjtag_init, usbjtag_reset, NULL},
        {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink},
+       {"m5960", m5960_init, m5960_reset, NULL},
        {NULL, NULL, NULL},
 };
 
@@ -154,7 +161,7 @@ int ft2232_write(u8 *buf, int size, u32* bytes_written)
        if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
        {
                *bytes_written = dw_bytes_written;
-               ERROR("FT_Write returned: %i", status);
+               ERROR("FT_Write returned: %lu", status);
                return ERROR_JTAG_DEVICE_ERROR;
        }
        else
@@ -183,15 +190,19 @@ int ft2232_read(u8* buf, int size, u32* bytes_read)
 #if BUILD_FT2232_FTD2XX == 1
        DWORD dw_bytes_read;
        FT_STATUS status;
-       if ((status = FT_Read(ftdih, buf, size, &dw_bytes_read)) != FT_OK)
+       int timeout = 5;
+       *bytes_read = 0;
+
+       while ((*bytes_read < size) && timeout--)
        {
-               *bytes_read = dw_bytes_read; 
-               ERROR("FT_Read returned: %i", status);
-               return ERROR_JTAG_DEVICE_ERROR;
+               if ((status = FT_Read(ftdih, buf, size, &dw_bytes_read)) != FT_OK)
+               {
+                       *bytes_read = 0; 
+                       ERROR("FT_Read returned: %lu", status);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               *bytes_read += dw_bytes_read; 
        }
-       *bytes_read = dw_bytes_read; 
-       return ERROR_OK;        
-
 #elif BUILD_FT2232_LIBFTDI == 1
        int retval;
        int timeout = 100;
@@ -207,8 +218,15 @@ int ft2232_read(u8* buf, int size, u32* bytes_read)
                }
                *bytes_read += retval;
        }
-       return ERROR_OK;        
 #endif
+
+       if (*bytes_read < size)
+       {
+               ERROR("couldn't read the requested number of bytes from FT2232 device (%i < %i)", *bytes_read, size);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       
+       return ERROR_OK;
 }
 
 int ft2232_speed(int speed)
@@ -235,6 +253,8 @@ int ft2232_register_commands(struct command_context_s *cmd_ctx)
 {
        register_command(cmd_ctx, NULL, "ft2232_device_desc", ft2232_handle_device_desc_command,
                COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "ft2232_serial", ft2232_handle_serial_command,
+               COMMAND_CONFIG, NULL);
        register_command(cmd_ctx, NULL, "ft2232_layout", ft2232_handle_layout_command,
                COMMAND_CONFIG, NULL);
        register_command(cmd_ctx, NULL, "ft2232_vid_pid", ft2232_handle_vid_pid_command,
@@ -450,7 +470,7 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
        int cur_byte = 0;
        int last_bit;
 
-       if ((!ir_scan && (cur_state != TAP_SD)) || (ir_scan && (cur_state != TAP_SI)))
+       if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI))))
        {
                /* command "Clock Data to TMS/CS Pin (no Read)" */
                BUFFER_ADD = 0x4b;
@@ -471,8 +491,9 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
        }
        
        /* add command for complete bytes */
-       if (num_bytes > 1)
+       while (num_bytes > 1)
        {
+               int thisrun_bytes;
                if (type == SCAN_IO)
                {
                        /* Clock Data Bytes In and Out LSB First */
@@ -491,24 +512,206 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
                        BUFFER_ADD = 0x28;
                        //DEBUG("added TDI bytes (i %i)", num_bytes);
                }
-               BUFFER_ADD = (num_bytes-2) & 0xff;
-               BUFFER_ADD = ((num_bytes-2) >> 8) & 0xff;
+               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+               num_bytes -= thisrun_bytes;
+               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;
+               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;
+               if (type != SCAN_IN)
+               {
+                       /* add complete bytes */
+                       while(thisrun_bytes-- > 0)
+                       {
+                               BUFFER_ADD = buffer[cur_byte];
+                               cur_byte++;
+                               bits_left -= 8;
+                       }
+               }
+               else /* (type == SCAN_IN) */
+               {
+                       bits_left -= 8 * (thisrun_bytes);
+               }
        }
+       
+       /* the most signifcant bit is scanned during TAP movement */
        if (type != SCAN_IN)
+               last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
+       else
+               last_bit = 0;
+
+       /* process remaining bits but the last one */
+       if (bits_left > 1)
        {
-               /* add complete bytes */
-               while(num_bytes-- > 1)
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
                {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = bits_left - 2;
+               if (type != SCAN_IN)
                        BUFFER_ADD = buffer[cur_byte];
-                       cur_byte++;
-                       bits_left -= 8;
+       }
+
+       if ((ir_scan && (end_state == TAP_SI)) ||
+               (!ir_scan && (end_state == TAP_SD)))
+       {
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
                }
+               BUFFER_ADD = 0x0;
+               BUFFER_ADD = last_bit;
        }
-       if (type == SCAN_IN)
+       else
        {
-               bits_left -= 8 * (num_bytes - 1);
+               /* move from Shift-IR/DR to end state */
+               if (type != SCAN_OUT)
+               {
+                       /* Clock Data to TMS/CS Pin with Read */
+                       BUFFER_ADD = 0x6b;
+                       //DEBUG("added TMS scan (read)");
+               }
+               else
+               {
+                       /* Clock Data to TMS/CS Pin (no Read) */
+                       BUFFER_ADD = 0x4b;
+                       //DEBUG("added TMS scan (no read)");
+               }
+               BUFFER_ADD = 0x6;
+               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
+               cur_state = end_state;
        }
+}
 
+int ft2232_large_scan(scan_command_t *cmd, enum scan_type type, u8 *buffer, int scan_size)
+{
+       int num_bytes = (scan_size + 7) / 8;
+       int bits_left = scan_size;
+       int cur_byte = 0;
+       int last_bit;
+       u8 *receive_buffer = malloc(CEIL(scan_size, 8));
+       u8 *receive_pointer = receive_buffer;
+       u32 bytes_written;
+       u32 bytes_read;
+       int retval;
+       int thisrun_read = 0;
+       
+       if (cmd->ir_scan)
+       {
+               ERROR("BUG: large IR scans are not supported");
+               exit(-1);
+       }
+
+       if (cur_state != TAP_SD)
+       {
+               /* command "Clock Data to TMS/CS Pin (no Read)" */
+               BUFFER_ADD = 0x4b;
+               /* scan 7 bit */
+               BUFFER_ADD = 0x6;
+               /* TMS data bits */
+               BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD);
+               cur_state = TAP_SD;
+       }
+       
+       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+       {
+               ERROR("couldn't write MPSSE commands to FT2232");
+               exit(-1);
+       }
+       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+       ft2232_buffer_size = 0;
+       
+       /* add command for complete bytes */
+       while (num_bytes > 1)
+       {
+               int thisrun_bytes;
+               
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bytes In and Out LSB First */
+                       BUFFER_ADD = 0x39;
+                       //DEBUG("added TDI bytes (io %i)", num_bytes);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x19;
+                       //DEBUG("added TDI bytes (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x28;
+                       //DEBUG("added TDI bytes (i %i)", num_bytes);
+               }
+               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+               thisrun_read = thisrun_bytes;
+               num_bytes -= thisrun_bytes;
+               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;
+               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;
+               if (type != SCAN_IN)
+               {
+                       /* add complete bytes */
+                       while(thisrun_bytes-- > 0)
+                       {
+                               BUFFER_ADD = buffer[cur_byte];
+                               cur_byte++;
+                               bits_left -= 8;
+                       }
+               }
+               else /* (type == SCAN_IN) */
+               {
+                       bits_left -= 8 * (thisrun_bytes);
+               }
+
+               if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+               {
+                       ERROR("couldn't write MPSSE commands to FT2232");
+                       exit(-1);
+               }
+               DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+               ft2232_buffer_size = 0;
+               
+               if (type != SCAN_OUT)
+               {
+                       if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)
+                       {
+                               ERROR("couldn't read from FT2232");
+                               exit(-1);
+                       }
+                       DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);
+                       receive_pointer += bytes_read;
+               }
+       }
+       
+       thisrun_read = 0;
+       
        /* the most signifcant bit is scanned during TAP movement */
        if (type != SCAN_IN)
                last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
@@ -539,30 +742,83 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
                BUFFER_ADD = bits_left - 2;
                if (type != SCAN_IN)
                        BUFFER_ADD = buffer[cur_byte];
+                       
+               if (type != SCAN_OUT)
+                       thisrun_read += 2;
        }
 
-       /* move from Shift-IR/DR to end state */
-       if (type != SCAN_OUT)
+       if (end_state == TAP_SD)
        {
-               /* Clock Data to TMS/CS Pin with Read */
-               BUFFER_ADD = 0x6b;
-               //DEBUG("added TMS scan (read)");
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = 0x0;
+               BUFFER_ADD = last_bit;
        }
        else
        {
-               /* Clock Data to TMS/CS Pin (no Read) */
-               BUFFER_ADD = 0x4b;
-               //DEBUG("added TMS scan (no read)");
+               /* move from Shift-IR/DR to end state */
+               if (type != SCAN_OUT)
+               {
+                       /* Clock Data to TMS/CS Pin with Read */
+                       BUFFER_ADD = 0x6b;
+                       //DEBUG("added TMS scan (read)");
+               }
+               else
+               {
+                       /* Clock Data to TMS/CS Pin (no Read) */
+                       BUFFER_ADD = 0x4b;
+                       //DEBUG("added TMS scan (no read)");
+               }
+               BUFFER_ADD = 0x6;
+               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
+               cur_state = end_state;
        }
-       BUFFER_ADD = 0x6;
-       BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
-       cur_state = end_state;
-
+       
+       if (type != SCAN_OUT)
+               thisrun_read += 1;
+       
+       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+       {
+               ERROR("couldn't write MPSSE commands to FT2232");
+               exit(-1);
+       }
+       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+       ft2232_buffer_size = 0;
+       
+       if (type != SCAN_OUT)
+       {
+               if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)
+               {
+                       ERROR("couldn't read from FT2232");
+                       exit(-1);
+               }
+               DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);
+               receive_pointer += bytes_read;
+       }
+       
+       return ERROR_OK;
 }
 
 int ft2232_predict_scan_out(int scan_size, enum scan_type type)
 {
        int predicted_size = 3;
+       int num_bytes = (scan_size - 1) / 8;
        
        if (cur_state != TAP_SD)
                predicted_size += 3;
@@ -570,14 +826,14 @@ int ft2232_predict_scan_out(int scan_size, enum scan_type type)
        if (type == SCAN_IN)    /* only from device to host */
        {
                /* complete bytes */
-               predicted_size += (CEIL(scan_size, 8) > 1) ? 3 : 0;
+               predicted_size += (CEIL(num_bytes, 65536)) * 3;
                /* remaining bits - 1 (up to 7) */
                predicted_size += ((scan_size - 1) % 8) ? 2 : 0;
        }
        else                                    /* host to device, or bidirectional */
        {
                /* complete bytes */
-               predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) + 3 - 1) : 0;
+               predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3;
                /* remaining bits -1 (up to 7) */
                predicted_size += ((scan_size - 1) % 8) ? 3 : 0;
        }
@@ -718,6 +974,34 @@ void olimex_jtag_reset(int trst, int srst)
     DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
 }
 
+void m5960_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               cur_state = TAP_TLR;
+               low_output &= ~nTRST;
+       }
+       else if (trst == 0)
+       {
+               low_output |= nTRST;
+       }
+
+    if (srst == 1)
+    {
+        low_output |= nSRST;
+    }
+    else if (srst == 0)
+    {
+        low_output &= ~nSRST;
+    }
+
+    /* command "set data bits low byte" */
+    BUFFER_ADD = 0x80;
+    BUFFER_ADD = low_output;
+    BUFFER_ADD = low_direction;
+    DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
+}
+
 int ft2232_execute_queue()
 {
        jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
@@ -862,9 +1146,26 @@ int ft2232_execute_queue()
                                scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
                                type = jtag_scan_type(cmd->cmd.scan);
                                predicted_size = ft2232_predict_scan_out(scan_size, type);
-                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               if ((predicted_size + 1) > FT2232_BUFFER_SIZE)
                                {
-                                       DEBUG("ftd2xx buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd);
+                                       DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)");
+                                       /* unsent commands before this */
+                                       if (first_unsent != cmd)
+                                               ft2232_send_and_recv(first_unsent, cmd);
+                                       
+                                       /* current command */
+                                       if (cmd->cmd.scan->end_state != -1)
+                                               ft2232_end_state(cmd->cmd.scan->end_state);
+                                       ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size);
+                                       require_send = 0;
+                                       first_unsent = cmd->next;
+                                       if (buffer)
+                                               free(buffer);
+                                       break;
+                               }
+                               else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               {
+                                       DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd);
                                        ft2232_send_and_recv(first_unsent, cmd);
                                        require_send = 0;
                                        first_unsent = cmd;
@@ -911,6 +1212,8 @@ int ft2232_init(void)
        
 #if BUILD_FT2232_FTD2XX == 1
        FT_STATUS status;
+       DWORD openex_flags = 0;
+       char *openex_string = NULL;
 #endif
 
        ft2232_layout_t *cur_layout = ft2232_layouts;
@@ -944,13 +1247,6 @@ int ft2232_init(void)
 #endif
 
 #if BUILD_FT2232_FTD2XX == 1
-       /* Open by device description */
-       if (ft2232_device_desc == NULL)
-       {
-               WARNING("no ftd2xx device description specified, using default 'Dual RS232'");
-               ft2232_device_desc = "Dual RS232";
-       }
-       
 #if IS_WIN32 == 0
        /* Add non-standard Vid/Pid to the linux driver */
        if ((status = FT_SetVIDPID(ft2232_vid, ft2232_pid)) != FT_OK)
@@ -959,11 +1255,35 @@ int ft2232_init(void)
        }
 #endif
 
-       if ((status = FT_OpenEx(ft2232_device_desc, FT_OPEN_BY_DESCRIPTION, &ftdih)) != FT_OK)
+       if (ft2232_device_desc && ft2232_serial)
+       {
+               WARNING("can't open by device description and serial number, giving precedence to serial");
+               ft2232_device_desc = NULL;
+       }
+       
+       if (ft2232_device_desc)
+       {
+               openex_string = ft2232_device_desc;
+               openex_flags = FT_OPEN_BY_DESCRIPTION;
+       }
+       else if (ft2232_serial)
+       {
+               openex_string = ft2232_serial;
+               openex_flags = FT_OPEN_BY_SERIAL_NUMBER;
+       }
+       else
+       {
+               ERROR("neither device description nor serial number specified");
+               ERROR("please add \"ft2232_device_desc <string>\" or \"ft2232_serial <string>\" to your .cfg file");
+               
+               return ERROR_JTAG_INIT_FAILED;  
+       }
+
+       if ((status = FT_OpenEx(openex_string, openex_flags, &ftdih)) != FT_OK)
        {
                DWORD num_devices;
                
-               ERROR("unable to open ftdi device: %i", status);
+               ERROR("unable to open ftdi device: %lu", status);
                status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
                if (status == FT_OK)
                {
@@ -974,11 +1294,11 @@ int ft2232_init(void)
                                desc_array[i] = malloc(64);
                        desc_array[num_devices] = NULL;
 
-                       status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
+                       status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags);
 
                        if (status == FT_OK)
                        {
-                               ERROR("ListDevices: %d\n", num_devices);
+                               ERROR("ListDevices: %lu\n", num_devices);
                                for (i = 0; i < num_devices; i++)
                                        ERROR("%i: %s", i, desc_array[i]);
                        }
@@ -996,23 +1316,29 @@ int ft2232_init(void)
 
        if ((status = FT_SetLatencyTimer(ftdih, 2)) != FT_OK)
        {
-               ERROR("unable to set latency timer: %i", status);
+               ERROR("unable to set latency timer: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
        
        if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK)
        {
-               ERROR("unable to get latency timer: %i", status);
+               ERROR("unable to get latency timer: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
        else
        {
                DEBUG("current latency timer: %i", latency_timer);
        }
+       
+       if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK)
+       {
+               ERROR("unable to set timeouts: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
 
        if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK)
        {
-               ERROR("unable to enable bit i/o mode: %i", status);
+               ERROR("unable to enable bit i/o mode: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
 #elif BUILD_FT2232_LIBFTDI == 1
@@ -1020,12 +1346,18 @@ int ft2232_init(void)
                return ERROR_JTAG_INIT_FAILED;
 
        /* context, vendor id, product id */
-       if (ftdi_usb_open(&ftdic, ft2232_vid, ft2232_pid) < 0)
+       if (ftdi_usb_open_desc(&ftdic, ft2232_vid, ft2232_pid, ft2232_device_desc, ft2232_serial) < 0)
        {
                ERROR("unable to open ftdi device: %s", ftdic.error_str);
                return ERROR_JTAG_INIT_FAILED;
        }
 
+       if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0)
+       {
+               ERROR("unable to select FT2232 channel A: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
        if (ftdi_usb_reset(&ftdic) < 0)
        {
                ERROR("unable to reset ftdi device");
@@ -1048,11 +1380,7 @@ int ft2232_init(void)
                DEBUG("current latency timer: %i", latency_timer);
        }
 
-       ftdic.bitbang_mode = 0; /* Reset controller */
-       ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */
-
-       ftdic.bitbang_mode = 2; /* MPSSE mode */
-       ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */
+       ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */
 #endif 
 
        ft2232_buffer_size = 0;
@@ -1073,7 +1401,7 @@ int ft2232_init(void)
 #if BUILD_FT2232_FTD2XX == 1
        if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
        {
-               ERROR("error purging ftd2xx device: %i", status);
+               ERROR("error purging ftd2xx device: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
 #elif BUILD_FT2232_LIBFTDI == 1
@@ -1109,6 +1437,15 @@ int usbjtag_init(void)
                nSRST = 0x20;
                nSRSTnOE = 0x20;
        }
+       else if (strcmp(ft2232_layout, "evb_lm3s811") == 0)
+       {
+               nTRST = 0x0;
+               nTRSTnOE = 0x00;
+               nSRST = 0x20;
+               nSRSTnOE = 0x20;
+               low_output = 0x88;
+               low_direction = 0x8b;
+       }
        else
        {
                ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout);
@@ -1179,7 +1516,8 @@ int jtagkey_init(void)
                nSRST = 0x02;
                nSRSTnOE = 0x08;
        }
-       else if (strcmp(layout->name, "jtagkey_prototype_v1") == 0)
+       else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) ||
+               (strcmp(layout->name, "oocdlink") == 0))
        {
                nTRST = 0x02;
                nTRSTnOE = 0x1;
@@ -1298,6 +1636,52 @@ int olimex_jtag_init(void)
        return ERROR_OK;
 }
 
+int m5960_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x18;
+       low_direction = 0xfb;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE[12]=out, n[ST]srst=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'm5960' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       nTRST = 0x10;
+       nTRSTnOE = 0x0; /* not output enable for nTRST */
+       nSRST = 0x20;
+       nSRSTnOE = 0x00; /* no output enable for nSRST */
+
+       high_output = 0x00;
+       high_direction = 0x0c;
+
+       /* turn red LED1 on, LED2 off */
+       high_output |= 0x08;
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output; /* value */
+       buf[2] = high_direction;   /* all outputs (xRST and xRSTnOE) */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'm5960' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
 void olimex_jtag_blink(void)
 {
        /* Olimex ARM-USB-OCD has a LED connected to ACBUS3
@@ -1352,6 +1736,20 @@ int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *c
        return ERROR_OK;
 }
 
+int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               ft2232_serial = strdup(args[0]);
+       }
+       else
+       {
+               ERROR("expected exactly one argument to ft2232_serial <serial-number>");
+       }
+       
+       return ERROR_OK;
+}
+
 int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        if (argc == 0)

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)