1 /**************************************************************************
2 * Copyright (C) 2012 by Andreas Fritiofson *
3 * andreas.fritiofson@gmail.com *
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
23 * JTAG adapters based on the FT2232 full and high speed USB parts are
24 * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters
25 * are discrete, but development boards may integrate them as alternatives
26 * to more capable (and expensive) third party JTAG pods.
28 * JTAG uses only one of the two communications channels ("MPSSE engines")
29 * on these devices. Adapters based on FT4232 parts have four ports/channels
30 * (A/B/C/D), instead of just two (A/B).
32 * Especially on development boards integrating one of these chips (as
33 * opposed to discrete pods/dongles), the additional channels can be used
34 * for a variety of purposes, but OpenOCD only uses one channel at a time.
36 * - As a USB-to-serial adapter for the target's console UART ...
37 * which may be able to support ROM boot loaders that load initial
38 * firmware images to flash (or SRAM).
40 * - On systems which support ARM's SWD in addition to JTAG, or instead
41 * of it, that second port can be used for reading SWV/SWO trace data.
43 * - Additional JTAG links, e.g. to a CPLD or * FPGA.
45 * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG
46 * request/response interactions involve round trips over the USB link.
47 * A "smart" JTAG adapter has intelligence close to the scan chain, so it
48 * can for example poll quickly for a status change (usually taking on the
49 * order of microseconds not milliseconds) before beginning a queued
50 * transaction which require the previous one to have completed.
52 * There are dozens of adapters of this type, differing in details which
53 * this driver needs to understand. Those "layout" details are required
54 * as part of FT2232 driver configuration.
56 * This code uses information contained in the MPSSE specification which was
58 * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf
59 * Hereafter this is called the "MPSSE Spec".
61 * The datasheet for the ftdichip.com's FT2232D part is here:
62 * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf
64 * Also note the issue with code 0x4b (clock data to TMS) noted in
65 * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html
66 * which can affect longer JTAG state paths.
73 /* project specific includes */
74 #include <jtag/interface.h>
75 #include <transport/transport.h>
76 #include <helper/time_support.h>
84 /* FTDI access library includes */
87 #define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
89 static char *ftdi_device_desc
;
90 static char *ftdi_serial
;
91 static uint8_t ftdi_channel
;
94 /* vid = pid = 0 marks the end of the list */
95 static uint16_t ftdi_vid
[MAX_USB_IDS
+ 1] = { 0 };
96 static uint16_t ftdi_pid
[MAX_USB_IDS
+ 1] = { 0 };
98 static struct mpsse_ctx
*mpsse_ctx
;
109 static struct signal
*signals
;
111 static uint16_t output
;
112 static uint16_t direction
;
114 static struct signal
*find_signal_by_name(const char *name
)
116 for (struct signal
*sig
= signals
; sig
; sig
= sig
->next
) {
117 if (strcmp(name
, sig
->name
) == 0)
123 static struct signal
*create_signal(const char *name
)
125 struct signal
**psig
= &signals
;
127 psig
= &(*psig
)->next
;
129 *psig
= calloc(1, sizeof(**psig
));
133 (*psig
)->name
= strdup(name
);
134 if ((*psig
)->name
== NULL
) {
141 static int ftdi_set_signal(const struct signal
*s
, char value
)
146 if (s
->data_mask
== 0 && s
->oe_mask
== 0) {
147 LOG_ERROR("interface doesn't provide signal '%s'", s
->name
);
152 data
= s
->invert_data
;
156 if (s
->data_mask
== 0) {
157 LOG_ERROR("interface can't drive '%s' high", s
->name
);
160 data
= !s
->invert_data
;
165 if (s
->oe_mask
== 0) {
166 LOG_ERROR("interface can't tri-state '%s'", s
->name
);
169 data
= s
->invert_data
;
173 assert(0 && "invalid signal level specifier");
177 output
= data
? output
| s
->data_mask
: output
& ~s
->data_mask
;
178 if (s
->oe_mask
== s
->data_mask
)
179 direction
= oe
? direction
| s
->oe_mask
: direction
& ~s
->oe_mask
;
181 output
= oe
? output
| s
->oe_mask
: output
& ~s
->oe_mask
;
183 mpsse_set_data_bits_low_byte(mpsse_ctx
, output
& 0xff, direction
& 0xff);
184 mpsse_set_data_bits_high_byte(mpsse_ctx
, output
>> 8, direction
>> 8);
191 * Function move_to_state
192 * moves the TAP controller from the current state to a
193 * \a goal_state through a path given by tap_get_tms_path(). State transition
194 * logging is performed by delegation to clock_tms().
196 * @param goal_state is the destination state for the move.
198 static void move_to_state(tap_state_t goal_state
)
200 tap_state_t start_state
= tap_get_state();
202 /* goal_state is 1/2 of a tuple/pair of states which allow convenient
203 lookup of the required TMS pattern to move to this state from the
207 /* do the 2 lookups */
208 int tms_bits
= tap_get_tms_path(start_state
, goal_state
);
209 int tms_count
= tap_get_tms_path_len(start_state
, goal_state
);
211 DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state
), tap_state_name(goal_state
));
213 /* Track state transitions step by step */
214 for (int i
= 0; i
< tms_count
; i
++)
215 tap_set_state(tap_state_transition(tap_get_state(), (tms_bits
>> i
) & 1));
217 mpsse_clock_tms_cs_out(mpsse_ctx
,
218 (uint8_t *)&tms_bits
,
225 static int ftdi_speed(int speed
)
228 retval
= mpsse_set_frequency(mpsse_ctx
, speed
);
231 LOG_ERROR("couldn't set FTDI TCK speed");
238 static int ftdi_speed_div(int speed
, int *khz
)
244 static int ftdi_khz(int khz
, int *jtag_speed
)
246 if (khz
== 0 && !mpsse_is_high_speed(mpsse_ctx
)) {
247 LOG_DEBUG("RCLK not supported");
251 *jtag_speed
= khz
* 1000;
255 static void ftdi_end_state(tap_state_t state
)
257 if (tap_is_state_stable(state
))
258 tap_set_end_state(state
);
260 LOG_ERROR("BUG: %s is not a stable end state", tap_state_name(state
));
265 static void ftdi_execute_runtest(struct jtag_command
*cmd
)
270 DEBUG_JTAG_IO("runtest %i cycles, end in %s",
271 cmd
->cmd
.runtest
->num_cycles
,
272 tap_state_name(cmd
->cmd
.runtest
->end_state
));
274 if (tap_get_state() != TAP_IDLE
)
275 move_to_state(TAP_IDLE
);
277 /* TODO: Reuse ftdi_execute_stableclocks */
278 i
= cmd
->cmd
.runtest
->num_cycles
;
280 /* there are no state transitions in this code, so omit state tracking */
281 unsigned this_len
= i
> 7 ? 7 : i
;
282 mpsse_clock_tms_cs_out(mpsse_ctx
, &zero
, 0, this_len
, false, JTAG_MODE
);
286 ftdi_end_state(cmd
->cmd
.runtest
->end_state
);
288 if (tap_get_state() != tap_get_end_state())
289 move_to_state(tap_get_end_state());
291 DEBUG_JTAG_IO("runtest: %i, end in %s",
292 cmd
->cmd
.runtest
->num_cycles
,
293 tap_state_name(tap_get_end_state()));
296 static void ftdi_execute_statemove(struct jtag_command
*cmd
)
298 DEBUG_JTAG_IO("statemove end in %s",
299 tap_state_name(cmd
->cmd
.statemove
->end_state
));
301 ftdi_end_state(cmd
->cmd
.statemove
->end_state
);
303 /* shortest-path move to desired end state */
304 if (tap_get_state() != tap_get_end_state() || tap_get_end_state() == TAP_RESET
)
305 move_to_state(tap_get_end_state());
309 * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG
310 * (or SWD) state machine. REVISIT: Not the best method, perhaps.
312 static void ftdi_execute_tms(struct jtag_command
*cmd
)
314 DEBUG_JTAG_IO("TMS: %d bits", cmd
->cmd
.tms
->num_bits
);
316 /* TODO: Missing tap state tracking, also missing from ft2232.c! */
317 mpsse_clock_tms_cs_out(mpsse_ctx
,
320 cmd
->cmd
.tms
->num_bits
,
325 static void ftdi_execute_pathmove(struct jtag_command
*cmd
)
327 tap_state_t
*path
= cmd
->cmd
.pathmove
->path
;
328 int num_states
= cmd
->cmd
.pathmove
->num_states
;
330 DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states
,
331 tap_state_name(tap_get_state()),
332 tap_state_name(path
[num_states
-1]));
335 unsigned bit_count
= 0;
336 uint8_t tms_byte
= 0;
340 /* this loop verifies that the path is legal and logs each state in the path */
341 while (num_states
--) {
343 /* either TMS=0 or TMS=1 must work ... */
344 if (tap_state_transition(tap_get_state(), false)
345 == path
[state_count
])
346 buf_set_u32(&tms_byte
, bit_count
++, 1, 0x0);
347 else if (tap_state_transition(tap_get_state(), true)
348 == path
[state_count
]) {
349 buf_set_u32(&tms_byte
, bit_count
++, 1, 0x1);
351 /* ... or else the caller goofed BADLY */
353 LOG_ERROR("BUG: %s -> %s isn't a valid "
354 "TAP state transition",
355 tap_state_name(tap_get_state()),
356 tap_state_name(path
[state_count
]));
360 tap_set_state(path
[state_count
]);
363 if (bit_count
== 7 || num_states
== 0) {
364 mpsse_clock_tms_cs_out(mpsse_ctx
,
373 tap_set_end_state(tap_get_state());
376 static void ftdi_execute_scan(struct jtag_command
*cmd
)
378 DEBUG_JTAG_IO("%s type:%d", cmd
->cmd
.scan
->ir_scan
? "IRSCAN" : "DRSCAN",
379 jtag_scan_type(cmd
->cmd
.scan
));
381 /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */
382 while (cmd
->cmd
.scan
->num_fields
> 0
383 && cmd
->cmd
.scan
->fields
[cmd
->cmd
.scan
->num_fields
- 1].num_bits
== 0) {
384 cmd
->cmd
.scan
->num_fields
--;
385 LOG_DEBUG("discarding trailing empty field");
388 if (cmd
->cmd
.scan
->num_fields
== 0) {
389 LOG_DEBUG("empty scan, doing nothing");
393 if (cmd
->cmd
.scan
->ir_scan
) {
394 if (tap_get_state() != TAP_IRSHIFT
)
395 move_to_state(TAP_IRSHIFT
);
397 if (tap_get_state() != TAP_DRSHIFT
)
398 move_to_state(TAP_DRSHIFT
);
401 ftdi_end_state(cmd
->cmd
.scan
->end_state
);
403 struct scan_field
*field
= cmd
->cmd
.scan
->fields
;
404 unsigned scan_size
= 0;
406 for (int i
= 0; i
< cmd
->cmd
.scan
->num_fields
; i
++, field
++) {
407 scan_size
+= field
->num_bits
;
408 DEBUG_JTAG_IO("%s%s field %d/%d %d bits",
409 field
->in_value
? "in" : "",
410 field
->out_value
? "out" : "",
412 cmd
->cmd
.scan
->num_fields
,
415 if (i
== cmd
->cmd
.scan
->num_fields
- 1 && tap_get_state() != tap_get_end_state()) {
416 /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap
417 * movement. This last field can't have length zero, it was checked above. */
418 mpsse_clock_data(mpsse_ctx
,
425 uint8_t last_bit
= 0;
426 if (field
->out_value
)
427 bit_copy(&last_bit
, 0, field
->out_value
, field
->num_bits
- 1, 1);
428 uint8_t tms_bits
= 0x01;
429 mpsse_clock_tms_cs(mpsse_ctx
,
437 tap_set_state(tap_state_transition(tap_get_state(), 1));
438 mpsse_clock_tms_cs_out(mpsse_ctx
,
444 tap_set_state(tap_state_transition(tap_get_state(), 0));
446 mpsse_clock_data(mpsse_ctx
,
455 if (tap_get_state() != tap_get_end_state())
456 move_to_state(tap_get_end_state());
458 DEBUG_JTAG_IO("%s scan, %i bits, end in %s",
459 (cmd
->cmd
.scan
->ir_scan
) ? "IR" : "DR", scan_size
,
460 tap_state_name(tap_get_end_state()));
463 static void ftdi_execute_reset(struct jtag_command
*cmd
)
465 DEBUG_JTAG_IO("reset trst: %i srst %i",
466 cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
468 if (cmd
->cmd
.reset
->trst
== 1
469 || (cmd
->cmd
.reset
->srst
470 && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST
)))
471 tap_set_state(TAP_RESET
);
473 struct signal
*trst
= find_signal_by_name("nTRST");
474 if (trst
&& cmd
->cmd
.reset
->trst
== 1) {
475 ftdi_set_signal(trst
, '0');
476 } else if (trst
&& cmd
->cmd
.reset
->trst
== 0) {
477 if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN
)
478 ftdi_set_signal(trst
, 'z');
480 ftdi_set_signal(trst
, '1');
483 struct signal
*srst
= find_signal_by_name("nSRST");
484 if (srst
&& cmd
->cmd
.reset
->srst
== 1) {
485 ftdi_set_signal(srst
, '0');
486 } else if (srst
&& cmd
->cmd
.reset
->srst
== 0) {
487 if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL
)
488 ftdi_set_signal(srst
, '1');
490 ftdi_set_signal(srst
, 'z');
493 DEBUG_JTAG_IO("trst: %i, srst: %i",
494 cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
497 static void ftdi_execute_sleep(struct jtag_command
*cmd
)
499 DEBUG_JTAG_IO("sleep %" PRIi32
, cmd
->cmd
.sleep
->us
);
501 mpsse_flush(mpsse_ctx
);
502 jtag_sleep(cmd
->cmd
.sleep
->us
);
503 DEBUG_JTAG_IO("sleep %" PRIi32
" usec while in %s",
505 tap_state_name(tap_get_state()));
508 static void ftdi_execute_stableclocks(struct jtag_command
*cmd
)
510 /* this is only allowed while in a stable state. A check for a stable
511 * state was done in jtag_add_clocks()
513 int num_cycles
= cmd
->cmd
.stableclocks
->num_cycles
;
515 /* 7 bits of either ones or zeros. */
516 uint8_t tms
= tap_get_state() == TAP_RESET
? 0x7f : 0x00;
518 /* TODO: Use mpsse_clock_data with in=out=0 for this, if TMS can be set to
519 * the correct level and remain there during the scan */
520 while (num_cycles
> 0) {
521 /* there are no state transitions in this code, so omit state tracking */
522 unsigned this_len
= num_cycles
> 7 ? 7 : num_cycles
;
523 mpsse_clock_tms_cs_out(mpsse_ctx
, &tms
, 0, this_len
, false, JTAG_MODE
);
524 num_cycles
-= this_len
;
527 DEBUG_JTAG_IO("clocks %i while in %s",
528 cmd
->cmd
.stableclocks
->num_cycles
,
529 tap_state_name(tap_get_state()));
532 static void ftdi_execute_command(struct jtag_command
*cmd
)
536 ftdi_execute_reset(cmd
);
539 ftdi_execute_runtest(cmd
);
542 ftdi_execute_statemove(cmd
);
545 ftdi_execute_pathmove(cmd
);
548 ftdi_execute_scan(cmd
);
551 ftdi_execute_sleep(cmd
);
553 case JTAG_STABLECLOCKS
:
554 ftdi_execute_stableclocks(cmd
);
557 ftdi_execute_tms(cmd
);
560 LOG_ERROR("BUG: unknown JTAG command type encountered: %d", cmd
->type
);
565 static int ftdi_execute_queue(void)
567 /* blink, if the current layout has that feature */
568 struct signal
*led
= find_signal_by_name("LED");
570 ftdi_set_signal(led
, '1');
572 for (struct jtag_command
*cmd
= jtag_command_queue
; cmd
; cmd
= cmd
->next
) {
573 /* fill the write buffer with the desired command */
574 ftdi_execute_command(cmd
);
578 ftdi_set_signal(led
, '0');
580 int retval
= mpsse_flush(mpsse_ctx
);
581 if (retval
!= ERROR_OK
)
582 LOG_ERROR("error while flushing MPSSE queue: %d", retval
);
587 static int ftdi_initialize(void)
589 if (tap_get_tms_path_len(TAP_IRPAUSE
, TAP_IRPAUSE
) == 7)
590 LOG_DEBUG("ftdi interface using 7 step jtag state transitions");
592 LOG_DEBUG("ftdi interface using shortest path jtag state transitions");
594 for (int i
= 0; ftdi_vid
[i
] || ftdi_pid
[i
]; i
++) {
595 mpsse_ctx
= mpsse_open(&ftdi_vid
[i
], &ftdi_pid
[i
], ftdi_device_desc
,
596 ftdi_serial
, ftdi_channel
);
602 return ERROR_JTAG_INIT_FAILED
;
604 mpsse_set_data_bits_low_byte(mpsse_ctx
, output
& 0xff, direction
& 0xff);
605 mpsse_set_data_bits_high_byte(mpsse_ctx
, output
>> 8, direction
>> 8);
607 mpsse_loopback_config(mpsse_ctx
, false);
609 return mpsse_flush(mpsse_ctx
);
612 static int ftdi_quit(void)
614 mpsse_close(mpsse_ctx
);
619 COMMAND_HANDLER(ftdi_handle_device_desc_command
)
622 if (ftdi_device_desc
)
623 free(ftdi_device_desc
);
624 ftdi_device_desc
= strdup(CMD_ARGV
[0]);
626 LOG_ERROR("expected exactly one argument to ftdi_device_desc <description>");
632 COMMAND_HANDLER(ftdi_handle_serial_command
)
637 ftdi_serial
= strdup(CMD_ARGV
[0]);
639 return ERROR_COMMAND_SYNTAX_ERROR
;
645 COMMAND_HANDLER(ftdi_handle_channel_command
)
648 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0], ftdi_channel
);
650 return ERROR_COMMAND_SYNTAX_ERROR
;
655 COMMAND_HANDLER(ftdi_handle_layout_init_command
)
658 return ERROR_COMMAND_SYNTAX_ERROR
;
660 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], output
);
661 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[1], direction
);
666 COMMAND_HANDLER(ftdi_handle_layout_signal_command
)
669 return ERROR_COMMAND_SYNTAX_ERROR
;
671 bool invert_data
= false;
672 uint16_t data_mask
= 0;
673 bool invert_oe
= false;
674 uint16_t oe_mask
= 0;
675 for (unsigned i
= 1; i
< CMD_ARGC
; i
+= 2) {
676 if (strcmp("-data", CMD_ARGV
[i
]) == 0) {
678 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[i
+ 1], data_mask
);
679 } else if (strcmp("-ndata", CMD_ARGV
[i
]) == 0) {
681 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[i
+ 1], data_mask
);
682 } else if (strcmp("-oe", CMD_ARGV
[i
]) == 0) {
684 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[i
+ 1], oe_mask
);
685 } else if (strcmp("-noe", CMD_ARGV
[i
]) == 0) {
687 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[i
+ 1], oe_mask
);
689 LOG_ERROR("unknown option '%s'", CMD_ARGV
[i
]);
690 return ERROR_COMMAND_SYNTAX_ERROR
;
695 sig
= find_signal_by_name(CMD_ARGV
[0]);
697 sig
= create_signal(CMD_ARGV
[0]);
699 LOG_ERROR("failed to create signal %s", CMD_ARGV
[0]);
703 sig
->invert_data
= invert_data
;
704 sig
->data_mask
= data_mask
;
705 sig
->invert_oe
= invert_oe
;
706 sig
->oe_mask
= oe_mask
;
711 COMMAND_HANDLER(ftdi_handle_set_signal_command
)
714 return ERROR_COMMAND_SYNTAX_ERROR
;
717 sig
= find_signal_by_name(CMD_ARGV
[0]);
719 LOG_ERROR("interface configuration doesn't define signal '%s'", CMD_ARGV
[0]);
723 switch (*CMD_ARGV
[1]) {
728 /* single character level specifier only */
729 if (CMD_ARGV
[1][1] == '\0') {
730 ftdi_set_signal(sig
, *CMD_ARGV
[1]);
734 LOG_ERROR("unknown signal level '%s', use 0, 1 or z", CMD_ARGV
[1]);
735 return ERROR_COMMAND_SYNTAX_ERROR
;
738 return mpsse_flush(mpsse_ctx
);
741 COMMAND_HANDLER(ftdi_handle_vid_pid_command
)
743 if (CMD_ARGC
> MAX_USB_IDS
* 2) {
744 LOG_WARNING("ignoring extra IDs in ftdi_vid_pid "
745 "(maximum is %d pairs)", MAX_USB_IDS
);
746 CMD_ARGC
= MAX_USB_IDS
* 2;
748 if (CMD_ARGC
< 2 || (CMD_ARGC
& 1)) {
749 LOG_WARNING("incomplete ftdi_vid_pid configuration directive");
751 return ERROR_COMMAND_SYNTAX_ERROR
;
752 /* remove the incomplete trailing id */
757 for (i
= 0; i
< CMD_ARGC
; i
+= 2) {
758 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[i
], ftdi_vid
[i
>> 1]);
759 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[i
+ 1], ftdi_pid
[i
>> 1]);
763 * Explicitly terminate, in case there are multiples instances of
766 ftdi_vid
[i
>> 1] = ftdi_pid
[i
>> 1] = 0;
771 static const struct command_registration ftdi_command_handlers
[] = {
773 .name
= "ftdi_device_desc",
774 .handler
= &ftdi_handle_device_desc_command
,
775 .mode
= COMMAND_CONFIG
,
776 .help
= "set the USB device description of the FTDI device",
777 .usage
= "description_string",
780 .name
= "ftdi_serial",
781 .handler
= &ftdi_handle_serial_command
,
782 .mode
= COMMAND_CONFIG
,
783 .help
= "set the serial number of the FTDI device",
784 .usage
= "serial_string",
787 .name
= "ftdi_channel",
788 .handler
= &ftdi_handle_channel_command
,
789 .mode
= COMMAND_CONFIG
,
790 .help
= "set the channel of the FTDI device that is used as JTAG",
794 .name
= "ftdi_layout_init",
795 .handler
= &ftdi_handle_layout_init_command
,
796 .mode
= COMMAND_CONFIG
,
797 .help
= "initialize the FTDI GPIO signals used "
798 "to control output-enables and reset signals",
799 .usage
= "data direction",
802 .name
= "ftdi_layout_signal",
803 .handler
= &ftdi_handle_layout_signal_command
,
805 .help
= "define a signal controlled by one or more FTDI GPIO as data "
806 "and/or output enable",
807 .usage
= "name [-data mask|-ndata mask] [-oe mask|-noe mask]",
810 .name
= "ftdi_set_signal",
811 .handler
= &ftdi_handle_set_signal_command
,
812 .mode
= COMMAND_EXEC
,
813 .help
= "control a layout-specific signal",
814 .usage
= "name (1|0|z)",
817 .name
= "ftdi_vid_pid",
818 .handler
= &ftdi_handle_vid_pid_command
,
819 .mode
= COMMAND_CONFIG
,
820 .help
= "the vendor ID and product ID of the FTDI device",
821 .usage
= "(vid pid)* ",
823 COMMAND_REGISTRATION_DONE
826 struct jtag_interface ftdi_interface
= {
828 .supported
= DEBUG_CAP_TMS_SEQ
,
829 .commands
= ftdi_command_handlers
,
830 .transports
= jtag_only
,
832 .init
= ftdi_initialize
,
835 .speed_div
= ftdi_speed_div
,
837 .execute_queue
= ftdi_execute_queue
,
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)