5d1084cebcb9d0d4c2997c5af1bebf21f3f8ab89
[openocd.git] / src / jtag / drivers / openjtag.c
1 /*******************************************************************************
2 * Driver for OpenJTAG Project (www.openjtag.org) *
3 * Compatible with libftdi driver. *
4 * *
5 * Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com> *
6 * *
7 * Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. <corbin.ryan@gmail.com> *
8 * Updated to work with OpenOCD v0.7.0. Fixed libftdi read speed issue. *
9 * *
10 * Based on usb_blaster.c *
11 * Copyright (C) 2009 Catalin Patulea *
12 * Copyright (C) 2006 Kolja Waschk *
13 * *
14 * And jlink.c *
15 * Copyright (C) 2008 by Spencer Oliver *
16 * spen@spen-soft.co.uk *
17 * *
18 * This program is free software; you can redistribute it and/or modify *
19 * it under the terms of the GNU General Public License as published by *
20 * the Free Software Foundation; either version 2 of the License, or *
21 * (at your option) any later version. *
22 * *
23 * This program is distributed in the hope that it will be useful, *
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
26 * GNU General Public License for more details. *
27 * *
28 * You should have received a copy of the GNU General Public License *
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
30 ***************************************************************************/
31
32 /***************************************************************************
33 * Version 1.0 Tested on a MCBSTM32 board using a Cortex-M3 (stm32f103x), *
34 * GDB and Eclipse under Linux (Ubuntu 10.04) *
35 * *
36 ***************************************************************************/
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include <jtag/interface.h>
43 #include <jtag/commands.h>
44 #include "usb_common.h"
45
46 /*
47 * OpenJTAG-OpenOCD state conversion
48 */
49 typedef enum openjtag_tap_state {
50 OPENJTAG_TAP_INVALID = -1,
51 OPENJTAG_TAP_RESET = 0,
52 OPENJTAG_TAP_IDLE = 1,
53 OPENJTAG_TAP_SELECT_DR = 2,
54 OPENJTAG_TAP_CAPTURE_DR = 3,
55 OPENJTAG_TAP_SHIFT_DR = 4,
56 OPENJTAG_TAP_EXIT1_DR = 5,
57 OPENJTAG_TAP_PAUSE_DR = 6,
58 OPENJTAG_TAP_EXIT2_DR = 7,
59 OPENJTAG_TAP_UPDATE_DR = 8,
60 OPENJTAG_TAP_SELECT_IR = 9,
61 OPENJTAG_TAP_CAPURE_IR = 10,
62 OPENJTAG_TAP_SHIFT_IR = 11,
63 OPENJTAG_TAP_EXIT1_IR = 12,
64 OPENJTAG_TAP_PAUSE_IR = 13,
65 OPENJTAG_TAP_EXIT2_IR = 14,
66 OPENJTAG_TAP_UPDATE_IR = 15,
67 } openjtag_tap_state_t;
68
69 /* OPENJTAG access library includes */
70 #include <ftdi.h>
71
72 /* OpenJTAG vid/pid */
73 static uint16_t openjtag_vid = 0x0403;
74 static uint16_t openjtag_pid = 0x6001;
75
76 static char *openjtag_device_desc;
77
78 static struct ftdi_context ftdic;
79
80 #define OPENJTAG_BUFFER_SIZE 504
81 #define OPENJTAG_MAX_PENDING_RESULTS 256
82
83 struct openjtag_scan_result {
84 uint32_t bits; /* Length in bits*/
85 struct scan_command *command; /* Corresponding scan command */
86 uint8_t *buffer;
87 };
88
89 /* USB RX/TX buffers */
90 static int usb_tx_buf_offs;
91 static uint8_t usb_tx_buf[OPENJTAG_BUFFER_SIZE];
92 static uint32_t usb_rx_buf_len;
93 static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
94
95 /* Pending readings */
96 static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
97 static int openjtag_scan_result_count;
98
99 /* Openocd usb handler */
100 struct openocd {
101 struct usb_dev_handle *usb_handle;
102 };
103
104 #ifdef _DEBUG_USB_COMMS_
105
106 #define DEBUG_TYPE_READ 0
107 #define DEBUG_TYPE_WRITE 1
108 #define DEBUG_TYPE_OCD_READ 2
109 #define DEBUG_TYPE_BUFFER 3
110
111 #define LINE_LEN 16
112 static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type)
113 {
114 char line[128];
115 char s[4];
116 int i;
117 int j;
118
119 switch (type) {
120 case DEBUG_TYPE_READ:
121 sprintf(line, "USB READ %d bytes", length);
122 break;
123 case DEBUG_TYPE_WRITE:
124 sprintf(line, "USB WRITE %d bytes", length);
125 break;
126 case DEBUG_TYPE_OCD_READ:
127 sprintf(line, "TO OpenOCD %d bytes", length);
128 break;
129 case DEBUG_TYPE_BUFFER:
130 sprintf(line, "Buffer %d bytes", length);
131 break;
132 }
133
134 LOG_DEBUG("%s", line);
135
136 for (i = 0; i < length; i += LINE_LEN) {
137 switch (type) {
138 case DEBUG_TYPE_READ:
139 sprintf(line, "USB READ: %04x", i);
140 break;
141 case DEBUG_TYPE_WRITE:
142 sprintf(line, "USB WRITE: %04x", i);
143 break;
144 case DEBUG_TYPE_OCD_READ:
145 sprintf(line, "TO OpenOCD: %04x", i);
146 break;
147 case DEBUG_TYPE_BUFFER:
148 sprintf(line, "BUFFER: %04x", i);
149 break;
150 }
151
152 for (j = i; j < i + LINE_LEN && j < length; j++) {
153 sprintf(s, " %02x", buffer[j]);
154 strcat(line, s);
155 }
156 LOG_DEBUG("%s", line);
157 }
158
159 }
160
161 #endif
162
163 static int8_t openjtag_get_tap_state(int8_t state)
164 {
165
166 switch (state) {
167 case TAP_DREXIT2: return OPENJTAG_TAP_EXIT2_DR;
168 case TAP_DREXIT1: return OPENJTAG_TAP_EXIT1_DR;
169 case TAP_DRSHIFT: return OPENJTAG_TAP_SHIFT_DR;
170 case TAP_DRPAUSE: return OPENJTAG_TAP_PAUSE_DR;
171 case TAP_IRSELECT: return OPENJTAG_TAP_SELECT_IR;
172 case TAP_DRUPDATE: return OPENJTAG_TAP_UPDATE_DR;
173 case TAP_DRCAPTURE: return OPENJTAG_TAP_CAPTURE_DR;
174 case TAP_DRSELECT: return OPENJTAG_TAP_SELECT_DR;
175 case TAP_IREXIT2: return OPENJTAG_TAP_EXIT2_IR;
176 case TAP_IREXIT1: return OPENJTAG_TAP_EXIT1_IR;
177 case TAP_IRSHIFT: return OPENJTAG_TAP_SHIFT_IR;
178 case TAP_IRPAUSE: return OPENJTAG_TAP_PAUSE_IR;
179 case TAP_IDLE: return OPENJTAG_TAP_IDLE;
180 case TAP_IRUPDATE: return OPENJTAG_TAP_UPDATE_IR;
181 case TAP_IRCAPTURE: return OPENJTAG_TAP_CAPURE_IR;
182 case TAP_RESET: return OPENJTAG_TAP_RESET;
183 case TAP_INVALID:
184 default: return OPENJTAG_TAP_INVALID;
185 }
186 }
187
188 static int openjtag_buf_write(
189 uint8_t *buf, int size, uint32_t *bytes_written)
190 {
191 int retval;
192 #ifdef _DEBUG_USB_COMMS_
193 openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
194 #endif
195
196 retval = ftdi_write_data(&ftdic, buf, size);
197 if (retval < 0) {
198 *bytes_written = 0;
199 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
200 return ERROR_JTAG_DEVICE_ERROR;
201 }
202
203 *bytes_written += retval;
204
205 return ERROR_OK;
206 }
207
208 static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
209 {
210 int retval;
211 int timeout = 5;
212
213 *bytes_read = 0;
214
215 while ((*bytes_read < qty) && timeout--) {
216 retval = ftdi_read_data(&ftdic, buf + *bytes_read,
217 qty - *bytes_read);
218 if (retval < 0) {
219 *bytes_read = 0;
220 DEBUG_JTAG_IO("ftdi_read_data: %s",
221 ftdi_get_error_string(&ftdic));
222 return ERROR_JTAG_DEVICE_ERROR;
223 }
224 *bytes_read += retval;
225 }
226
227 #ifdef _DEBUG_USB_COMMS_
228 openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
229 #endif
230
231 return ERROR_OK;
232 }
233
234 static int openjtag_sendcommand(uint8_t cmd)
235 {
236 uint32_t written;
237 return openjtag_buf_write(&cmd, 1, &written);
238 }
239
240 static int openjtag_speed(int speed)
241 {
242 int clockcmd;
243 switch (speed) {
244 case 48000:
245 clockcmd = 0x00;
246 break;
247 case 24000:
248 clockcmd = 0x20;
249 break;
250 case 12000:
251 clockcmd = 0x40;
252 break;
253 case 6000:
254 clockcmd = 0x60;
255 break;
256 case 3000:
257 clockcmd = 0x80;
258 break;
259 case 1500:
260 clockcmd = 0xA0;
261 break;
262 case 750:
263 clockcmd = 0xC0;
264 break;
265 case 375:
266 clockcmd = 0xE0;
267 break;
268 default:
269 clockcmd = 0xE0;
270 LOG_WARNING("adapter speed not recognized, reverting to 375 kHz");
271 break;
272 }
273 openjtag_sendcommand(clockcmd);
274
275 return ERROR_OK;
276 }
277
278 static int openjtag_init(void)
279 {
280 uint8_t latency_timer;
281
282 usb_tx_buf_offs = 0;
283 usb_rx_buf_len = 0;
284 openjtag_scan_result_count = 0;
285
286 LOG_DEBUG("'openjtag' interface using libftdi");
287
288 /* Open by device description */
289 if (openjtag_device_desc == NULL) {
290 LOG_WARNING("no openjtag device description specified, "
291 "using default 'Open JTAG Project'");
292 openjtag_device_desc = "Open JTAG Project";
293 }
294
295 if (ftdi_init(&ftdic) < 0)
296 return ERROR_JTAG_INIT_FAILED;
297
298 /* context, vendor id, product id, description, serial id */
299 if (ftdi_usb_open_desc(&ftdic, openjtag_vid, openjtag_pid, openjtag_device_desc, NULL) < 0) {
300 LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
301 return ERROR_JTAG_INIT_FAILED;
302 }
303
304 if (ftdi_usb_reset(&ftdic) < 0) {
305 LOG_ERROR("unable to reset ftdi device");
306 return ERROR_JTAG_INIT_FAILED;
307 }
308
309 if (ftdi_set_latency_timer(&ftdic, 2) < 0) {
310 LOG_ERROR("unable to set latency timer");
311 return ERROR_JTAG_INIT_FAILED;
312 }
313
314 if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) {
315 LOG_ERROR("unable to get latency timer");
316 return ERROR_JTAG_INIT_FAILED;
317 }
318 LOG_DEBUG("current latency timer: %u", latency_timer);
319
320 ftdi_disable_bitbang(&ftdic);
321 /* was (3000000 / 4) with a comment about a bug in libftdi when using high baudrate */
322 if (ftdi_set_baudrate(&ftdic, 3000000) < 0) {
323 LOG_ERROR("Can't set baud rate to max: %s",
324 ftdi_get_error_string(&ftdic));
325 return ERROR_JTAG_DEVICE_ERROR;
326 }
327
328 if (ftdi_usb_purge_buffers(&ftdic) < 0) {
329 LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
330 return ERROR_JTAG_INIT_FAILED;
331 }
332
333 /* OpenJTAG speed */
334 openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/
335
336 /* MSB */
337 openjtag_sendcommand(0x75);
338
339 return ERROR_OK;
340 }
341
342 static int openjtag_quit(void)
343 {
344 ftdi_usb_close(&ftdic);
345 ftdi_deinit(&ftdic);
346
347 return ERROR_OK;
348 }
349
350 static void openjtag_write_tap_buffer(void)
351 {
352 uint32_t written;
353
354 openjtag_buf_write(usb_tx_buf, usb_tx_buf_offs, &written);
355 openjtag_buf_read(usb_rx_buf, usb_tx_buf_offs, &usb_rx_buf_len);
356
357 usb_tx_buf_offs = 0;
358 }
359
360 static int openjtag_execute_tap_queue(void)
361 {
362 openjtag_write_tap_buffer();
363
364 int res_count = 0;
365
366 if (openjtag_scan_result_count && usb_rx_buf_len) {
367
368 int count;
369 int rx_offs = 0;
370 int len;
371
372 /* for every pending result */
373 while (res_count < openjtag_scan_result_count) {
374
375 /* get sent bits */
376 len = openjtag_scan_result_buffer[res_count].bits;
377
378 count = 0;
379
380 uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer;
381
382 while (len) {
383 if (len <= 8) {
384 DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X",
385 usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len));
386 buffer[count] = usb_rx_buf[rx_offs] >> (8 - len);
387 len = 0;
388 } else {
389 buffer[count] = usb_rx_buf[rx_offs];
390 len -= 8;
391 }
392
393 rx_offs++;
394 count++;
395 }
396
397 #ifdef _DEBUG_USB_COMMS_
398 openjtag_debug_buffer(buffer,
399 DIV_ROUND_UP(openjtag_scan_result_buffer[res_count].bits, 8), DEBUG_TYPE_OCD_READ);
400 #endif
401 jtag_read_buffer(buffer, openjtag_scan_result_buffer[res_count].command);
402
403 if (openjtag_scan_result_buffer[res_count].buffer)
404 free(openjtag_scan_result_buffer[res_count].buffer);
405
406 res_count++;
407 }
408 }
409
410 openjtag_scan_result_count = 0;
411
412 return ERROR_OK;
413 }
414
415 static void openjtag_add_byte(char buf)
416 {
417
418 if (usb_tx_buf_offs == OPENJTAG_BUFFER_SIZE) {
419 DEBUG_JTAG_IO("Forcing execute_tap_queue");
420 DEBUG_JTAG_IO("TX Buff offs=%d", usb_tx_buf_offs);
421 openjtag_execute_tap_queue();
422 }
423
424 usb_tx_buf[usb_tx_buf_offs] = buf;
425 usb_tx_buf_offs++;
426 }
427
428 static void openjtag_add_scan(uint8_t *buffer, int length, struct scan_command *scan_cmd)
429 {
430
431 /* Ensure space to send long chains */
432 /* We add two byte for each eight (or less) bits, one for command, one for data */
433 if (usb_tx_buf_offs + (DIV_ROUND_UP(length, 8) * 2) >= OPENJTAG_BUFFER_SIZE) {
434 DEBUG_JTAG_IO("Forcing execute_tap_queue from scan");
435 DEBUG_JTAG_IO("TX Buff offs=%d len=%d", usb_tx_buf_offs, DIV_ROUND_UP(length, 8) * 2);
436 openjtag_execute_tap_queue();
437 }
438
439 openjtag_scan_result_buffer[openjtag_scan_result_count].bits = length;
440 openjtag_scan_result_buffer[openjtag_scan_result_count].command = scan_cmd;
441 openjtag_scan_result_buffer[openjtag_scan_result_count].buffer = buffer;
442
443 uint8_t command;
444 uint8_t bits;
445 int count = 0;
446 while (length) {
447
448 /* write command */
449 command = 6;
450
451 /* last bits? */
452 if (length <= 8) {
453 /* tms high */
454 command |= (1 << 4);
455
456 /* bits to transfer */
457 bits = (length - 1);
458 command |= bits << 5;
459 length = 0;
460 } else {
461 /* whole byte */
462
463 /* bits to transfer */
464 bits = 7;
465 command |= (7 << 5);
466 length -= 8;
467 }
468
469 openjtag_add_byte(command);
470 openjtag_add_byte(buffer[count]);
471 count++;
472 }
473
474 openjtag_scan_result_count++;
475 }
476
477 static void openjtag_execute_reset(struct jtag_command *cmd)
478 {
479
480 DEBUG_JTAG_IO("reset trst: %i srst %i",
481 cmd->cmd.reset->trst, cmd->cmd.reset->srst);
482
483 uint8_t buf = 0x00;
484
485 if (cmd->cmd.reset->trst) {
486 buf = 0x03;
487 } else {
488 buf |= 0x04;
489 buf |= 0x05 << 4;
490 }
491
492 openjtag_add_byte(buf);
493 }
494
495 static void openjtag_execute_sleep(struct jtag_command *cmd)
496 {
497 jtag_sleep(cmd->cmd.sleep->us);
498 }
499
500 static void openjtag_set_state(uint8_t openocd_state)
501 {
502 int8_t state = openjtag_get_tap_state(openocd_state);
503
504 uint8_t buf = 0;
505 buf = 0x01;
506 buf |= state << 4;
507
508 openjtag_add_byte(buf);
509 }
510
511 static void openjtag_execute_statemove(struct jtag_command *cmd)
512 {
513 DEBUG_JTAG_IO("state move to %i", cmd->cmd.statemove->end_state);
514
515 tap_set_end_state(cmd->cmd.statemove->end_state);
516
517 openjtag_set_state(cmd->cmd.statemove->end_state);
518
519 tap_set_state(tap_get_end_state());
520 }
521
522
523 static void openjtag_execute_scan(struct jtag_command *cmd)
524 {
525
526 int scan_size, old_state;
527 uint8_t *buffer;
528
529 DEBUG_JTAG_IO("scan ends in %s", tap_state_name(cmd->cmd.scan->end_state));
530
531 /* get scan info */
532 tap_set_end_state(cmd->cmd.scan->end_state);
533 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
534
535 #ifdef _DEBUG_USB_COMMS_
536 openjtag_debug_buffer(buffer, (scan_size + 7) / 8, DEBUG_TYPE_BUFFER);
537 #endif
538 /* set state */
539 old_state = tap_get_end_state();
540 openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
541 tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
542 tap_set_end_state(old_state);
543
544 openjtag_add_scan(buffer, scan_size, cmd->cmd.scan);
545
546 openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
547 tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
548
549 if (tap_get_state() != tap_get_end_state()) {
550 openjtag_set_state(tap_get_end_state());
551 tap_set_state(tap_get_end_state());
552 }
553 }
554
555 static void openjtag_execute_runtest(struct jtag_command *cmd)
556 {
557
558 tap_state_t end_state = cmd->cmd.runtest->end_state;
559 tap_set_end_state(end_state);
560
561 /* only do a state_move when we're not already in IDLE */
562 if (tap_get_state() != TAP_IDLE) {
563 openjtag_set_state(TAP_IDLE);
564 tap_set_state(TAP_IDLE);
565 }
566
567 if (cmd->cmd.runtest->num_cycles > 16)
568 LOG_WARNING("num_cycles > 16 on run test");
569
570 uint8_t command;
571 command = 7;
572 command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
573
574 openjtag_add_byte(command);
575
576 tap_set_end_state(end_state);
577 if (tap_get_end_state() != tap_get_state()) {
578 openjtag_set_state(end_state);
579 tap_set_state(end_state);
580 }
581 }
582
583 static void openjtag_execute_command(struct jtag_command *cmd)
584 {
585 DEBUG_JTAG_IO("openjtag_execute_command %i", cmd->type);
586 switch (cmd->type) {
587 case JTAG_RESET:
588 openjtag_execute_reset(cmd);
589 break;
590 case JTAG_SLEEP:
591 openjtag_execute_sleep(cmd);
592 break;
593 case JTAG_TLR_RESET:
594 openjtag_execute_statemove(cmd);
595 break;
596 case JTAG_SCAN:
597 openjtag_execute_scan(cmd);
598 break;
599 case JTAG_RUNTEST:
600 openjtag_execute_runtest(cmd);
601 break;
602 case JTAG_PATHMOVE:
603 /* jlink_execute_pathmove(cmd); break; */
604 default:
605 LOG_ERROR("BUG: unknown Open JTAG command type encountered");
606 exit(-1);
607 }
608 }
609
610 static int openjtag_execute_queue(void)
611 {
612 struct jtag_command *cmd = jtag_command_queue;
613
614 while (cmd != NULL) {
615 openjtag_execute_command(cmd);
616 cmd = cmd->next;
617 }
618
619 return openjtag_execute_tap_queue();
620 }
621
622 static int openjtag_speed_div(int speed, int *khz)
623 {
624 *khz = speed;
625
626 return ERROR_OK;
627 }
628
629 static int openjtag_khz(int khz, int *jtag_speed)
630 {
631
632 if (khz >= 48000)
633 *jtag_speed = 48000;
634 else if (khz >= 24000)
635 *jtag_speed = 24000;
636 else if (khz >= 12000)
637 *jtag_speed = 12000;
638 else if (khz >= 6000)
639 *jtag_speed = 6000;
640 else if (khz >= 3000)
641 *jtag_speed = 3000;
642 else if (khz >= 1500)
643 *jtag_speed = 1500;
644 else if (khz >= 750)
645 *jtag_speed = 750;
646 else
647 *jtag_speed = 375;
648
649 return ERROR_OK;
650 }
651
652 COMMAND_HANDLER(openjtag_handle_device_desc_command)
653 {
654 if (CMD_ARGC == 1)
655 openjtag_device_desc = strdup(CMD_ARGV[0]);
656 else
657 LOG_ERROR("require exactly one argument to "
658 "openjtag_device_desc <description>");
659 return ERROR_OK;
660 }
661
662
663 static const struct command_registration openjtag_command_handlers[] = {
664 {
665 .name = "openjtag_device_desc",
666 .handler = openjtag_handle_device_desc_command,
667 .mode = COMMAND_CONFIG,
668 .help = "set the USB device description of the OpenJTAG",
669 .usage = "description-string",
670 },
671 COMMAND_REGISTRATION_DONE
672 };
673
674 struct jtag_interface openjtag_interface = {
675 .name = "openjtag",
676 .commands = openjtag_command_handlers,
677
678 .execute_queue = openjtag_execute_queue,
679 .speed = openjtag_speed,
680 .speed_div = openjtag_speed_div,
681 .khz = openjtag_khz,
682 .init = openjtag_init,
683 .quit = openjtag_quit,
684 };
685
686

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)