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

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)