- reworked presto.c to allow use of either FTD2XX or libftdi (libftdi not functional...
[openocd.git] / src / jtag / presto.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
3 * chromy@asix.cz *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #if IS_CYGWIN == 1
25 #include "windows.h"
26 #undef ERROR
27 #endif
28
29 #include "replacements.h"
30
31 /* project specific includes */
32 #include "log.h"
33 #include "types.h"
34 #include "jtag.h"
35 #include "configuration.h"
36 #include "time_support.h"
37 #include "bitq.h"
38
39 /* system includes */
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43
44 #include <sys/time.h>
45 #include <time.h>
46
47 /* PRESTO access library includes */
48 #if BUILD_PRESTO_FTD2XX == 1
49 #include <ftd2xx.h>
50 #elif BUILD_PRESTO_LIBFTDI == 1
51 #include <ftdi.h>
52 #endif
53
54
55 int presto_jtag_speed(int speed);
56 int presto_jtag_register_commands(struct command_context_s *cmd_ctx);
57 int presto_jtag_init(void);
58 int presto_jtag_quit(void);
59
60 jtag_interface_t presto_interface =
61 {
62 .name = "presto",
63 .execute_queue = bitq_execute_queue,
64 .support_pathmove = 1,
65 .speed = presto_jtag_speed,
66 .register_commands = presto_jtag_register_commands,
67 .init = presto_jtag_init,
68 .quit = presto_jtag_quit,
69 };
70
71
72 int presto_bitq_out(int tms, int tdi, int tdo_req);
73 int presto_bitq_flush(void);
74 int presto_bitq_sleep(unsigned long us);
75 int presto_bitq_reset(int trst, int srst);
76 int presto_bitq_in_rdy(void);
77 int presto_bitq_in(void);
78
79 bitq_interface_t presto_bitq =
80 {
81 .out = presto_bitq_out,
82 .flush = presto_bitq_flush,
83 .sleep = presto_bitq_sleep,
84 .reset = presto_bitq_reset,
85 .in_rdy = presto_bitq_in_rdy,
86 .in = presto_bitq_in,
87 };
88
89
90 /* -------------------------------------------------------------------------- */
91
92
93 #define FT_DEVICE_NAME_LEN 64
94 #define FT_DEVICE_SERNUM_LEN 64
95
96 #define PRESTO_VID_PID 0x0403f1a0
97 #define PRESTO_VID (0x0403)
98 #define PRESTO_PID (0xf1a0)
99
100 #define BUFFER_SIZE (64*62)
101
102 typedef struct presto_s
103 {
104 #if BUILD_PRESTO_FTD2XX == 1
105 FT_HANDLE handle;
106 FT_STATUS status;
107 #elif BUILD_PRESTO_LIBFTDI == 1
108 struct ftdi_context ftdic;
109 int retval;
110 #endif
111
112 char serial[FT_DEVICE_SERNUM_LEN];
113
114 u8 buff_out[BUFFER_SIZE];
115 int buff_out_pos;
116
117 u8 buff_in[BUFFER_SIZE];
118 int buff_in_exp; /* expected in buffer length */
119 int buff_in_len; /* length of data received */
120 int buff_in_pos;
121
122 unsigned long total_out;
123 unsigned long total_in;
124
125 int jtag_tms; /* last tms state */
126 int jtag_tck; /* last tck state */
127
128 int jtag_tdi_data;
129 int jtag_tdi_count;
130
131 } presto_t;
132
133 presto_t presto_state;
134 presto_t *presto = &presto_state;
135
136 u8 presto_init_seq[] =
137 {
138 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
139 };
140
141 int presto_write(u8 *buf, int size, u32* bytes_written)
142 {
143 #if BUILD_PRESTO_FTD2XX == 1
144 DWORD dw_bytes_written;
145 if ((presto->status = FT_Write(presto->handle, buf, size, &dw_bytes_written)) != FT_OK)
146 {
147 *bytes_written = dw_bytes_written;
148 ERROR("FT_Write returned: %lu", presto->status);
149 return ERROR_JTAG_DEVICE_ERROR;
150 }
151 else
152 {
153 *bytes_written = dw_bytes_written;
154 return ERROR_OK;
155 }
156 #elif BUILD_PRESTO_LIBFTDI == 1
157 if ((presto->retval = ftdi_write_data(&presto->ftdic, buf, size)) < 0)
158 {
159 *bytes_written = 0;
160 ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto->ftdic));
161 return ERROR_JTAG_DEVICE_ERROR;
162 }
163 else
164 {
165 *bytes_written = retval;
166 return ERROR_OK;
167 }
168 #endif
169 }
170
171 int presto_read(u8* buf, int size, u32* bytes_read)
172 {
173 #if BUILD_PRESTO_FTD2XX == 1
174 DWORD dw_bytes_read;
175 int timeout = 5;
176 *bytes_read = 0;
177
178 while ((*bytes_read < size) && timeout--)
179 {
180 if ((presto->status = FT_Read(presto->handle, buf + *bytes_read, size -
181 *bytes_read, &dw_bytes_read)) != FT_OK)
182 {
183 *bytes_read = 0;
184 ERROR("FT_Read returned: %lu", presto->status);
185 return ERROR_JTAG_DEVICE_ERROR;
186 }
187 *bytes_read += dw_bytes_read;
188 }
189 #elif BUILD_PRESTO_LIBFTDI == 1
190 int timeout = 100;
191 *bytes_read = 0;
192
193 while ((*bytes_read < size) && timeout--)
194 {
195 if ((presto->retval = ftdi_read_data(&presto->ftdic, buf + *bytes_read, size - *bytes_read)) < 0)
196 {
197 *bytes_read = 0;
198 ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto->ftdic));
199 return ERROR_JTAG_DEVICE_ERROR;
200 }
201 *bytes_read += retval;
202 }
203 #endif
204
205 if (*bytes_read < size)
206 {
207 ERROR("couldn't read the requested number of bytes from PRESTO (%i < %i)", *bytes_read, size);
208 return ERROR_JTAG_DEVICE_ERROR;
209 }
210
211 return ERROR_OK;
212 }
213
214 #if BUILD_PRESTO_FTD2XX == 1
215 int presto_open_ftd2xx(char *req_serial)
216 {
217 int i;
218 DWORD numdevs;
219 DWORD vidpid;
220 char devname[FT_DEVICE_NAME_LEN];
221 FT_DEVICE device;
222
223 BYTE presto_data;
224 unsigned long ftbytes;
225
226 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
227
228 #if IS_WIN32 == 0
229 /* Add non-standard Vid/Pid to the linux driver */
230 if ((presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID)) != FT_OK)
231 {
232 ERROR("couldn't add PRESTO VID/PID");
233 exit(-1);
234 }
235 #endif
236
237 if ((presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY)) != FT_OK)
238 {
239 ERROR("FT_ListDevices failed: %i", (int)presto->status);
240 return ERROR_JTAG_INIT_FAILED;
241 }
242
243 for (i = 0; i < numdevs; i++)
244 {
245 if (FT_Open(i, &(presto->handle)) != FT_OK)
246 {
247 ERROR("FT_Open failed: %i", (int)presto->status);
248 continue;
249 }
250
251 if (FT_GetDeviceInfo(presto->handle, &device, &vidpid,
252 presto->serial, devname, NULL) == FT_OK)
253 {
254 if (vidpid == PRESTO_VID_PID
255 && (req_serial == NULL || !strcmp(presto->serial, req_serial)))
256 break;
257 }
258
259 FT_Close(presto->handle);
260 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
261 }
262
263 if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
264 return ERROR_JTAG_INIT_FAILED;
265 if ((presto->status = FT_SetLatencyTimer(presto->handle, 1)) != FT_OK)
266 return ERROR_JTAG_INIT_FAILED;
267 if ((presto->status = FT_SetTimeouts(presto->handle, 100, 0)) != FT_OK)
268 return ERROR_JTAG_INIT_FAILED;
269 if ((presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX)) != FT_OK)
270 return ERROR_JTAG_INIT_FAILED;
271
272 presto_data = 0xD0;
273 if ((presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes)) != FT_OK)
274 return ERROR_JTAG_INIT_FAILED;
275 if ((presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes)) != FT_OK)
276 return ERROR_JTAG_INIT_FAILED;
277
278 if (ftbytes!=1)
279 {
280 if ((presto->status = FT_SetBitMode(presto->handle, 0x80, 1)) != FT_OK)
281 return ERROR_JTAG_INIT_FAILED;
282 if ((presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX)) != FT_OK)
283 return ERROR_JTAG_INIT_FAILED ;
284 if ((presto->status = FT_SetBaudRate(presto->handle, 9600)) != FT_OK)
285 return ERROR_JTAG_INIT_FAILED;
286
287 presto_data = 0;
288 for (i = 0; i < 4 * 62; i++)
289 if ((presto->status=FT_Write(presto->handle, &presto_data, 1, &ftbytes)) != FT_OK)
290 return ERROR_JTAG_INIT_FAILED;
291
292 usleep(100000);
293
294 if ((presto->status = FT_SetBitMode(presto->handle, 0x00, 0)) != FT_OK)
295 return ERROR_JTAG_INIT_FAILED;
296 if ((presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX)) != FT_OK)
297 return ERROR_JTAG_INIT_FAILED;
298
299 presto_data = 0xD0;
300 if ((presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes)) != FT_OK)
301 return ERROR_JTAG_INIT_FAILED;
302 if ((presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes)) != FT_OK)
303 return ERROR_JTAG_INIT_FAILED;
304 if (ftbytes!=1)
305 return ERROR_JTAG_INIT_FAILED;
306 }
307
308 if ((presto->status = FT_SetTimeouts(presto->handle, 0, 0)) != FT_OK)
309 return ERROR_JTAG_INIT_FAILED;
310
311 presto->status = FT_Write(presto->handle, &presto_init_seq, sizeof(presto_init_seq), &ftbytes);
312 if (presto->status != FT_OK)
313 return ERROR_JTAG_INIT_FAILED;
314 if (ftbytes != sizeof(presto_init_seq))
315 return ERROR_JTAG_INIT_FAILED;
316
317 return ERROR_OK;
318 }
319
320 #elif BUILD_PRESTO_LIBFTDI == 1
321 int presto_open_libftdi(char *req_serial)
322 {
323 u8 presto_data;
324 u32 ftbytes;
325
326 DEBUG("searching for presto JTAG interface using libftdi");
327
328 /* context, vendor id, product id */
329 if (ftdi_usb_open_desc(&presto->ftdic, PRESTO_VID, PRESTO_PID, NULL, req_serial) < 0)
330 {
331 ERROR("unable to open presto: %s", presto->ftdic.error_str);
332 return ERROR_JTAG_INIT_FAILED;
333 }
334
335 if (ftdi_usb_reset(&presto->ftdic) < 0)
336 {
337 ERROR("unable to reset presto device");
338 return ERROR_JTAG_INIT_FAILED;
339 }
340
341 if (ftdi_set_latency_timer(&presto->ftdic, 1) < 0)
342 {
343 ERROR("unable to set latency timer");
344 return ERROR_JTAG_INIT_FAILED;
345 }
346
347 if (ftdi_usb_purge_buffers(&presto->ftdic) < 0)
348 {
349 ERROR("unable to purge presto buffer");
350 return ERROR_JTAG_INIT_FAILED;
351 }
352
353 presto_data = 0xD0;
354 if ((presto->retval = presto_write(&presto_data, 1, &ftbytes)) != ERROR_OK)
355 return ERROR_JTAG_INIT_FAILED;
356 if ((presto->retval = presto_read(&presto_data, 1, &ftbytes)) != ERROR_OK)
357 return ERROR_JTAG_INIT_FAILED;
358
359 return ERROR_OK;
360 }
361 #endif /* BUILD_PRESTO_LIBFTDI == 1 */
362
363 int presto_open(char *req_serial)
364 {
365 presto->buff_out_pos=0;
366 presto->buff_in_pos=0;
367 presto->buff_in_len=0;
368 presto->buff_in_exp=0;
369
370 presto->total_out=0;
371 presto->total_in=0;
372
373 presto->jtag_tms=0;
374 presto->jtag_tck=0;
375 presto->jtag_tdi_data=0;
376 presto->jtag_tdi_count=0;
377
378 #if BUILD_PRESTO_FTD2XX == 1
379 return presto_open_ftd2xx(req_serial);
380 #elif BUILD_PRESTO_LIBFTDI == 1
381 return presto_open_libftdi(req_serial);
382 #endif
383 }
384
385 int presto_close(void)
386 {
387
388 int result = ERROR_OK;
389
390 #if BUID_PRESTO_FTD2XX == 1
391 unsigned long ftbytes;
392
393 if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
394 return result;
395
396 presto->status = FT_Write(presto->handle, &presto_init_seq, sizeof(presto_init_seq), &ftbytes);
397 if (presto->status != FT_OK)
398 result = PRST_ERR;
399 if (ftbytes != sizeof(presto_init_seq))
400 result = PRST_TIMEOUT;
401
402 if ((presto->status = FT_SetLatencyTimer(presto->handle, 16)) != FT_OK)
403 result = PRST_ERR;
404
405 if ((presto->status = FT_Close(presto->handle)) != FT_OK)
406 result = PRST_ERR;
407 else
408 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
409
410 #elif BUILD_PRESTO_LIBFTDI == 1
411
412 if ((presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq))) < 0)
413 {
414 result = ERROR_JTAG_DEVICE_ERROR;
415 }
416
417 if ((presto->retval = ftdi_set_latency_timer(&presto->ftdic, 16)) < 0)
418 {
419 result = ERROR_JTAG_DEVICE_ERROR;
420 }
421
422 ftdi_deinit(&presto->ftdic);
423
424 #endif
425
426 return result;
427 }
428
429
430 int presto_flush(void)
431 {
432 u32 ftbytes;
433
434 if (presto->buff_out_pos == 0)
435 return ERROR_OK;
436
437 #if BUILD_PRESTO_FTD2XX == 1
438 if (presto->status != FT_OK)
439 #elif BUILD_PRESTO_LIBFTDI == 1
440 if (presto->retval != ERROR_OK)
441 #endif
442 return ERROR_JTAG_DEVICE_ERROR;
443
444
445 if (presto_write(presto->buff_out, presto->buff_out_pos, &ftbytes) != ERROR_OK)
446 {
447 presto->buff_out_pos = 0;
448 return ERROR_JTAG_DEVICE_ERROR;
449 }
450
451 presto->total_out += ftbytes;
452
453 if (presto->buff_out_pos != ftbytes)
454 {
455 presto->buff_out_pos = 0;
456 return ERROR_JTAG_DEVICE_ERROR;
457 }
458
459 presto->buff_out_pos = 0;
460
461 if (presto->buff_in_exp == 0)
462 return ERROR_OK;
463
464 presto->buff_in_pos = 0;
465 presto->buff_in_len = 0;
466
467 if (presto_read(presto->buff_in, presto->buff_in_exp, &ftbytes) != ERROR_OK)
468 {
469 presto->buff_in_exp = 0;
470 return ERROR_JTAG_DEVICE_ERROR;
471 }
472
473 presto->total_in += ftbytes;
474
475 if (ftbytes != presto->buff_in_exp)
476 {
477 presto->buff_in_exp = 0;
478 return ERROR_JTAG_DEVICE_ERROR;
479 }
480
481 presto->buff_in_len = presto->buff_in_exp;
482 presto->buff_in_exp = 0;
483
484 return ERROR_OK;
485 }
486
487
488 int presto_sendbyte(int data)
489 {
490 if (data == EOF) return presto_flush();
491
492 if (presto->buff_out_pos < BUFFER_SIZE)
493 {
494 presto->buff_out[presto->buff_out_pos++] = (u8)data;
495 if (((data & 0xC0) == 0x40) || ((data & 0xD0)== 0xD0))
496 presto->buff_in_exp++;
497 }
498 else
499 return ERROR_JTAG_DEVICE_ERROR;
500
501 if (presto->buff_out_pos >= BUFFER_SIZE)
502 return presto_flush();
503
504 return ERROR_OK;
505 }
506
507
508 int presto_getbyte(void)
509 {
510 if (presto->buff_in_pos < presto->buff_in_len)
511 return presto->buff_in[presto->buff_in_pos++];
512
513 if (presto->buff_in_exp == 0)
514 return -1;
515
516 if (presto_flush() != ERROR_OK)
517 return -1;
518
519 if (presto->buff_in_pos<presto->buff_in_len)
520 return presto->buff_in[presto->buff_in_pos++];
521
522 return -1;
523 }
524
525
526 /* -------------------------------------------------------------------------- */
527
528
529 int presto_bitq_out(int tms, int tdi, int tdo_req)
530 {
531 unsigned char cmdparam;
532
533 if (presto->jtag_tck == 0)
534 {
535 presto_sendbyte(0xA4);
536 presto->jtag_tck = 1;
537 }
538
539 else if (!tdo_req && tms == presto->jtag_tms)
540 {
541 if (presto->jtag_tdi_count == 0)
542 presto->jtag_tdi_data = (tdi != 0);
543 else
544 presto->jtag_tdi_data |= (tdi != 0) << presto->jtag_tdi_count;
545
546 if (++presto->jtag_tdi_count == 4)
547 {
548 presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4;
549 presto_sendbyte(presto->jtag_tdi_data);
550 presto->jtag_tdi_count = 0;
551 }
552 return 0;
553 }
554
555 if (presto->jtag_tdi_count)
556 {
557 presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4;
558 presto_sendbyte(presto->jtag_tdi_data);
559 presto->jtag_tdi_count = 0;
560 }
561
562 if (tdi)
563 cmdparam = 0x0B;
564 else
565 cmdparam = 0x0A;
566
567 presto_sendbyte( 0xC0 | cmdparam);
568
569 if (tms != presto->jtag_tms)
570 {
571 if (tms)
572 presto_sendbyte(0xEC);
573 else
574 presto_sendbyte(0xE8);
575 presto->jtag_tms = tms;
576 }
577
578 if (tdo_req)
579 presto_sendbyte(0xD4 | cmdparam);
580 else
581 presto_sendbyte(0xC4|cmdparam);
582
583 return 0;
584 }
585
586
587 int presto_bitq_flush(void)
588 {
589 if (presto->jtag_tdi_count)
590 {
591 presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4;
592 presto_sendbyte(presto->jtag_tdi_data);
593 presto->jtag_tdi_count = 0;
594 }
595
596 presto_sendbyte(0xCA);
597 presto->jtag_tck = 0;
598
599 presto_sendbyte(0xA0);
600
601 return presto_flush();
602 }
603
604
605 int presto_bitq_in_rdy(void)
606 {
607 if (presto->buff_in_pos>=presto->buff_in_len)
608 return 0;
609 return presto->buff_in_len-presto->buff_in_pos;
610 }
611
612
613 int presto_bitq_in(void)
614 {
615 if (presto->buff_in_pos>=presto->buff_in_len)
616 return -1;
617 if (presto->buff_in[presto->buff_in_pos++]&0x08) return 1;
618 return 0;
619 }
620
621
622 int presto_bitq_sleep(unsigned long us)
623 {
624 long waits;
625
626 if (us > 100000)
627 {
628 presto_bitq_flush();
629 jtag_sleep(us);
630 return 0;
631 }
632
633 waits = us / 170 + 2;
634 while (waits--)
635 presto_sendbyte(0x80);
636
637 return 0;
638 }
639
640
641 int presto_bitq_reset(int trst, int srst)
642 {
643 unsigned char cmd;
644
645 cmd = 0xE8;
646 if (presto->jtag_tms)
647 cmd |= 0x04;
648
649 if (trst || srst)
650 cmd |= 0x02;
651
652 presto_sendbyte(cmd);
653 return 0;
654 }
655
656
657 /* -------------------------------------------------------------------------- */
658
659
660 int presto_jtag_speed(int speed)
661 {
662 jtag_speed = speed;
663 return ERROR_OK;
664 }
665
666
667 char *presto_serial;
668
669 int presto_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
670 {
671 if (argc == 1)
672 {
673 if (presto_serial)
674 free(presto_serial);
675 presto_serial = strdup(args[0]);
676 }
677 else
678 {
679 ERROR("expected exactly one argument to presto_serial <serial-number>");
680 }
681
682 return ERROR_OK;
683 }
684
685
686 int presto_jtag_register_commands(struct command_context_s *cmd_ctx)
687 {
688 register_command(cmd_ctx, NULL, "presto_serial", presto_handle_serial_command,
689 COMMAND_CONFIG, NULL);
690 return ERROR_OK;
691 }
692
693
694 int presto_jtag_init(void)
695 {
696 if (presto_open(presto_serial) != ERROR_OK)
697 {
698 presto_close();
699 if (presto_serial != NULL)
700 ERROR("Cannot open PRESTO, serial number '%s'", presto_serial);
701 else
702 ERROR("Cannot open PRESTO");
703 return ERROR_JTAG_INIT_FAILED;
704 }
705 INFO("PRESTO open, serial number '%s'", presto->serial);
706
707 bitq_interface = &presto_bitq;
708 return ERROR_OK;
709 }
710
711
712 int presto_jtag_quit(void)
713 {
714 bitq_cleanup();
715 presto_close();
716 INFO("PRESTO closed");
717
718 if (presto_serial)
719 {
720 free(presto_serial);
721 presto_serial = NULL;
722 }
723
724 return ERROR_OK;
725 }

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)