1 /***************************************************************************
2 * Copyright (C) 2004 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
24 /* project specific includes */
28 #include "configuration.h"
41 /* enable this to debug io latency
44 #define _DEBUG_USB_IO_
47 int ftdi2232_execute_queue(void);
49 int ftdi2232_speed(int speed
);
50 int ftdi2232_register_commands(struct command_context_s
*cmd_ctx
);
51 int ftdi2232_init(void);
52 int ftdi2232_quit(void);
54 enum { FTDI2232_TRST
= 0x10, FTDI2232_SRST
= 0x40 };
55 static u8 discrete_output
= 0x0 | FTDI2232_TRST
| FTDI2232_SRST
;
56 static struct ftdi_context ftdic
;
58 static u8
*ftdi2232_buffer
= NULL
;
59 static int ftdi2232_buffer_size
= 0;
60 static int ftdi2232_read_pointer
= 0;
61 static int ftdi2232_expect_read
= 0;
62 #define FTDI2232_BUFFER_SIZE 131072
63 #define BUFFER_ADD ftdi2232_buffer[ftdi2232_buffer_size++]
64 #define BUFFER_READ ftdi2232_buffer[ftdi2232_read_pointer++]
66 #define FTDI2232_SAVE_SIZE 1024
68 int ftdi2232_handle_vid_pid_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
70 static u16 ftdi2232_vid
= 0x0403;
71 static u16 ftdi2232_pid
= 0x6010;
73 jtag_interface_t ftdi2232_interface
=
78 .execute_queue
= ftdi2232_execute_queue
,
80 .support_statemove
= 1,
82 .speed
= ftdi2232_speed
,
83 .register_commands
= ftdi2232_register_commands
,
84 .init
= ftdi2232_init
,
85 .quit
= ftdi2232_quit
,
88 int ftdi2232_speed(int speed
)
92 buf
[0] = 0x86; /* command "set divisor" */
93 buf
[1] = speed
& 0xff; /* valueL (0=6MHz, 1=3MHz, 2=1.5MHz, ...*/
94 buf
[2] = (speed
>> 8) & 0xff; /* valueH */
96 DEBUG("%2.2x %2.2x %2.2x", buf
[0], buf
[1], buf
[2]);
97 ftdi_write_data(&ftdic
, buf
, 3);
102 int ftdi2232_register_commands(struct command_context_s
*cmd_ctx
)
104 register_command(cmd_ctx
, NULL
, "ftdi2232_vid_pid", ftdi2232_handle_vid_pid_command
,
105 COMMAND_CONFIG
, NULL
);
110 void ftdi2232_end_state(state
)
112 if (tap_move_map
[state
] != -1)
116 ERROR("BUG: %i is not a valid end state", state
);
121 void ftdi2232_read_scan(enum scan_type type
, u8
* buffer
, int scan_size
)
123 int num_bytes
= ((scan_size
+ 7) / 8);
124 int bits_left
= scan_size
;
127 while(num_bytes
-- > 1)
129 buffer
[cur_byte
] = BUFFER_READ
;
134 buffer
[cur_byte
] = 0x0;
138 buffer
[cur_byte
] = BUFFER_READ
>> 1;
141 buffer
[cur_byte
] = (buffer
[cur_byte
] | ((BUFFER_READ
& 0x02) << 6)) >> (8 - bits_left
);
145 void ftdi2232_debug_dump_buffer(void)
148 for (i
= 0; i
< ftdi2232_buffer_size
; i
++)
150 printf("%2.2x ", ftdi2232_buffer
[i
]);
158 int ftdi2232_send_and_recv(jtag_command_t
*first
, jtag_command_t
*last
)
166 BUFFER_ADD
= 0x87; /* send immediate command */
168 if (ftdi2232_buffer_size
> FTDI2232_SAVE_SIZE
)
170 ERROR("BUG: ftdi2232_buffer grew beyond %i byte (%i) - this is going to fail", FTDI2232_SAVE_SIZE
, ftdi2232_buffer_size
);
173 #ifdef _DEBUG_USB_IO_
174 DEBUG("write buffer (size %i):", ftdi2232_buffer_size
);
175 ftdi2232_debug_dump_buffer();
178 if ((retval
= ftdi_write_data(&ftdic
, ftdi2232_buffer
, ftdi2232_buffer_size
)) < 0)
180 ERROR("ftdi_write_data returned %i", retval
);
184 if (ftdi2232_expect_read
)
187 ftdi2232_buffer_size
= 0;
189 while ((ftdi2232_buffer_size
< ftdi2232_expect_read
) && timeout
)
191 ftdi2232_buffer_size
+= ftdi_read_data(&ftdic
, ftdi2232_buffer
+ ftdi2232_buffer_size
, FTDI2232_BUFFER_SIZE
- ftdi2232_buffer_size
);
195 if (ftdi2232_expect_read
!= ftdi2232_buffer_size
)
197 ERROR("ftdi2232_expect_read (%i) != ftdi2232_buffer_size (%i) (%i retries)", ftdi2232_expect_read
, ftdi2232_buffer_size
, 100 - timeout
);
198 ftdi2232_debug_dump_buffer();
203 #ifdef _DEBUG_USB_IO_
204 DEBUG("read buffer (%i retries): %i bytes", 100 - timeout
, ftdi2232_buffer_size
);
205 ftdi2232_debug_dump_buffer();
209 ftdi2232_expect_read
= 0;
210 ftdi2232_read_pointer
= 0;
218 type
= jtag_scan_type(cmd
->cmd
.scan
);
219 if (type
!= SCAN_OUT
)
221 scan_size
= jtag_scan_size(cmd
->cmd
.scan
);
222 buffer
= calloc(CEIL(scan_size
, 8), 1);
223 ftdi2232_read_scan(type
, buffer
, scan_size
);
224 jtag_read_buffer(buffer
, cmd
->cmd
.scan
);
234 ftdi2232_buffer_size
= 0;
239 void ftdi2232_add_scan(int ir_scan
, enum scan_type type
, u8
*buffer
, int scan_size
)
241 int num_bytes
= (scan_size
+ 7) / 8;
242 int bits_left
= scan_size
;
246 /* command "Clock Data to TMS/CS Pin (no Read)" */
253 BUFFER_ADD
= TAP_MOVE(cur_state
, TAP_SI
);
258 BUFFER_ADD
= TAP_MOVE(cur_state
, TAP_SD
);
261 //DEBUG("added TMS scan (no read)");
263 /* add command for complete bytes */
268 /* Clock Data Bytes In and Out LSB First */
270 //DEBUG("added TDI bytes (io %i)", num_bytes);
272 else if (type
== SCAN_OUT
)
274 /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
276 //DEBUG("added TDI bytes (o)");
278 else if (type
== SCAN_IN
)
280 /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
282 //DEBUG("added TDI bytes (i %i)", num_bytes);
284 BUFFER_ADD
= (num_bytes
-2) & 0xff;
285 BUFFER_ADD
= ((num_bytes
-2) >> 8) & 0xff;
289 /* add complete bytes */
290 while(num_bytes
-- > 1)
292 BUFFER_ADD
= buffer
[cur_byte
];
299 bits_left
-= 8 * (num_bytes
- 1);
302 /* the most signifcant bit is scanned during TAP movement */
304 last_bit
= (buffer
[cur_byte
] >> (bits_left
- 1)) & 0x1;
308 /* process remaining bits but the last one */
313 /* Clock Data Bits In and Out LSB First */
315 //DEBUG("added TDI bits (io) %i", bits_left - 1);
317 else if (type
== SCAN_OUT
)
319 /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
321 //DEBUG("added TDI bits (o)");
323 else if (type
== SCAN_IN
)
325 /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
327 //DEBUG("added TDI bits (i %i)", bits_left - 1);
329 BUFFER_ADD
= bits_left
- 2;
331 BUFFER_ADD
= buffer
[cur_byte
];
334 /* move from Shift-IR/DR to end state */
335 if (type
!= SCAN_OUT
)
337 /* Clock Data to TMS/CS Pin with Read */
339 //DEBUG("added TMS scan (read)");
343 /* Clock Data to TMS/CS Pin (no Read) */
345 //DEBUG("added TMS scan (no read)");
348 BUFFER_ADD
= TAP_MOVE(cur_state
, end_state
) | (last_bit
<< 7);
349 cur_state
= end_state
;
353 int ftdi2232_predict_scan_out(int scan_size
, enum scan_type type
)
355 int predicted_size
= 6;
356 if (type
== SCAN_IN
) /* only from device to host */
358 predicted_size
+= (CEIL(scan_size
, 8) > 1) ? 3 : 0;
359 predicted_size
+= ((scan_size
- 1) % 8) ? 2 : 0;
361 else /* host to device, or bidirectional */
363 predicted_size
+= (CEIL(scan_size
, 8) > 1) ? (CEIL(scan_size
, 8) + 3 - 1) : 0;
364 predicted_size
+= ((scan_size
- 1) % 8) ? 3 : 0;
367 return predicted_size
;
370 int ftdi2232_predict_scan_in(int scan_size
, enum scan_type type
)
372 int predicted_size
= 0;
374 if (type
!= SCAN_OUT
)
377 predicted_size
+= (CEIL(scan_size
, 8) > 1) ? (CEIL(scan_size
, 8) - 1) : 0;
378 /* remaining bits - 1 */
379 predicted_size
+= ((scan_size
- 1) % 8) ? 1 : 0;
380 /* last bit (from TMS scan) */
384 //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size);
386 return predicted_size
;
389 int ftdi2232_execute_queue()
391 jtag_command_t
*cmd
= jtag_command_queue
; /* currently processed command */
392 jtag_command_t
*first_unsent
= cmd
; /* next command that has to be sent */
394 int scan_size
; /* size of IR or DR scan */
397 int predicted_size
= 0;
398 int require_send
= 0;
400 ftdi2232_buffer_size
= 0;
401 ftdi2232_expect_read
= 0;
408 if (cmd
->cmd
.end_state
->end_state
!= -1)
409 ftdi2232_end_state(cmd
->cmd
.end_state
->end_state
);
412 /* only send the maximum buffer size that FT2232C can handle */
414 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
416 ftdi2232_send_and_recv(first_unsent
, cmd
);
421 if (cmd
->cmd
.reset
->trst
== 1)
424 discrete_output
&= ~FTDI2232_TRST
;
426 else if (cmd
->cmd
.reset
->trst
== 0)
428 discrete_output
|= FTDI2232_TRST
;
431 if (cmd
->cmd
.reset
->srst
== 1)
432 discrete_output
&= ~FTDI2232_SRST
;
433 else if (cmd
->cmd
.reset
->srst
== 0)
434 discrete_output
|= FTDI2232_SRST
;
435 /* command "set data bits low byte" */
437 /* value (TMS=1,TCK=0, TDI=0, TRST/SRST */
438 BUFFER_ADD
= 0x08 | discrete_output
;
439 /* dir (output=1), TCK/TDI/TMS=out, TDO=in, TRST/SRST=out */
440 BUFFER_ADD
= 0x0b | FTDI2232_SRST
| FTDI2232_TRST
;
444 /* only send the maximum buffer size that FT2232C can handle */
446 if (cur_state
!= TAP_RTI
)
448 predicted_size
+= 3 * CEIL(cmd
->cmd
.runtest
->num_cycles
, 7);
449 if ((cmd
->cmd
.runtest
->end_state
!= -1) && (cmd
->cmd
.runtest
->end_state
!= TAP_RTI
))
451 if ((cmd
->cmd
.runtest
->end_state
== -1) && (end_state
!= TAP_RTI
))
453 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
455 ftdi2232_send_and_recv(first_unsent
, cmd
);
459 if (cur_state
!= TAP_RTI
)
461 /* command "Clock Data to TMS/CS Pin (no Read)" */
466 BUFFER_ADD
= TAP_MOVE(cur_state
, TAP_RTI
);
470 i
= cmd
->cmd
.runtest
->num_cycles
;
473 /* command "Clock Data to TMS/CS Pin (no Read)" */
476 BUFFER_ADD
= (i
> 7) ? 6 : (i
- 1);
480 i
-= (i
> 7) ? 7 : i
;
481 //DEBUG("added TMS scan (no read)");
483 if (cmd
->cmd
.runtest
->end_state
!= -1)
484 ftdi2232_end_state(cmd
->cmd
.runtest
->end_state
);
485 if (cur_state
!= end_state
)
487 /* command "Clock Data to TMS/CS Pin (no Read)" */
492 BUFFER_ADD
= TAP_MOVE(cur_state
, end_state
);
493 cur_state
= end_state
;
494 //DEBUG("added TMS scan (no read)");
499 /* only send the maximum buffer size that FT2232C can handle */
501 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
503 ftdi2232_send_and_recv(first_unsent
, cmd
);
507 if (cmd
->cmd
.statemove
->end_state
!= -1)
508 ftdi2232_end_state(cmd
->cmd
.statemove
->end_state
);
509 /* command "Clock Data to TMS/CS Pin (no Read)" */
514 BUFFER_ADD
= TAP_MOVE(cur_state
, end_state
);
515 //DEBUG("added TMS scan (no read)");
516 cur_state
= end_state
;
520 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
521 type
= jtag_scan_type(cmd
->cmd
.scan
);
522 predicted_size
= ftdi2232_predict_scan_out(scan_size
, type
);
523 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
525 ftdi2232_send_and_recv(first_unsent
, cmd
);
529 ftdi2232_expect_read
+= ftdi2232_predict_scan_in(scan_size
, type
);
530 //DEBUG("new read size: %i", ftdi2232_expect_read);
531 if (cmd
->cmd
.scan
->end_state
!= -1)
532 ftdi2232_end_state(cmd
->cmd
.scan
->end_state
);
533 ftdi2232_add_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
539 jtag_sleep(cmd
->cmd
.sleep
->us
);
542 ERROR("BUG: unknown JTAG command type encountered");
548 if (require_send
> 0)
549 ftdi2232_send_and_recv(first_unsent
, cmd
);
554 int ftdi2232_init(void)
556 if (ftdi_init(&ftdic
) < 0)
557 return ERROR_JTAG_INIT_FAILED
;
559 /* context, vendor id, product id */
560 if (ftdi_usb_open(&ftdic
, ftdi2232_vid
, ftdi2232_pid
) < 0)
562 ERROR("unable to open ftdi device: %s", ftdic
.error_str
);
563 return ERROR_JTAG_INIT_FAILED
;
566 if (ftdi_usb_reset(&ftdic
) < 0)
568 ERROR("unable to reset ftdi device");
569 return ERROR_JTAG_INIT_FAILED
;
572 if (ftdi_set_latency_timer(&ftdic
, 1) < 0)
574 ERROR("unable to set latency timer");
575 return ERROR_JTAG_INIT_FAILED
;
578 ftdi2232_buffer_size
= 0;
579 ftdi2232_buffer
= malloc(FTDI2232_BUFFER_SIZE
);
581 ftdic
.bitbang_mode
= 0; /* Reset controller */
582 ftdi_enable_bitbang(&ftdic
, 0x0b | FTDI2232_SRST
| FTDI2232_TRST
); /* ctx, i/o mask (out=1, in=0) */
584 ftdic
.bitbang_mode
= 2; /* MPSSE mode */
585 ftdi_enable_bitbang(&ftdic
, 0x0b | FTDI2232_SRST
| FTDI2232_TRST
); /* ctx, i/o mask (out=1, in=0) */
587 if (ftdi_usb_purge_buffers(&ftdic
) < 0)
589 ERROR("ftdi_purge_buffers: %s", ftdic
.error_str
);
590 return ERROR_JTAG_INIT_FAILED
;
593 /* initialize low byte for jtag */
594 BUFFER_ADD
= 0x80; /* command "set data bits low byte" */
595 BUFFER_ADD
= 0x08 | FTDI2232_SRST
| FTDI2232_TRST
; /* value (TMS=1,TCK=0, TDI=0, xRST high) */
596 BUFFER_ADD
= 0x0b | FTDI2232_SRST
| FTDI2232_TRST
; /* dir (output=1), TCK/TDI/TMS=out, TDO=in */
597 BUFFER_ADD
= 0x85; /* command "Disconnect TDI/DO to TDO/DI for Loopback" */
598 ftdi2232_debug_dump_buffer();
599 if (ftdi_write_data(&ftdic
, ftdi2232_buffer
, ftdi2232_buffer_size
) != 4)
600 return ERROR_JTAG_INIT_FAILED
;
602 ftdi2232_speed(jtag_speed
);
607 int ftdi2232_quit(void)
609 ftdi_disable_bitbang(&ftdic
);
611 ftdi_usb_close(&ftdic
);
615 free(ftdi2232_buffer
);
620 int ftdi2232_handle_vid_pid_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
624 ftdi2232_vid
= strtol(args
[0], NULL
, 0);
625 ftdi2232_pid
= strtol(args
[1], NULL
, 0);
629 WARNING("incomplete ftdi2232_vid_pid configuration directive");
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)