1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
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 ***************************************************************************/
28 #include "replacements.h"
30 /* project specific includes */
34 #include "configuration.h"
35 #include "time_support.h"
43 /* PRESTO access library includes */
44 #if BUILD_PRESTO_FTD2XX == 1
46 #elif BUILD_PRESTO_LIBFTDI == 1
49 #error "BUG: either FTD2XX and LIBFTDI has to be used"
52 static int presto_jtag_speed(int speed
);
53 static int presto_jtag_khz(int khz
, int *jtag_speed
);
54 static int presto_jtag_speed_div(int speed
, int *khz
);
55 static int presto_jtag_register_commands(struct command_context_s
*cmd_ctx
);
56 static int presto_jtag_init(void);
57 static int presto_jtag_quit(void);
59 jtag_interface_t presto_interface
=
62 .execute_queue
= bitq_execute_queue
,
63 .speed
= presto_jtag_speed
,
64 .khz
= presto_jtag_khz
,
65 .speed_div
= presto_jtag_speed_div
,
66 .register_commands
= presto_jtag_register_commands
,
67 .init
= presto_jtag_init
,
68 .quit
= presto_jtag_quit
,
71 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
);
72 static int presto_bitq_flush(void);
73 static int presto_bitq_sleep(unsigned long us
);
74 static int presto_bitq_reset(int trst
, int srst
);
75 static int presto_bitq_in_rdy(void);
76 static int presto_bitq_in(void);
78 static bitq_interface_t presto_bitq
=
80 .out
= presto_bitq_out
,
81 .flush
= presto_bitq_flush
,
82 .sleep
= presto_bitq_sleep
,
83 .reset
= presto_bitq_reset
,
84 .in_rdy
= presto_bitq_in_rdy
,
88 /* -------------------------------------------------------------------------- */
90 #define FT_DEVICE_NAME_LEN 64
91 #define FT_DEVICE_SERNUM_LEN 64
93 #define PRESTO_VID_PID 0x0403f1a0
94 #define PRESTO_VID (0x0403)
95 #define PRESTO_PID (0xf1a0)
97 #define BUFFER_SIZE (64*62)
99 typedef struct presto_s
101 #if BUILD_PRESTO_FTD2XX == 1
104 #elif BUILD_PRESTO_LIBFTDI == 1
105 struct ftdi_context ftdic
;
109 char serial
[FT_DEVICE_SERNUM_LEN
];
111 u8 buff_out
[BUFFER_SIZE
];
114 u8 buff_in
[BUFFER_SIZE
];
115 int buff_in_exp
; /* expected in buffer length */
116 int buff_in_len
; /* length of data received */
119 unsigned long total_out
;
120 unsigned long total_in
;
122 int jtag_tms
; /* last tms state */
123 int jtag_tck
; /* last tck state */
124 int jtag_rst
; /* last trst state */
133 static presto_t presto_state
;
134 static presto_t
*presto
= &presto_state
;
136 static u8 presto_init_seq
[] =
138 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
141 static int presto_write(u8
*buf
, u32 size
)
143 #if BUILD_PRESTO_FTD2XX == 1
145 if ((presto
->status
= FT_Write(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
147 LOG_ERROR("FT_Write returned: %lu", presto
->status
);
148 return ERROR_JTAG_DEVICE_ERROR
;
151 #elif BUILD_PRESTO_LIBFTDI == 1
153 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, buf
, size
)) < 0)
155 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto
->ftdic
));
156 return ERROR_JTAG_DEVICE_ERROR
;
158 ftbytes
= presto
->retval
;
163 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", (u32
)ftbytes
, size
);
164 return ERROR_JTAG_DEVICE_ERROR
;
170 static int presto_read(u8
* buf
, u32 size
)
172 #if BUILD_PRESTO_FTD2XX == 1
174 if ((presto
->status
= FT_Read(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
176 LOG_ERROR("FT_Read returned: %lu", presto
->status
);
177 return ERROR_JTAG_DEVICE_ERROR
;
180 #elif BUILD_PRESTO_LIBFTDI == 1
183 struct timeval timeout
, now
;
184 gettimeofday(&timeout
, NULL
);
185 timeval_add_time(&timeout
, 1, 0); /* one second timeout */
187 while (ftbytes
< size
)
189 if ((presto
->retval
= ftdi_read_data(&presto
->ftdic
, buf
+ ftbytes
, size
- ftbytes
)) < 0)
191 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto
->ftdic
));
192 return ERROR_JTAG_DEVICE_ERROR
;
194 ftbytes
+= presto
->retval
;
196 gettimeofday(&now
, NULL
);
197 if ((now
.tv_sec
> timeout
.tv_sec
) || ((now
.tv_sec
== timeout
.tv_sec
) && (now
.tv_usec
> timeout
.tv_usec
)))
204 /* this is just a warning, there might have been timeout when detecting PRESTO, which is not fatal */
205 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)", (u32
)ftbytes
, size
);
206 return ERROR_JTAG_DEVICE_ERROR
;
212 #if BUILD_PRESTO_FTD2XX == 1
213 static int presto_open_ftd2xx(char *req_serial
)
218 char devname
[FT_DEVICE_NAME_LEN
];
224 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
227 /* Add non-standard Vid/Pid to the linux driver */
228 if ((presto
->status
= FT_SetVIDPID(PRESTO_VID
, PRESTO_PID
)) != FT_OK
)
230 LOG_ERROR("couldn't add PRESTO VID/PID");
235 if ((presto
->status
= FT_ListDevices(&numdevs
, NULL
, FT_LIST_NUMBER_ONLY
)) != FT_OK
)
237 LOG_ERROR("FT_ListDevices failed: %i", (int)presto
->status
);
238 return ERROR_JTAG_DEVICE_ERROR
;
241 LOG_DEBUG("FTDI devices available: %lu", numdevs
);
242 for (i
= 0; i
< numdevs
; i
++)
244 if ((presto
->status
= FT_Open(i
, &(presto
->handle
))) != FT_OK
)
246 /* this is not fatal, the device may be legitimately open by other process, hence debug message only */
247 LOG_DEBUG("FT_Open failed: %i", (int)presto
->status
);
250 LOG_DEBUG("FTDI device %i open", i
);
252 if ((presto
->status
= FT_GetDeviceInfo(presto
->handle
, &device
, &vidpid
,
253 presto
->serial
, devname
, NULL
)) == FT_OK
)
255 if (vidpid
== PRESTO_VID_PID
256 && (req_serial
== NULL
|| !strcmp(presto
->serial
, req_serial
)))
260 LOG_DEBUG("FT_GetDeviceInfo failed: %lu", presto
->status
);
262 LOG_DEBUG("FTDI device %i does not match, closing", i
);
263 FT_Close(presto
->handle
);
264 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
267 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
268 return ERROR_JTAG_DEVICE_ERROR
; /* presto not open, return */
270 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 1)) != FT_OK
)
271 return ERROR_JTAG_DEVICE_ERROR
;
274 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 100, 0)) != FT_OK
)
275 return ERROR_JTAG_DEVICE_ERROR
;
277 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
278 return ERROR_JTAG_DEVICE_ERROR
;
281 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
282 return ERROR_JTAG_DEVICE_ERROR
;
284 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
285 probably a bug in library threading */
287 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
288 return ERROR_JTAG_DEVICE_ERROR
;
292 LOG_DEBUG("PRESTO reset");
294 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
295 return ERROR_JTAG_DEVICE_ERROR
;
296 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x80, 1)) != FT_OK
)
297 return ERROR_JTAG_DEVICE_ERROR
;
298 if ((presto
->status
= FT_SetBaudRate(presto
->handle
, 9600)) != FT_OK
)
299 return ERROR_JTAG_DEVICE_ERROR
;
302 for (i
= 0; i
< 4 * 62; i
++)
303 if ((presto
->status
=FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
304 return ERROR_JTAG_DEVICE_ERROR
;
308 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x00, 0)) != FT_OK
)
309 return ERROR_JTAG_DEVICE_ERROR
;
311 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
312 return ERROR_JTAG_DEVICE_ERROR
;
315 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
316 return ERROR_JTAG_DEVICE_ERROR
;
318 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
319 probably a bug in library threading */
321 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
322 return ERROR_JTAG_DEVICE_ERROR
;
326 LOG_DEBUG("PRESTO not responding");
327 return ERROR_JTAG_DEVICE_ERROR
;
331 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 0, 0)) != FT_OK
)
332 return ERROR_JTAG_DEVICE_ERROR
;
335 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
336 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
337 return ERROR_JTAG_DEVICE_ERROR
;
342 #elif BUILD_PRESTO_LIBFTDI == 1
343 static int presto_open_libftdi(char *req_serial
)
347 LOG_DEBUG("searching for PRESTO using libftdi");
349 /* initialize FTDI context structure */
350 if (ftdi_init(&presto
->ftdic
) < 0)
352 LOG_ERROR("unable to init libftdi: %s", presto
->ftdic
.error_str
);
353 return ERROR_JTAG_DEVICE_ERROR
;
356 /* context, vendor id, product id */
357 if (ftdi_usb_open_desc(&presto
->ftdic
, PRESTO_VID
, PRESTO_PID
, NULL
, req_serial
) < 0)
359 LOG_ERROR("unable to open PRESTO: %s", presto
->ftdic
.error_str
);
360 return ERROR_JTAG_DEVICE_ERROR
;
363 if (ftdi_usb_reset(&presto
->ftdic
) < 0)
365 LOG_ERROR("unable to reset PRESTO device");
366 return ERROR_JTAG_DEVICE_ERROR
;
369 if (ftdi_set_latency_timer(&presto
->ftdic
, 1) < 0)
371 LOG_ERROR("unable to set latency timer");
372 return ERROR_JTAG_DEVICE_ERROR
;
375 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
377 LOG_ERROR("unable to purge PRESTO buffers");
378 return ERROR_JTAG_DEVICE_ERROR
;
382 if (presto_write(&presto_data
, 1) != ERROR_OK
)
384 LOG_ERROR("error writing to PRESTO");
385 return ERROR_JTAG_DEVICE_ERROR
;
388 if (presto_read(&presto_data
, 1) != ERROR_OK
)
390 LOG_DEBUG("no response from PRESTO, retrying");
392 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
393 return ERROR_JTAG_DEVICE_ERROR
;
396 if (presto_write(&presto_data
, 1) != ERROR_OK
)
397 return ERROR_JTAG_DEVICE_ERROR
;
399 if (presto_read(&presto_data
, 1) != ERROR_OK
)
401 LOG_ERROR("no response from PRESTO, giving up");
402 return ERROR_JTAG_DEVICE_ERROR
;
406 if (presto_write(presto_init_seq
, sizeof(presto_init_seq
)) != ERROR_OK
)
408 LOG_ERROR("error writing PRESTO init sequence");
409 return ERROR_JTAG_DEVICE_ERROR
;
414 #endif /* BUILD_PRESTO_LIBFTDI == 1 */
416 static int presto_open(char *req_serial
)
418 presto
->buff_out_pos
=0;
419 presto
->buff_in_pos
=0;
420 presto
->buff_in_len
=0;
421 presto
->buff_in_exp
=0;
429 presto
->jtag_tdi_data
=0;
430 presto
->jtag_tdi_count
=0;
432 presto
->jtag_speed
=0;
434 #if BUILD_PRESTO_FTD2XX == 1
435 return presto_open_ftd2xx(req_serial
);
436 #elif BUILD_PRESTO_LIBFTDI == 1
437 return presto_open_libftdi(req_serial
);
441 static int presto_close(void)
444 int result
= ERROR_OK
;
446 #if BUILD_PRESTO_FTD2XX == 1
447 unsigned long ftbytes
;
449 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
452 presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
);
453 if (presto
->status
!= FT_OK
)
454 result
= ERROR_JTAG_DEVICE_ERROR
;
456 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
457 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
458 result
= ERROR_JTAG_DEVICE_ERROR
;
460 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 16)) != FT_OK
)
461 result
= ERROR_JTAG_DEVICE_ERROR
;
463 if ((presto
->status
= FT_Close(presto
->handle
)) != FT_OK
)
464 result
= ERROR_JTAG_DEVICE_ERROR
;
466 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
468 #elif BUILD_PRESTO_LIBFTDI == 1
470 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, presto_init_seq
, sizeof(presto_init_seq
))) != sizeof(presto_init_seq
))
471 result
= ERROR_JTAG_DEVICE_ERROR
;
473 if ((presto
->retval
= ftdi_set_latency_timer(&presto
->ftdic
, 16)) < 0)
474 result
= ERROR_JTAG_DEVICE_ERROR
;
476 if ((presto
->retval
= ftdi_usb_close(&presto
->ftdic
)) < 0)
477 result
= ERROR_JTAG_DEVICE_ERROR
;
479 ftdi_deinit(&presto
->ftdic
);
485 static int presto_flush(void)
487 if (presto
->buff_out_pos
== 0)
490 #if BUILD_PRESTO_FTD2XX == 1
491 if (presto
->status
!= FT_OK
)
492 #elif BUILD_PRESTO_LIBFTDI == 1
493 if (presto
->retval
< 0)
496 LOG_DEBUG("error in previous communication, canceling I/O operation");
497 return ERROR_JTAG_DEVICE_ERROR
;
500 if (presto_write(presto
->buff_out
, presto
->buff_out_pos
) != ERROR_OK
)
502 presto
->buff_out_pos
= 0;
503 return ERROR_JTAG_DEVICE_ERROR
;
506 presto
->total_out
+= presto
->buff_out_pos
;
507 presto
->buff_out_pos
= 0;
509 if (presto
->buff_in_exp
== 0)
512 presto
->buff_in_pos
= 0;
513 presto
->buff_in_len
= 0;
515 if (presto_read(presto
->buff_in
, presto
->buff_in_exp
) != ERROR_OK
)
517 presto
->buff_in_exp
= 0;
518 return ERROR_JTAG_DEVICE_ERROR
;
521 presto
->total_in
+= presto
->buff_in_exp
;
522 presto
->buff_in_len
= presto
->buff_in_exp
;
523 presto
->buff_in_exp
= 0;
528 static int presto_sendbyte(int data
)
530 if (data
== EOF
) return presto_flush();
532 if (presto
->buff_out_pos
< BUFFER_SIZE
)
534 presto
->buff_out
[presto
->buff_out_pos
++] = (u8
)data
;
535 if (((data
& 0xC0) == 0x40) || ((data
& 0xD0)== 0xD0))
536 presto
->buff_in_exp
++;
539 return ERROR_JTAG_DEVICE_ERROR
;
541 #if BUILD_PRESTO_FTD2XX == 1
542 if (presto
->buff_out_pos
>= BUFFER_SIZE
)
543 #elif BUILD_PRESTO_LIBFTDI == 1
544 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 bytes only!) */
545 if (presto
->buff_out_pos
>= BUFFER_SIZE
|| presto
->buff_in_exp
==128)
547 return presto_flush();
553 static int presto_getbyte(void)
555 if (presto
->buff_in_pos
< presto
->buff_in_len
)
556 return presto
->buff_in
[presto
->buff_in_pos
++];
558 if (presto
->buff_in_exp
== 0)
561 if (presto_flush() != ERROR_OK
)
564 if (presto
->buff_in_pos
<presto
->buff_in_len
)
565 return presto
->buff_in
[presto
->buff_in_pos
++];
571 /* -------------------------------------------------------------------------- */
573 static int presto_tdi_flush(void)
575 if (presto
->jtag_tdi_count
== 0)
578 if (presto
->jtag_tck
== 0)
580 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
584 presto
->jtag_tdi_data
|= (presto
->jtag_tdi_count
- 1) << 4;
585 presto_sendbyte(presto
->jtag_tdi_data
);
586 presto
->jtag_tdi_count
= 0;
587 presto
->jtag_tdi_data
= 0;
592 static int presto_tck_idle(void)
594 if (presto
->jtag_tck
== 1)
596 presto_sendbyte(0xCA);
597 presto
->jtag_tck
= 0;
603 /* -------------------------------------------------------------------------- */
605 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
)
610 if (presto
->jtag_tck
== 0)
612 presto_sendbyte(0xA4); /* LED idicator - JTAG active */
614 else if (presto
->jtag_speed
== 0 && !tdo_req
&& tms
== presto
->jtag_tms
)
616 presto
->jtag_tdi_data
|= (tdi
!= 0) << presto
->jtag_tdi_count
;
618 if (++presto
->jtag_tdi_count
== 4)
626 cmd
= tdi
? 0xCB : 0xCA;
627 presto_sendbyte(cmd
);
629 if (tms
!= presto
->jtag_tms
)
631 presto_sendbyte((tms
? 0xEC : 0xE8) | (presto
->jtag_rst
? 0x02 : 0));
632 presto
->jtag_tms
= tms
;
635 /* delay with TCK low */
636 for (i
=presto
->jtag_speed
; i
>1; i
--)
637 presto_sendbyte(cmd
);
640 presto_sendbyte(cmd
| (tdo_req
? 0x10 : 0));
642 /* delay with TCK high */
643 for (i
=presto
->jtag_speed
; i
>1; i
--)
644 presto_sendbyte(cmd
);
646 presto
->jtag_tck
= 1;
651 static int presto_bitq_flush(void)
656 presto_sendbyte(0xA0); /* LED idicator - JTAG idle */
658 return presto_flush();
661 static int presto_bitq_in_rdy(void)
663 if (presto
->buff_in_pos
>=presto
->buff_in_len
)
665 return presto
->buff_in_len
-presto
->buff_in_pos
;
668 static int presto_bitq_in(void)
670 if (presto
->buff_in_pos
>=presto
->buff_in_len
)
672 if (presto
->buff_in
[presto
->buff_in_pos
++]&0x08) return 1;
676 static int presto_bitq_sleep(unsigned long us
)
690 waits
= us
/ 170 + 2;
692 presto_sendbyte(0x80);
697 static int presto_bitq_reset(int trst
, int srst
)
702 /* add a delay after possible TCK transition */
703 presto_sendbyte(0x80);
704 presto_sendbyte(0x80);
706 presto
->jtag_rst
= trst
|| srst
;
707 presto_sendbyte((presto
->jtag_rst
? 0xEA : 0xE8) | (presto
->jtag_tms
? 0x04 : 0));
712 /* -------------------------------------------------------------------------- */
714 static int presto_jtag_khz(int khz
, int *jtag_speed
)
719 return ERROR_INVALID_ARGUMENTS
;
722 if (khz
>= 3000) *jtag_speed
= 0;
723 else *jtag_speed
= (1000+khz
-1)/khz
;
728 static int presto_jtag_speed_div(int speed
, int *khz
)
730 if ((speed
< 0) || (speed
> 1000))
733 return ERROR_INVALID_ARGUMENTS
;
736 if (speed
== 0) *khz
= 3000;
737 else *khz
= 1000/speed
;
742 static int presto_jtag_speed(int speed
)
746 if (presto_jtag_speed_div(speed
, &khz
))
748 return ERROR_INVALID_ARGUMENTS
;
751 presto
->jtag_speed
= speed
;
754 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed
, khz
/1000);
756 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed
, khz
);
761 static char *presto_serial
;
763 static int presto_handle_serial_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
769 presto_serial
= strdup(args
[0]);
773 LOG_ERROR("expected exactly one argument to presto_serial <serial-number>");
779 static int presto_jtag_register_commands(struct command_context_s
*cmd_ctx
)
781 register_command(cmd_ctx
, NULL
, "presto_serial", presto_handle_serial_command
,
782 COMMAND_CONFIG
, NULL
);
786 static int presto_jtag_init(void)
788 if (presto_open(presto_serial
) != ERROR_OK
)
791 if (presto_serial
!= NULL
)
792 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
794 LOG_ERROR("Cannot open PRESTO");
795 return ERROR_JTAG_INIT_FAILED
;
797 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
799 /* use JTAG speed setting from configuration file */
800 presto_jtag_speed(jtag_speed
);
802 bitq_interface
= &presto_bitq
;
806 static int presto_jtag_quit(void)
810 LOG_INFO("PRESTO closed");
815 presto_serial
= NULL
;
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)