Add FTDI SWD driver
[openocd.git] / src / target / embeddedice.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007-2010 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
25 ***************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "embeddedice.h"
32 #include "register.h"
33
34 /**
35 * @file
36 *
37 * This provides lowlevel glue to the EmbeddedICE (or EmbeddedICE-RT)
38 * module found on scan chain 2 in ARM7, ARM9, and some other families
39 * of ARM cores. The module is called "EmbeddedICE-RT" if it has
40 * monitor mode support.
41 *
42 * EmbeddedICE provides basic watchpoint/breakpoint hardware and a Debug
43 * Communications Channel (DCC) used to read or write 32-bit words to
44 * OpenOCD-aware code running on the target CPU.
45 * Newer modules also include vector catch hardware. Some versions
46 * support hardware single-stepping, "monitor mode" debug (which is not
47 * currently supported by OpenOCD), or extended reporting on why the
48 * core entered debug mode.
49 */
50
51 static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf);
52
53 /*
54 * From: ARM9E-S TRM, DDI 0165, table C-4 (and similar, for other cores)
55 */
56 static const struct {
57 char *name;
58 unsigned short addr;
59 unsigned short width;
60 } eice_regs[] = {
61 [EICE_DBG_CTRL] = {
62 .name = "debug_ctrl",
63 .addr = 0,
64 /* width is assigned based on EICE version */
65 },
66 [EICE_DBG_STAT] = {
67 .name = "debug_status",
68 .addr = 1,
69 /* width is assigned based on EICE version */
70 },
71 [EICE_COMMS_CTRL] = {
72 .name = "comms_ctrl",
73 .addr = 4,
74 .width = 6,
75 },
76 [EICE_COMMS_DATA] = {
77 .name = "comms_data",
78 .addr = 5,
79 .width = 32,
80 },
81 [EICE_W0_ADDR_VALUE] = {
82 .name = "watch_0_addr_value",
83 .addr = 8,
84 .width = 32,
85 },
86 [EICE_W0_ADDR_MASK] = {
87 .name = "watch_0_addr_mask",
88 .addr = 9,
89 .width = 32,
90 },
91 [EICE_W0_DATA_VALUE] = {
92 .name = "watch_0_data_value",
93 .addr = 10,
94 .width = 32,
95 },
96 [EICE_W0_DATA_MASK] = {
97 .name = "watch_0_data_mask",
98 .addr = 11,
99 .width = 32,
100 },
101 [EICE_W0_CONTROL_VALUE] = {
102 .name = "watch_0_control_value",
103 .addr = 12,
104 .width = 9,
105 },
106 [EICE_W0_CONTROL_MASK] = {
107 .name = "watch_0_control_mask",
108 .addr = 13,
109 .width = 8,
110 },
111 [EICE_W1_ADDR_VALUE] = {
112 .name = "watch_1_addr_value",
113 .addr = 16,
114 .width = 32,
115 },
116 [EICE_W1_ADDR_MASK] = {
117 .name = "watch_1_addr_mask",
118 .addr = 17,
119 .width = 32,
120 },
121 [EICE_W1_DATA_VALUE] = {
122 .name = "watch_1_data_value",
123 .addr = 18,
124 .width = 32,
125 },
126 [EICE_W1_DATA_MASK] = {
127 .name = "watch_1_data_mask",
128 .addr = 19,
129 .width = 32,
130 },
131 [EICE_W1_CONTROL_VALUE] = {
132 .name = "watch_1_control_value",
133 .addr = 20,
134 .width = 9,
135 },
136 [EICE_W1_CONTROL_MASK] = {
137 .name = "watch_1_control_mask",
138 .addr = 21,
139 .width = 8,
140 },
141 /* vector_catch isn't always present */
142 [EICE_VEC_CATCH] = {
143 .name = "vector_catch",
144 .addr = 2,
145 .width = 8,
146 },
147 };
148
149 static int embeddedice_get_reg(struct reg *reg)
150 {
151 int retval = embeddedice_read_reg(reg);
152 if (retval != ERROR_OK) {
153 LOG_ERROR("error queueing EmbeddedICE register read");
154 return retval;
155 }
156
157 retval = jtag_execute_queue();
158 if (retval != ERROR_OK)
159 LOG_ERROR("EmbeddedICE register read failed");
160
161 return retval;
162 }
163
164 static const struct reg_arch_type eice_reg_type = {
165 .get = embeddedice_get_reg,
166 .set = embeddedice_set_reg_w_exec,
167 };
168
169 /**
170 * Probe EmbeddedICE module and set up local records of its registers.
171 * Different versions of the modules have different capabilities, such as
172 * hardware support for vector_catch, single stepping, and monitor mode.
173 */
174 struct reg_cache *embeddedice_build_reg_cache(struct target *target,
175 struct arm7_9_common *arm7_9)
176 {
177 int retval;
178 struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
179 struct reg *reg_list = NULL;
180 struct embeddedice_reg *arch_info = NULL;
181 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
182 int num_regs = ARRAY_SIZE(eice_regs);
183 int i;
184 int eice_version = 0;
185
186 /* vector_catch isn't always present */
187 if (!arm7_9->has_vector_catch)
188 num_regs--;
189
190 /* the actual registers are kept in two arrays */
191 reg_list = calloc(num_regs, sizeof(struct reg));
192 arch_info = calloc(num_regs, sizeof(struct embeddedice_reg));
193
194 /* fill in values for the reg cache */
195 reg_cache->name = "EmbeddedICE registers";
196 reg_cache->next = NULL;
197 reg_cache->reg_list = reg_list;
198 reg_cache->num_regs = num_regs;
199
200 /* FIXME the second watchpoint unit on Feroceon and Dragonite
201 * seems not to work ... we should have a way to not set up
202 * its four registers here!
203 */
204
205 /* set up registers */
206 for (i = 0; i < num_regs; i++) {
207 reg_list[i].name = eice_regs[i].name;
208 reg_list[i].size = eice_regs[i].width;
209 reg_list[i].dirty = 0;
210 reg_list[i].valid = 0;
211 reg_list[i].value = calloc(1, 4);
212 reg_list[i].arch_info = &arch_info[i];
213 reg_list[i].type = &eice_reg_type;
214 arch_info[i].addr = eice_regs[i].addr;
215 arch_info[i].jtag_info = jtag_info;
216 }
217
218 /* identify EmbeddedICE version by reading DCC control register */
219 embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);
220 retval = jtag_execute_queue();
221 if (retval != ERROR_OK) {
222 for (i = 0; i < num_regs; i++)
223 free(reg_list[i].value);
224 free(reg_list);
225 free(reg_cache);
226 free(arch_info);
227 return NULL;
228 }
229
230 eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
231 LOG_INFO("Embedded ICE version %d", eice_version);
232
233 switch (eice_version) {
234 case 1:
235 /* ARM7TDMI r3, ARM7TDMI-S r3
236 *
237 * REVISIT docs say ARM7TDMI-S r4 uses version 1 but
238 * that it has 6-bit CTRL and 5-bit STAT... doc bug?
239 * ARM7TDMI r4 docs say EICE v4.
240 */
241 reg_list[EICE_DBG_CTRL].size = 3;
242 reg_list[EICE_DBG_STAT].size = 5;
243 break;
244 case 2:
245 /* ARM9TDMI */
246 reg_list[EICE_DBG_CTRL].size = 4;
247 reg_list[EICE_DBG_STAT].size = 5;
248 arm7_9->has_single_step = 1;
249 break;
250 case 3:
251 LOG_ERROR("EmbeddedICE v%d handling might be broken",
252 eice_version);
253 reg_list[EICE_DBG_CTRL].size = 6;
254 reg_list[EICE_DBG_STAT].size = 5;
255 arm7_9->has_single_step = 1;
256 arm7_9->has_monitor_mode = 1;
257 break;
258 case 4:
259 /* ARM7TDMI r4 */
260 reg_list[EICE_DBG_CTRL].size = 6;
261 reg_list[EICE_DBG_STAT].size = 5;
262 arm7_9->has_monitor_mode = 1;
263 break;
264 case 5:
265 /* ARM9E-S rev 1 */
266 reg_list[EICE_DBG_CTRL].size = 6;
267 reg_list[EICE_DBG_STAT].size = 5;
268 arm7_9->has_single_step = 1;
269 arm7_9->has_monitor_mode = 1;
270 break;
271 case 6:
272 /* ARM7EJ-S, ARM9E-S rev 2, ARM9EJ-S */
273 reg_list[EICE_DBG_CTRL].size = 6;
274 reg_list[EICE_DBG_STAT].size = 10;
275 /* DBG_STAT has MOE bits */
276 arm7_9->has_monitor_mode = 1;
277 break;
278 case 7:
279 LOG_ERROR("EmbeddedICE v%d handling might be broken",
280 eice_version);
281 reg_list[EICE_DBG_CTRL].size = 6;
282 reg_list[EICE_DBG_STAT].size = 5;
283 arm7_9->has_monitor_mode = 1;
284 break;
285 default:
286 /*
287 * The Feroceon implementation has the version number
288 * in some unusual bits. Let feroceon.c validate it
289 * and do the appropriate setup itself.
290 */
291 if (strcmp(target_type_name(target), "feroceon") == 0 ||
292 strcmp(target_type_name(target), "dragonite") == 0)
293 break;
294 LOG_ERROR("unknown EmbeddedICE version "
295 "(comms ctrl: 0x%8.8" PRIx32 ")",
296 buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
297 }
298
299 /* On Feroceon and Dragonite the second unit is seemingly missing. */
300 LOG_INFO("%s: hardware has %d breakpoint/watchpoint unit%s",
301 target_name(target), arm7_9->wp_available_max,
302 (arm7_9->wp_available_max != 1) ? "s" : "");
303
304 return reg_cache;
305 }
306
307 /**
308 * Initialize EmbeddedICE module, if needed.
309 */
310 int embeddedice_setup(struct target *target)
311 {
312 int retval;
313 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
314
315 /* Explicitly disable monitor mode. For now we only support halting
316 * debug ... we don't know how to talk with a resident debug monitor
317 * that manages break requests. ARM's "Angel Debug Monitor" is one
318 * common example of such code.
319 */
320 if (arm7_9->has_monitor_mode) {
321 struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
322
323 embeddedice_read_reg(dbg_ctrl);
324 retval = jtag_execute_queue();
325 if (retval != ERROR_OK)
326 return retval;
327 buf_set_u32(dbg_ctrl->value, 4, 1, 0);
328 embeddedice_set_reg_w_exec(dbg_ctrl, dbg_ctrl->value);
329 }
330 return jtag_execute_queue();
331 }
332
333 /**
334 * Queue a read for an EmbeddedICE register into the register cache,
335 * optionally checking the value read.
336 * Note that at this level, all registers are 32 bits wide.
337 */
338 int embeddedice_read_reg_w_check(struct reg *reg,
339 uint8_t *check_value, uint8_t *check_mask)
340 {
341 struct embeddedice_reg *ice_reg = reg->arch_info;
342 uint8_t reg_addr = ice_reg->addr & 0x1f;
343 struct scan_field fields[3];
344 uint8_t field1_out[1];
345 uint8_t field2_out[1];
346 int retval;
347
348 retval = arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE);
349 if (retval != ERROR_OK)
350 return retval;
351
352 retval = arm_jtag_set_instr(ice_reg->jtag_info,
353 ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE);
354 if (retval != ERROR_OK)
355 return retval;
356
357 /* bits 31:0 -- data (ignored here) */
358 fields[0].num_bits = 32;
359 fields[0].out_value = reg->value;
360 fields[0].in_value = NULL;
361 fields[0].check_value = NULL;
362 fields[0].check_mask = NULL;
363
364 /* bits 36:32 -- register */
365 fields[1].num_bits = 5;
366 fields[1].out_value = field1_out;
367 field1_out[0] = reg_addr;
368 fields[1].in_value = NULL;
369 fields[1].check_value = NULL;
370 fields[1].check_mask = NULL;
371
372 /* bit 37 -- 0/read */
373 fields[2].num_bits = 1;
374 fields[2].out_value = field2_out;
375 field2_out[0] = 0;
376 fields[2].in_value = NULL;
377 fields[2].check_value = NULL;
378 fields[2].check_mask = NULL;
379
380 /* traverse Update-DR, setting address for the next read */
381 jtag_add_dr_scan(ice_reg->jtag_info->tap, 3, fields, TAP_IDLE);
382
383 /* bits 31:0 -- the data we're reading (and maybe checking) */
384 fields[0].in_value = reg->value;
385 fields[0].check_value = check_value;
386 fields[0].check_mask = check_mask;
387
388 /* when reading the DCC data register, leaving the address field set to
389 * EICE_COMMS_DATA would read the register twice
390 * reading the control register is safe
391 */
392 field1_out[0] = eice_regs[EICE_COMMS_CTRL].addr;
393
394 /* traverse Update-DR, reading but with no other side effects */
395 jtag_add_dr_scan_check(ice_reg->jtag_info->tap, 3, fields, TAP_IDLE);
396
397 return ERROR_OK;
398 }
399
400 /**
401 * Receive a block of size 32-bit words from the DCC.
402 * We assume the target is always going to be fast enough (relative to
403 * the JTAG clock) that the debugger won't need to poll the handshake
404 * bit. The JTAG clock is usually at least six times slower than the
405 * functional clock, so the 50+ JTAG clocks needed to receive the word
406 * allow hundreds of instruction cycles (per word) in the target.
407 */
408 int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
409 {
410 struct scan_field fields[3];
411 uint8_t field1_out[1];
412 uint8_t field2_out[1];
413 int retval;
414
415 retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
416 if (retval != ERROR_OK)
417 return retval;
418 retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
419 if (retval != ERROR_OK)
420 return retval;
421
422 fields[0].num_bits = 32;
423 fields[0].out_value = NULL;
424 fields[0].in_value = NULL;
425
426 fields[1].num_bits = 5;
427 fields[1].out_value = field1_out;
428 field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
429 fields[1].in_value = NULL;
430
431 fields[2].num_bits = 1;
432 fields[2].out_value = field2_out;
433 field2_out[0] = 0;
434 fields[2].in_value = NULL;
435
436 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
437
438 while (size > 0) {
439 /* when reading the last item, set the register address to the DCC control reg,
440 * to avoid reading additional data from the DCC data reg
441 */
442 if (size == 1)
443 field1_out[0] = eice_regs[EICE_COMMS_CTRL].addr;
444
445 fields[0].in_value = (uint8_t *)data;
446 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
447 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)data);
448
449 data++;
450 size--;
451 }
452
453 return jtag_execute_queue();
454 }
455
456 /**
457 * Queue a read for an EmbeddedICE register into the register cache,
458 * not checking the value read.
459 */
460 int embeddedice_read_reg(struct reg *reg)
461 {
462 return embeddedice_read_reg_w_check(reg, NULL, NULL);
463 }
464
465 /**
466 * Queue a write for an EmbeddedICE register, updating the register cache.
467 * Uses embeddedice_write_reg().
468 */
469 void embeddedice_set_reg(struct reg *reg, uint32_t value)
470 {
471 embeddedice_write_reg(reg, value);
472
473 buf_set_u32(reg->value, 0, reg->size, value);
474 reg->valid = 1;
475 reg->dirty = 0;
476
477 }
478
479 /**
480 * Write an EmbeddedICE register, updating the register cache.
481 * Uses embeddedice_set_reg(); not queued.
482 */
483 static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf)
484 {
485 int retval;
486
487 embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
488 retval = jtag_execute_queue();
489 if (retval != ERROR_OK)
490 LOG_ERROR("register write failed");
491 return retval;
492 }
493
494 /**
495 * Queue a write for an EmbeddedICE register, bypassing the register cache.
496 */
497 void embeddedice_write_reg(struct reg *reg, uint32_t value)
498 {
499 struct embeddedice_reg *ice_reg = reg->arch_info;
500
501 LOG_DEBUG("%i: 0x%8.8" PRIx32 "", ice_reg->addr, value);
502
503 arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE);
504
505 arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE);
506
507 uint8_t reg_addr = ice_reg->addr & 0x1f;
508 embeddedice_write_reg_inner(ice_reg->jtag_info->tap, reg_addr, value);
509 }
510
511 /**
512 * Queue a write for an EmbeddedICE register, using cached value.
513 * Uses embeddedice_write_reg().
514 */
515 void embeddedice_store_reg(struct reg *reg)
516 {
517 embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
518 }
519
520 /**
521 * Send a block of size 32-bit words to the DCC.
522 * We assume the target is always going to be fast enough (relative to
523 * the JTAG clock) that the debugger won't need to poll the handshake
524 * bit. The JTAG clock is usually at least six times slower than the
525 * functional clock, so the 50+ JTAG clocks needed to receive the word
526 * allow hundreds of instruction cycles (per word) in the target.
527 */
528 int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
529 {
530 struct scan_field fields[3];
531 uint8_t field0_out[4];
532 uint8_t field1_out[1];
533 uint8_t field2_out[1];
534 int retval;
535
536 retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
537 if (retval != ERROR_OK)
538 return retval;
539 retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
540 if (retval != ERROR_OK)
541 return retval;
542
543 fields[0].num_bits = 32;
544 fields[0].out_value = field0_out;
545 fields[0].in_value = NULL;
546
547 fields[1].num_bits = 5;
548 fields[1].out_value = field1_out;
549 field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
550 fields[1].in_value = NULL;
551
552 fields[2].num_bits = 1;
553 fields[2].out_value = field2_out;
554 field2_out[0] = 1;
555
556 fields[2].in_value = NULL;
557
558 while (size > 0) {
559 buf_set_u32(field0_out, 0, 32, *data);
560 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
561
562 data++;
563 size--;
564 }
565
566 /* call to jtag_execute_queue() intentionally omitted */
567 return ERROR_OK;
568 }
569
570 /**
571 * Poll DCC control register until read or write handshake completes.
572 */
573 int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout)
574 {
575 struct scan_field fields[3];
576 uint8_t field0_in[4];
577 uint8_t field1_out[1];
578 uint8_t field2_out[1];
579 int retval;
580 uint32_t hsact;
581 struct timeval lap;
582 struct timeval now;
583
584 if (hsbit == EICE_COMM_CTRL_WBIT)
585 hsact = 1;
586 else if (hsbit == EICE_COMM_CTRL_RBIT)
587 hsact = 0;
588 else {
589 LOG_ERROR("Invalid arguments");
590 return ERROR_COMMAND_SYNTAX_ERROR;
591 }
592
593 retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
594 if (retval != ERROR_OK)
595 return retval;
596 retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
597 if (retval != ERROR_OK)
598 return retval;
599
600 fields[0].num_bits = 32;
601 fields[0].out_value = NULL;
602 fields[0].in_value = field0_in;
603
604 fields[1].num_bits = 5;
605 fields[1].out_value = field1_out;
606 field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
607 fields[1].in_value = NULL;
608
609 fields[2].num_bits = 1;
610 fields[2].out_value = field2_out;
611 field2_out[0] = 0;
612 fields[2].in_value = NULL;
613
614 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
615 gettimeofday(&lap, NULL);
616 do {
617 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
618 retval = jtag_execute_queue();
619 if (retval != ERROR_OK)
620 return retval;
621
622 if (buf_get_u32(field0_in, hsbit, 1) == hsact)
623 return ERROR_OK;
624
625 gettimeofday(&now, NULL);
626 } while ((uint32_t)((now.tv_sec - lap.tv_sec) * 1000
627 + (now.tv_usec - lap.tv_usec) / 1000) <= timeout);
628
629 LOG_ERROR("embeddedice handshake timeout");
630 return ERROR_TARGET_TIMEOUT;
631 }
632
633 #ifndef HAVE_JTAG_MINIDRIVER_H
634 /**
635 * This is an inner loop of the open loop DCC write of data to target
636 */
637 void embeddedice_write_dcc(struct jtag_tap *tap,
638 int reg_addr, const uint8_t *buffer, int little, int count)
639 {
640 int i;
641
642 for (i = 0; i < count; i++) {
643 embeddedice_write_reg_inner(tap, reg_addr,
644 fast_target_buffer_get_u32(buffer, little));
645 buffer += 4;
646 }
647 }
648 #else
649 /* provided by minidriver */
650 #endif

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)