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 ***************************************************************************/
21 /* project specific includes */
25 #include "configuration.h"
38 /* enable this to debug io latency
41 #define _DEBUG_USB_IO_
44 int ftdi2232_execute_queue(void);
46 int ftdi2232_speed(int speed
);
47 int ftdi2232_register_commands(struct command_context_s
*cmd_ctx
);
48 int ftdi2232_init(void);
49 int ftdi2232_quit(void);
51 enum { FTDI2232_TRST
= 0x10, FTDI2232_SRST
= 0x40 };
52 static u8 discrete_output
= 0x0 | FTDI2232_TRST
| FTDI2232_SRST
;
53 static struct ftdi_context ftdic
;
55 static u8
*ftdi2232_buffer
= NULL
;
56 static int ftdi2232_buffer_size
= 0;
57 static int ftdi2232_read_pointer
= 0;
58 static int ftdi2232_expect_read
= 0;
59 #define FTDI2232_BUFFER_SIZE 131072
60 #define BUFFER_ADD ftdi2232_buffer[ftdi2232_buffer_size++]
61 #define BUFFER_READ ftdi2232_buffer[ftdi2232_read_pointer++]
63 #define FTDI2232_SAVE_SIZE 1024
65 int ftdi2232_handle_vid_pid_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
67 static u16 ftdi2232_vid
= 0x0403;
68 static u16 ftdi2232_pid
= 0x6010;
70 jtag_interface_t ftdi2232_interface
=
75 .execute_queue
= ftdi2232_execute_queue
,
77 .support_statemove
= 1,
79 .speed
= ftdi2232_speed
,
80 .register_commands
= ftdi2232_register_commands
,
81 .init
= ftdi2232_init
,
82 .quit
= ftdi2232_quit
,
85 int ftdi2232_speed(int speed
)
89 buf
[0] = 0x86; /* command "set divisor" */
90 buf
[1] = speed
& 0xff; /* valueL (0=6MHz, 1=3MHz, 2=1.5MHz, ...*/
91 buf
[2] = (speed
>> 8) & 0xff; /* valueH */
93 DEBUG("%2.2x %2.2x %2.2x", buf
[0], buf
[1], buf
[2]);
94 ftdi_write_data(&ftdic
, buf
, 3);
99 int ftdi2232_register_commands(struct command_context_s
*cmd_ctx
)
101 register_command(cmd_ctx
, NULL
, "ftdi2232_vid_pid", ftdi2232_handle_vid_pid_command
,
102 COMMAND_CONFIG
, NULL
);
107 void ftdi2232_end_state(state
)
109 if (tap_move_map
[state
] != -1)
113 ERROR("BUG: %i is not a valid end state", state
);
118 void ftdi2232_read_scan(enum scan_type type
, u8
* buffer
, int scan_size
)
120 int num_bytes
= ((scan_size
+ 7) / 8);
121 int bits_left
= scan_size
;
124 while(num_bytes
-- > 1)
126 buffer
[cur_byte
] = BUFFER_READ
;
131 buffer
[cur_byte
] = 0x0;
135 buffer
[cur_byte
] = BUFFER_READ
>> 1;
138 buffer
[cur_byte
] = (buffer
[cur_byte
] | ((BUFFER_READ
& 0x02) << 6)) >> (8 - bits_left
);
142 void ftdi2232_debug_dump_buffer(void)
145 for (i
= 0; i
< ftdi2232_buffer_size
; i
++)
147 printf("%2.2x ", ftdi2232_buffer
[i
]);
155 int ftdi2232_send_and_recv(jtag_command_t
*first
, jtag_command_t
*last
)
163 BUFFER_ADD
= 0x87; /* send immediate command */
165 if (ftdi2232_buffer_size
> FTDI2232_SAVE_SIZE
)
167 ERROR("BUG: ftdi2232_buffer grew beyond %i byte (%i) - this is going to fail", FTDI2232_SAVE_SIZE
, ftdi2232_buffer_size
);
170 #ifdef _DEBUG_USB_IO_
171 DEBUG("write buffer (size %i):", ftdi2232_buffer_size
);
172 ftdi2232_debug_dump_buffer();
175 if ((retval
= ftdi_write_data(&ftdic
, ftdi2232_buffer
, ftdi2232_buffer_size
)) < 0)
177 ERROR("ftdi_write_data returned %i", retval
);
181 if (ftdi2232_expect_read
)
184 ftdi2232_buffer_size
= 0;
186 while ((ftdi2232_buffer_size
< ftdi2232_expect_read
) && timeout
)
188 ftdi2232_buffer_size
+= ftdi_read_data(&ftdic
, ftdi2232_buffer
+ ftdi2232_buffer_size
, FTDI2232_BUFFER_SIZE
- ftdi2232_buffer_size
);
192 if (ftdi2232_expect_read
!= ftdi2232_buffer_size
)
194 ERROR("ftdi2232_expect_read (%i) != ftdi2232_buffer_size (%i) (%i retries)", ftdi2232_expect_read
, ftdi2232_buffer_size
, 100 - timeout
);
195 ftdi2232_debug_dump_buffer();
200 #ifdef _DEBUG_USB_IO_
201 DEBUG("read buffer (%i retries): %i bytes", 100 - timeout
, ftdi2232_buffer_size
);
202 ftdi2232_debug_dump_buffer();
206 ftdi2232_expect_read
= 0;
207 ftdi2232_read_pointer
= 0;
215 type
= jtag_scan_type(cmd
->cmd
.scan
);
216 if (type
!= SCAN_OUT
)
218 scan_size
= jtag_scan_size(cmd
->cmd
.scan
);
219 buffer
= calloc(CEIL(scan_size
, 8), 1);
220 ftdi2232_read_scan(type
, buffer
, scan_size
);
221 jtag_read_buffer(buffer
, cmd
->cmd
.scan
);
231 ftdi2232_buffer_size
= 0;
236 void ftdi2232_add_scan(int ir_scan
, enum scan_type type
, u8
*buffer
, int scan_size
)
238 int num_bytes
= (scan_size
+ 7) / 8;
239 int bits_left
= scan_size
;
243 /* command "Clock Data to TMS/CS Pin (no Read)" */
250 BUFFER_ADD
= TAP_MOVE(cur_state
, TAP_SI
);
255 BUFFER_ADD
= TAP_MOVE(cur_state
, TAP_SD
);
258 //DEBUG("added TMS scan (no read)");
260 /* add command for complete bytes */
265 /* Clock Data Bytes In and Out LSB First */
267 //DEBUG("added TDI bytes (io %i)", num_bytes);
269 else if (type
== SCAN_OUT
)
271 /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
273 //DEBUG("added TDI bytes (o)");
275 else if (type
== SCAN_IN
)
277 /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
279 //DEBUG("added TDI bytes (i %i)", num_bytes);
281 BUFFER_ADD
= (num_bytes
-2) & 0xff;
282 BUFFER_ADD
= ((num_bytes
-2) >> 8) & 0xff;
286 /* add complete bytes */
287 while(num_bytes
-- > 1)
289 BUFFER_ADD
= buffer
[cur_byte
];
296 bits_left
-= 8 * (num_bytes
- 1);
299 /* the most signifcant bit is scanned during TAP movement */
301 last_bit
= (buffer
[cur_byte
] >> (bits_left
- 1)) & 0x1;
305 /* process remaining bits but the last one */
310 /* Clock Data Bits In and Out LSB First */
312 //DEBUG("added TDI bits (io) %i", bits_left - 1);
314 else if (type
== SCAN_OUT
)
316 /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
318 //DEBUG("added TDI bits (o)");
320 else if (type
== SCAN_IN
)
322 /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
324 //DEBUG("added TDI bits (i %i)", bits_left - 1);
326 BUFFER_ADD
= bits_left
- 2;
328 BUFFER_ADD
= buffer
[cur_byte
];
331 /* move from Shift-IR/DR to end state */
332 if (type
!= SCAN_OUT
)
334 /* Clock Data to TMS/CS Pin with Read */
336 //DEBUG("added TMS scan (read)");
340 /* Clock Data to TMS/CS Pin (no Read) */
342 //DEBUG("added TMS scan (no read)");
345 BUFFER_ADD
= TAP_MOVE(cur_state
, end_state
) | (last_bit
<< 7);
346 cur_state
= end_state
;
350 int ftdi2232_predict_scan_out(int scan_size
, enum scan_type type
)
352 int predicted_size
= 6;
353 if (type
== SCAN_IN
) /* only from device to host */
355 predicted_size
+= (CEIL(scan_size
, 8) > 1) ? 3 : 0;
356 predicted_size
+= ((scan_size
- 1) % 8) ? 2 : 0;
358 else /* host to device, or bidirectional */
360 predicted_size
+= (CEIL(scan_size
, 8) > 1) ? (CEIL(scan_size
, 8) + 3 - 1) : 0;
361 predicted_size
+= ((scan_size
- 1) % 8) ? 3 : 0;
364 return predicted_size
;
367 int ftdi2232_predict_scan_in(int scan_size
, enum scan_type type
)
369 int predicted_size
= 0;
371 if (type
!= SCAN_OUT
)
374 predicted_size
+= (CEIL(scan_size
, 8) > 1) ? (CEIL(scan_size
, 8) - 1) : 0;
375 /* remaining bits - 1 */
376 predicted_size
+= ((scan_size
- 1) % 8) ? 1 : 0;
377 /* last bit (from TMS scan) */
381 //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size);
383 return predicted_size
;
386 int ftdi2232_execute_queue()
388 jtag_command_t
*cmd
= jtag_command_queue
; /* currently processed command */
389 jtag_command_t
*first_unsent
= cmd
; /* next command that has to be sent */
391 int scan_size
; /* size of IR or DR scan */
394 int predicted_size
= 0;
395 int require_send
= 0;
397 ftdi2232_buffer_size
= 0;
398 ftdi2232_expect_read
= 0;
405 if (cmd
->cmd
.end_state
->end_state
!= -1)
406 ftdi2232_end_state(cmd
->cmd
.end_state
->end_state
);
409 /* only send the maximum buffer size that FT2232C can handle */
411 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
413 ftdi2232_send_and_recv(first_unsent
, cmd
);
418 if (cmd
->cmd
.reset
->trst
== 1)
421 discrete_output
&= ~FTDI2232_TRST
;
423 else if (cmd
->cmd
.reset
->trst
== 0)
425 discrete_output
|= FTDI2232_TRST
;
428 if (cmd
->cmd
.reset
->srst
== 1)
429 discrete_output
&= ~FTDI2232_SRST
;
430 else if (cmd
->cmd
.reset
->srst
== 0)
431 discrete_output
|= FTDI2232_SRST
;
432 /* command "set data bits low byte" */
434 /* value (TMS=1,TCK=0, TDI=0, TRST/SRST */
435 BUFFER_ADD
= 0x08 | discrete_output
;
436 /* dir (output=1), TCK/TDI/TMS=out, TDO=in, TRST/SRST=out */
437 BUFFER_ADD
= 0x0b | FTDI2232_SRST
| FTDI2232_TRST
;
441 /* only send the maximum buffer size that FT2232C can handle */
443 if (cur_state
!= TAP_RTI
)
445 predicted_size
+= 3 * CEIL(cmd
->cmd
.runtest
->num_cycles
, 7);
446 if ((cmd
->cmd
.runtest
->end_state
!= -1) && (cmd
->cmd
.runtest
->end_state
!= TAP_RTI
))
448 if ((cmd
->cmd
.runtest
->end_state
== -1) && (end_state
!= TAP_RTI
))
450 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
452 ftdi2232_send_and_recv(first_unsent
, cmd
);
456 if (cur_state
!= TAP_RTI
)
458 /* command "Clock Data to TMS/CS Pin (no Read)" */
463 BUFFER_ADD
= TAP_MOVE(cur_state
, TAP_RTI
);
467 i
= cmd
->cmd
.runtest
->num_cycles
;
470 /* command "Clock Data to TMS/CS Pin (no Read)" */
473 BUFFER_ADD
= (i
> 7) ? 6 : (i
- 1);
477 i
-= (i
> 7) ? 7 : i
;
478 //DEBUG("added TMS scan (no read)");
480 if (cmd
->cmd
.runtest
->end_state
!= -1)
481 ftdi2232_end_state(cmd
->cmd
.runtest
->end_state
);
482 if (cur_state
!= end_state
)
484 /* command "Clock Data to TMS/CS Pin (no Read)" */
489 BUFFER_ADD
= TAP_MOVE(cur_state
, end_state
);
490 cur_state
= end_state
;
491 //DEBUG("added TMS scan (no read)");
496 /* only send the maximum buffer size that FT2232C can handle */
498 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
500 ftdi2232_send_and_recv(first_unsent
, cmd
);
504 if (cmd
->cmd
.statemove
->end_state
!= -1)
505 ftdi2232_end_state(cmd
->cmd
.statemove
->end_state
);
506 /* command "Clock Data to TMS/CS Pin (no Read)" */
511 BUFFER_ADD
= TAP_MOVE(cur_state
, end_state
);
512 //DEBUG("added TMS scan (no read)");
513 cur_state
= end_state
;
517 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
518 type
= jtag_scan_type(cmd
->cmd
.scan
);
519 predicted_size
= ftdi2232_predict_scan_out(scan_size
, type
);
520 if (ftdi2232_buffer_size
+ predicted_size
+ 1 > FTDI2232_SAVE_SIZE
)
522 ftdi2232_send_and_recv(first_unsent
, cmd
);
526 ftdi2232_expect_read
+= ftdi2232_predict_scan_in(scan_size
, type
);
527 //DEBUG("new read size: %i", ftdi2232_expect_read);
528 if (cmd
->cmd
.scan
->end_state
!= -1)
529 ftdi2232_end_state(cmd
->cmd
.scan
->end_state
);
530 ftdi2232_add_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
536 jtag_sleep(cmd
->cmd
.sleep
->us
);
539 ERROR("BUG: unknown JTAG command type encountered");
545 if (require_send
> 0)
546 ftdi2232_send_and_recv(first_unsent
, cmd
);
551 int ftdi2232_init(void)
553 if (ftdi_init(&ftdic
) < 0)
554 return ERROR_JTAG_INIT_FAILED
;
556 /* context, vendor id, product id */
557 if (ftdi_usb_open(&ftdic
, ftdi2232_vid
, ftdi2232_pid
) < 0)
559 ERROR("unable to open ftdi device: %s", ftdic
.error_str
);
560 return ERROR_JTAG_INIT_FAILED
;
563 if (ftdi_usb_reset(&ftdic
) < 0)
565 ERROR("unable to reset ftdi device");
566 return ERROR_JTAG_INIT_FAILED
;
569 if (ftdi_set_latency_timer(&ftdic
, 1) < 0)
571 ERROR("unable to set latency timer");
572 return ERROR_JTAG_INIT_FAILED
;
575 ftdi2232_buffer_size
= 0;
576 ftdi2232_buffer
= malloc(FTDI2232_BUFFER_SIZE
);
578 ftdic
.bitbang_mode
= 0; /* Reset controller */
579 ftdi_enable_bitbang(&ftdic
, 0x0b | FTDI2232_SRST
| FTDI2232_TRST
); /* ctx, i/o mask (out=1, in=0) */
581 ftdic
.bitbang_mode
= 2; /* MPSSE mode */
582 ftdi_enable_bitbang(&ftdic
, 0x0b | FTDI2232_SRST
| FTDI2232_TRST
); /* ctx, i/o mask (out=1, in=0) */
584 if (ftdi_usb_purge_buffers(&ftdic
) < 0)
586 ERROR("ftdi_purge_buffers: %s", ftdic
.error_str
);
587 return ERROR_JTAG_INIT_FAILED
;
590 /* initialize low byte for jtag */
591 BUFFER_ADD
= 0x80; /* command "set data bits low byte" */
592 BUFFER_ADD
= 0x08 | FTDI2232_SRST
| FTDI2232_TRST
; /* value (TMS=1,TCK=0, TDI=0, xRST high) */
593 BUFFER_ADD
= 0x0b | FTDI2232_SRST
| FTDI2232_TRST
; /* dir (output=1), TCK/TDI/TMS=out, TDO=in */
594 BUFFER_ADD
= 0x85; /* command "Disconnect TDI/DO to TDO/DI for Loopback" */
595 ftdi2232_debug_dump_buffer();
596 if (ftdi_write_data(&ftdic
, ftdi2232_buffer
, ftdi2232_buffer_size
) != 4)
597 return ERROR_JTAG_INIT_FAILED
;
599 ftdi2232_speed(jtag_speed
);
604 int ftdi2232_quit(void)
606 ftdi_disable_bitbang(&ftdic
);
608 ftdi_usb_close(&ftdic
);
612 free(ftdi2232_buffer
);
617 int ftdi2232_handle_vid_pid_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
621 ftdi2232_vid
= strtol(args
[0], NULL
, 0);
622 ftdi2232_pid
= strtol(args
[1], NULL
, 0);
626 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)