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