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 "interface.h"
29 #include <helper/time_support.h>
33 /* PRESTO access library includes */
34 #if BUILD_PRESTO_FTD2XX == 1
36 #elif BUILD_PRESTO_LIBFTDI == 1
39 #error "BUG: either FTD2XX and LIBFTDI has to be used"
42 /* -------------------------------------------------------------------------- */
44 #define FT_DEVICE_NAME_LEN 64
45 #define FT_DEVICE_SERNUM_LEN 64
47 #define PRESTO_VID_PID 0x0403f1a0
48 #define PRESTO_VID (0x0403)
49 #define PRESTO_PID (0xf1a0)
51 #define BUFFER_SIZE (64*62)
54 #if BUILD_PRESTO_FTD2XX == 1
57 #elif BUILD_PRESTO_LIBFTDI == 1
58 struct ftdi_context ftdic
;
62 char serial
[FT_DEVICE_SERNUM_LEN
];
64 uint8_t buff_out
[BUFFER_SIZE
];
67 uint8_t buff_in
[BUFFER_SIZE
];
68 int buff_in_exp
; /* expected in buffer length */
69 int buff_in_len
; /* length of data received */
72 unsigned long total_out
;
73 unsigned long total_in
;
75 int jtag_tms
; /* last tms state */
76 int jtag_tck
; /* last tck state */
77 int jtag_rst
; /* last trst state */
85 static struct presto presto_state
;
86 static struct presto
*presto
= &presto_state
;
88 static uint8_t presto_init_seq
[] =
90 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
93 static int presto_write(uint8_t *buf
, uint32_t size
)
95 #if BUILD_PRESTO_FTD2XX == 1
97 if ((presto
->status
= FT_Write(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
99 LOG_ERROR("FT_Write returned: %lu", presto
->status
);
100 return ERROR_JTAG_DEVICE_ERROR
;
103 #elif BUILD_PRESTO_LIBFTDI == 1
105 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, buf
, size
)) < 0)
107 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto
->ftdic
));
108 return ERROR_JTAG_DEVICE_ERROR
;
110 ftbytes
= presto
->retval
;
115 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
116 (unsigned)ftbytes
, (unsigned)size
);
117 return ERROR_JTAG_DEVICE_ERROR
;
123 static int presto_read(uint8_t* buf
, uint32_t size
)
125 #if BUILD_PRESTO_FTD2XX == 1
127 if ((presto
->status
= FT_Read(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
129 LOG_ERROR("FT_Read returned: %lu", presto
->status
);
130 return ERROR_JTAG_DEVICE_ERROR
;
133 #elif BUILD_PRESTO_LIBFTDI == 1
134 uint32_t ftbytes
= 0;
136 struct timeval timeout
, now
;
137 gettimeofday(&timeout
, NULL
);
138 timeval_add_time(&timeout
, 1, 0); /* one second timeout */
140 while (ftbytes
< size
)
142 if ((presto
->retval
= ftdi_read_data(&presto
->ftdic
, buf
+ ftbytes
, size
- ftbytes
)) < 0)
144 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto
->ftdic
));
145 return ERROR_JTAG_DEVICE_ERROR
;
147 ftbytes
+= presto
->retval
;
149 gettimeofday(&now
, NULL
);
150 if ((now
.tv_sec
> timeout
.tv_sec
) || ((now
.tv_sec
== timeout
.tv_sec
) && (now
.tv_usec
> timeout
.tv_usec
)))
157 /* this is just a warning, there might have been timeout when detecting PRESTO, which is not fatal */
158 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)",
159 (unsigned)ftbytes
, (unsigned)size
);
160 return ERROR_JTAG_DEVICE_ERROR
;
166 #if BUILD_PRESTO_FTD2XX == 1
167 static int presto_open_ftd2xx(char *req_serial
)
172 char devname
[FT_DEVICE_NAME_LEN
];
178 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
181 /* Add non-standard Vid/Pid to the linux driver */
182 if ((presto
->status
= FT_SetVIDPID(PRESTO_VID
, PRESTO_PID
)) != FT_OK
)
184 LOG_ERROR("couldn't add PRESTO VID/PID");
189 if ((presto
->status
= FT_ListDevices(&numdevs
, NULL
, FT_LIST_NUMBER_ONLY
)) != FT_OK
)
191 LOG_ERROR("FT_ListDevices failed: %i", (int)presto
->status
);
192 return ERROR_JTAG_DEVICE_ERROR
;
195 LOG_DEBUG("FTDI devices available: %lu", numdevs
);
196 for (i
= 0; i
< numdevs
; i
++)
198 if ((presto
->status
= FT_Open(i
, &(presto
->handle
))) != FT_OK
)
200 /* this is not fatal, the device may be legitimately open by other process, hence debug message only */
201 LOG_DEBUG("FT_Open failed: %i", (int)presto
->status
);
204 LOG_DEBUG("FTDI device %i open", (int)i
);
206 if ((presto
->status
= FT_GetDeviceInfo(presto
->handle
, &device
, &vidpid
,
207 presto
->serial
, devname
, NULL
)) == FT_OK
)
209 if (vidpid
== PRESTO_VID_PID
210 && (req_serial
== NULL
|| !strcmp(presto
->serial
, req_serial
)))
214 LOG_DEBUG("FT_GetDeviceInfo failed: %lu", presto
->status
);
216 LOG_DEBUG("FTDI device %i does not match, closing", (int)i
);
217 FT_Close(presto
->handle
);
218 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
221 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
222 return ERROR_JTAG_DEVICE_ERROR
; /* presto not open, return */
224 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 1)) != FT_OK
)
225 return ERROR_JTAG_DEVICE_ERROR
;
228 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 100, 0)) != FT_OK
)
229 return ERROR_JTAG_DEVICE_ERROR
;
231 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
232 return ERROR_JTAG_DEVICE_ERROR
;
235 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
236 return ERROR_JTAG_DEVICE_ERROR
;
238 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
239 probably a bug in library threading */
241 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
242 return ERROR_JTAG_DEVICE_ERROR
;
246 LOG_DEBUG("PRESTO reset");
248 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
249 return ERROR_JTAG_DEVICE_ERROR
;
250 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x80, 1)) != FT_OK
)
251 return ERROR_JTAG_DEVICE_ERROR
;
252 if ((presto
->status
= FT_SetBaudRate(presto
->handle
, 9600)) != FT_OK
)
253 return ERROR_JTAG_DEVICE_ERROR
;
256 for (i
= 0; i
< 4 * 62; i
++)
257 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
258 return ERROR_JTAG_DEVICE_ERROR
;
262 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x00, 0)) != FT_OK
)
263 return ERROR_JTAG_DEVICE_ERROR
;
265 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
266 return ERROR_JTAG_DEVICE_ERROR
;
269 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
270 return ERROR_JTAG_DEVICE_ERROR
;
272 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
273 probably a bug in library threading */
275 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
276 return ERROR_JTAG_DEVICE_ERROR
;
280 LOG_DEBUG("PRESTO not responding");
281 return ERROR_JTAG_DEVICE_ERROR
;
285 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 0, 0)) != FT_OK
)
286 return ERROR_JTAG_DEVICE_ERROR
;
289 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
290 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
291 return ERROR_JTAG_DEVICE_ERROR
;
296 #elif BUILD_PRESTO_LIBFTDI == 1
297 static int presto_open_libftdi(char *req_serial
)
301 LOG_DEBUG("searching for PRESTO using libftdi");
303 /* initialize FTDI context structure */
304 if (ftdi_init(&presto
->ftdic
) < 0)
306 LOG_ERROR("unable to init libftdi: %s", presto
->ftdic
.error_str
);
307 return ERROR_JTAG_DEVICE_ERROR
;
310 /* context, vendor id, product id */
311 if (ftdi_usb_open_desc(&presto
->ftdic
, PRESTO_VID
, PRESTO_PID
, NULL
, req_serial
) < 0)
313 LOG_ERROR("unable to open PRESTO: %s", presto
->ftdic
.error_str
);
314 return ERROR_JTAG_DEVICE_ERROR
;
317 if (ftdi_usb_reset(&presto
->ftdic
) < 0)
319 LOG_ERROR("unable to reset PRESTO device");
320 return ERROR_JTAG_DEVICE_ERROR
;
323 if (ftdi_set_latency_timer(&presto
->ftdic
, 1) < 0)
325 LOG_ERROR("unable to set latency timer");
326 return ERROR_JTAG_DEVICE_ERROR
;
329 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
331 LOG_ERROR("unable to purge PRESTO buffers");
332 return ERROR_JTAG_DEVICE_ERROR
;
336 if (presto_write(&presto_data
, 1) != ERROR_OK
)
338 LOG_ERROR("error writing to PRESTO");
339 return ERROR_JTAG_DEVICE_ERROR
;
342 if (presto_read(&presto_data
, 1) != ERROR_OK
)
344 LOG_DEBUG("no response from PRESTO, retrying");
346 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
347 return ERROR_JTAG_DEVICE_ERROR
;
350 if (presto_write(&presto_data
, 1) != ERROR_OK
)
351 return ERROR_JTAG_DEVICE_ERROR
;
353 if (presto_read(&presto_data
, 1) != ERROR_OK
)
355 LOG_ERROR("no response from PRESTO, giving up");
356 return ERROR_JTAG_DEVICE_ERROR
;
360 if (presto_write(presto_init_seq
, sizeof(presto_init_seq
)) != ERROR_OK
)
362 LOG_ERROR("error writing PRESTO init sequence");
363 return ERROR_JTAG_DEVICE_ERROR
;
368 #endif /* BUILD_PRESTO_LIBFTDI == 1 */
370 static int presto_open(char *req_serial
)
372 presto
->buff_out_pos
= 0;
373 presto
->buff_in_pos
= 0;
374 presto
->buff_in_len
= 0;
375 presto
->buff_in_exp
= 0;
377 presto
->total_out
= 0;
378 presto
->total_in
= 0;
380 presto
->jtag_tms
= 0;
381 presto
->jtag_tck
= 0;
382 presto
->jtag_rst
= 0;
383 presto
->jtag_tdi_data
= 0;
384 presto
->jtag_tdi_count
= 0;
386 presto
->jtag_speed
= 0;
388 #if BUILD_PRESTO_FTD2XX == 1
389 return presto_open_ftd2xx(req_serial
);
390 #elif BUILD_PRESTO_LIBFTDI == 1
391 return presto_open_libftdi(req_serial
);
395 static int presto_close(void)
398 int result
= ERROR_OK
;
400 #if BUILD_PRESTO_FTD2XX == 1
401 unsigned long ftbytes
;
403 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
406 presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
);
407 if (presto
->status
!= FT_OK
)
408 result
= ERROR_JTAG_DEVICE_ERROR
;
410 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
411 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
412 result
= ERROR_JTAG_DEVICE_ERROR
;
414 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 16)) != FT_OK
)
415 result
= ERROR_JTAG_DEVICE_ERROR
;
417 if ((presto
->status
= FT_Close(presto
->handle
)) != FT_OK
)
418 result
= ERROR_JTAG_DEVICE_ERROR
;
420 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
422 #elif BUILD_PRESTO_LIBFTDI == 1
424 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, presto_init_seq
, sizeof(presto_init_seq
))) != sizeof(presto_init_seq
))
425 result
= ERROR_JTAG_DEVICE_ERROR
;
427 if ((presto
->retval
= ftdi_set_latency_timer(&presto
->ftdic
, 16)) < 0)
428 result
= ERROR_JTAG_DEVICE_ERROR
;
430 if ((presto
->retval
= ftdi_usb_close(&presto
->ftdic
)) < 0)
431 result
= ERROR_JTAG_DEVICE_ERROR
;
433 ftdi_deinit(&presto
->ftdic
);
439 static int presto_flush(void)
441 if (presto
->buff_out_pos
== 0)
444 #if BUILD_PRESTO_FTD2XX == 1
445 if (presto
->status
!= FT_OK
)
446 #elif BUILD_PRESTO_LIBFTDI == 1
447 if (presto
->retval
< 0)
450 LOG_DEBUG("error in previous communication, canceling I/O operation");
451 return ERROR_JTAG_DEVICE_ERROR
;
454 if (presto_write(presto
->buff_out
, presto
->buff_out_pos
) != ERROR_OK
)
456 presto
->buff_out_pos
= 0;
457 return ERROR_JTAG_DEVICE_ERROR
;
460 presto
->total_out
+= presto
->buff_out_pos
;
461 presto
->buff_out_pos
= 0;
463 if (presto
->buff_in_exp
== 0)
466 presto
->buff_in_pos
= 0;
467 presto
->buff_in_len
= 0;
469 if (presto_read(presto
->buff_in
, presto
->buff_in_exp
) != ERROR_OK
)
471 presto
->buff_in_exp
= 0;
472 return ERROR_JTAG_DEVICE_ERROR
;
475 presto
->total_in
+= presto
->buff_in_exp
;
476 presto
->buff_in_len
= presto
->buff_in_exp
;
477 presto
->buff_in_exp
= 0;
482 static int presto_sendbyte(int data
)
484 if (data
== EOF
) return presto_flush();
486 if (presto
->buff_out_pos
< BUFFER_SIZE
)
488 presto
->buff_out
[presto
->buff_out_pos
++] = (uint8_t)data
;
489 if (((data
& 0xC0) == 0x40) || ((data
& 0xD0)== 0xD0))
490 presto
->buff_in_exp
++;
493 return ERROR_JTAG_DEVICE_ERROR
;
495 #if BUILD_PRESTO_FTD2XX == 1
496 if (presto
->buff_out_pos
>= BUFFER_SIZE
)
497 #elif BUILD_PRESTO_LIBFTDI == 1
498 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 bytes only!) */
499 if (presto
->buff_out_pos
>= BUFFER_SIZE
|| presto
->buff_in_exp
== 128)
501 return presto_flush();
507 static int presto_getbyte(void)
509 if (presto
->buff_in_pos
< presto
->buff_in_len
)
510 return presto
->buff_in
[presto
->buff_in_pos
++];
512 if (presto
->buff_in_exp
== 0)
515 if (presto_flush() != ERROR_OK
)
518 if (presto
->buff_in_pos
< presto
->buff_in_len
)
519 return presto
->buff_in
[presto
->buff_in_pos
++];
525 /* -------------------------------------------------------------------------- */
527 static int presto_tdi_flush(void)
529 if (presto
->jtag_tdi_count
== 0)
532 if (presto
->jtag_tck
== 0)
534 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
538 presto
->jtag_tdi_data
|= (presto
->jtag_tdi_count
- 1) << 4;
539 presto_sendbyte(presto
->jtag_tdi_data
);
540 presto
->jtag_tdi_count
= 0;
541 presto
->jtag_tdi_data
= 0;
546 static int presto_tck_idle(void)
548 if (presto
->jtag_tck
== 1)
550 presto_sendbyte(0xCA);
551 presto
->jtag_tck
= 0;
557 /* -------------------------------------------------------------------------- */
559 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
)
564 if (presto
->jtag_tck
== 0)
566 presto_sendbyte(0xA4); /* LED idicator - JTAG active */
568 else if (presto
->jtag_speed
== 0 && !tdo_req
&& tms
== presto
->jtag_tms
)
570 presto
->jtag_tdi_data
|= (tdi
!= 0) << presto
->jtag_tdi_count
;
572 if (++presto
->jtag_tdi_count
== 4)
580 cmd
= tdi
? 0xCB : 0xCA;
581 presto_sendbyte(cmd
);
583 if (tms
!= presto
->jtag_tms
)
585 presto_sendbyte((tms
? 0xEC : 0xE8) | (presto
->jtag_rst
? 0x02 : 0));
586 presto
->jtag_tms
= tms
;
589 /* delay with TCK low */
590 for (i
= presto
->jtag_speed
; i
> 1; i
--)
591 presto_sendbyte(cmd
);
594 presto_sendbyte(cmd
| (tdo_req
? 0x10 : 0));
596 /* delay with TCK high */
597 for (i
= presto
->jtag_speed
; i
> 1; i
--)
598 presto_sendbyte(cmd
);
600 presto
->jtag_tck
= 1;
605 static int presto_bitq_flush(void)
610 presto_sendbyte(0xA0); /* LED idicator - JTAG idle */
612 return presto_flush();
615 static int presto_bitq_in_rdy(void)
617 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
619 return presto
->buff_in_len
-presto
->buff_in_pos
;
622 static int presto_bitq_in(void)
624 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
626 if (presto
->buff_in
[presto
->buff_in_pos
++]&0x08) return 1;
630 static int presto_bitq_sleep(unsigned long us
)
644 waits
= us
/ 170 + 2;
646 presto_sendbyte(0x80);
651 static int presto_bitq_reset(int trst
, int srst
)
656 /* add a delay after possible TCK transition */
657 presto_sendbyte(0x80);
658 presto_sendbyte(0x80);
660 presto
->jtag_rst
= trst
|| srst
;
661 presto_sendbyte((presto
->jtag_rst
? 0xEA : 0xE8) | (presto
->jtag_tms
? 0x04 : 0));
666 static struct bitq_interface presto_bitq
= {
667 .out
= &presto_bitq_out
,
668 .flush
= &presto_bitq_flush
,
669 .sleep
= &presto_bitq_sleep
,
670 .reset
= &presto_bitq_reset
,
671 .in_rdy
= &presto_bitq_in_rdy
,
672 .in
= &presto_bitq_in
,
675 /* -------------------------------------------------------------------------- */
677 static int presto_jtag_khz(int khz
, int *jtag_speed
)
682 return ERROR_INVALID_ARGUMENTS
;
685 if (khz
>= 3000) *jtag_speed
= 0;
686 else *jtag_speed
= (1000 + khz
-1)/khz
;
691 static int presto_jtag_speed_div(int speed
, int *khz
)
693 if ((speed
< 0) || (speed
> 1000))
696 return ERROR_INVALID_ARGUMENTS
;
699 if (speed
== 0) *khz
= 3000;
700 else *khz
= 1000/speed
;
705 static int presto_jtag_speed(int speed
)
709 if (presto_jtag_speed_div(speed
, &khz
))
711 return ERROR_INVALID_ARGUMENTS
;
714 presto
->jtag_speed
= speed
;
717 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed
, khz
/1000);
719 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed
, khz
);
724 static char *presto_serial
;
726 COMMAND_HANDLER(presto_handle_serial_command
)
732 presto_serial
= strdup(CMD_ARGV
[0]);
736 LOG_ERROR("expected exactly one argument to presto_serial <serial-number>");
742 static const struct command_registration presto_command_handlers
[] = {
744 .name
= "presto_serial",
745 .handler
= &presto_handle_serial_command
,
746 .mode
= COMMAND_CONFIG
,
747 .help
= "configure serial port",
748 .usage
= "<devname>",
750 COMMAND_REGISTRATION_DONE
753 static int presto_jtag_init(void)
755 if (presto_open(presto_serial
) != ERROR_OK
)
758 if (presto_serial
!= NULL
)
759 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
761 LOG_ERROR("Cannot open PRESTO");
762 return ERROR_JTAG_INIT_FAILED
;
764 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
766 /* use JTAG speed setting from configuration file */
767 presto_jtag_speed(jtag_get_speed());
769 bitq_interface
= &presto_bitq
;
773 static int presto_jtag_quit(void)
777 LOG_INFO("PRESTO closed");
782 presto_serial
= NULL
;
788 struct jtag_interface presto_interface
= {
791 .commands
= presto_command_handlers
,
793 .execute_queue
= &bitq_execute_queue
,
794 .speed
= &presto_jtag_speed
,
795 .khz
= &presto_jtag_khz
,
796 .speed_div
= &presto_jtag_speed_div
,
798 .init
= &presto_jtag_init
,
799 .quit
= &presto_jtag_quit
,
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)