bf220364e653a33630a426e243b8faefeb8747f6
[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 #include "register.h"
32
33 /**
34 * @file
35 *
36 * This provides lowlevel glue to the EmbeddedICE (or EmbeddedICE-RT)
37 * module found on scan chain 2 in ARM7, ARM9, and some other families
38 * of ARM cores. The module is called "EmbeddedICE-RT" if it has
39 * monitor mode support.
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_get_reg(struct reg *reg)
148 {
149 int retval;
150
151 if ((retval = embeddedice_read_reg(reg)) != ERROR_OK)
152 LOG_ERROR("error queueing EmbeddedICE register read");
153 else if ((retval = jtag_execute_queue()) != ERROR_OK)
154 LOG_ERROR("EmbeddedICE register read failed");
155
156 return retval;
157 }
158
159 static const struct reg_arch_type eice_reg_type = {
160 .get = embeddedice_get_reg,
161 .set = embeddedice_set_reg_w_exec,
162 };
163
164 /**
165 * Probe EmbeddedICE module and set up local records of its registers.
166 * Different versions of the modules have different capabilities, such as
167 * hardware support for vector_catch, single stepping, and monitor mode.
168 */
169 struct reg_cache *
170 embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9)
171 {
172 int retval;
173 struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
174 struct reg *reg_list = NULL;
175 struct embeddedice_reg *arch_info = NULL;
176 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
177 int num_regs = ARRAY_SIZE(eice_regs);
178 int i;
179 int eice_version = 0;
180
181 /* vector_catch isn't always present */
182 if (!arm7_9->has_vector_catch)
183 num_regs--;
184
185 /* the actual registers are kept in two arrays */
186 reg_list = calloc(num_regs, sizeof(struct reg));
187 arch_info = calloc(num_regs, sizeof(struct embeddedice_reg));
188
189 /* fill in values for the reg cache */
190 reg_cache->name = "EmbeddedICE registers";
191 reg_cache->next = NULL;
192 reg_cache->reg_list = reg_list;
193 reg_cache->num_regs = num_regs;
194
195 /* FIXME the second watchpoint unit on Feroceon and Dragonite
196 * seems not to work ... we should have a way to not set up
197 * its four registers here!
198 */
199
200 /* set up registers */
201 for (i = 0; i < num_regs; i++)
202 {
203 reg_list[i].name = eice_regs[i].name;
204 reg_list[i].size = eice_regs[i].width;
205 reg_list[i].dirty = 0;
206 reg_list[i].valid = 0;
207 reg_list[i].value = calloc(1, 4);
208 reg_list[i].arch_info = &arch_info[i];
209 reg_list[i].type = &eice_reg_type;
210 arch_info[i].addr = eice_regs[i].addr;
211 arch_info[i].jtag_info = jtag_info;
212 }
213
214 /* identify EmbeddedICE version by reading DCC control register */
215 embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);
216 if ((retval = jtag_execute_queue()) != ERROR_OK)
217 {
218 for (i = 0; i < num_regs; i++)
219 {
220 free(reg_list[i].value);
221 }
222 free(reg_list);
223 free(reg_cache);
224 free(arch_info);
225 return NULL;
226 }
227
228 eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
229 LOG_INFO("Embedded ICE version %d", eice_version);
230
231 switch (eice_version)
232 {
233 case 1:
234 /* ARM7TDMI r3, ARM7TDMI-S r3
235 *
236 * REVISIT docs say ARM7TDMI-S r4 uses version 1 but
237 * that it has 6-bit CTRL and 5-bit STAT... doc bug?
238 * ARM7TDMI r4 docs say EICE v4.
239 */
240 reg_list[EICE_DBG_CTRL].size = 3;
241 reg_list[EICE_DBG_STAT].size = 5;
242 break;
243 case 2:
244 /* ARM9TDMI */
245 reg_list[EICE_DBG_CTRL].size = 4;
246 reg_list[EICE_DBG_STAT].size = 5;
247 arm7_9->has_single_step = 1;
248 break;
249 case 3:
250 LOG_ERROR("EmbeddedICE v%d handling might be broken",
251 eice_version);
252 reg_list[EICE_DBG_CTRL].size = 6;
253 reg_list[EICE_DBG_STAT].size = 5;
254 arm7_9->has_single_step = 1;
255 arm7_9->has_monitor_mode = 1;
256 break;
257 case 4:
258 /* ARM7TDMI r4 */
259 reg_list[EICE_DBG_CTRL].size = 6;
260 reg_list[EICE_DBG_STAT].size = 5;
261 arm7_9->has_monitor_mode = 1;
262 break;
263 case 5:
264 /* ARM9E-S rev 1 */
265 reg_list[EICE_DBG_CTRL].size = 6;
266 reg_list[EICE_DBG_STAT].size = 5;
267 arm7_9->has_single_step = 1;
268 arm7_9->has_monitor_mode = 1;
269 break;
270 case 6:
271 /* ARM7EJ-S, ARM9E-S rev 2, ARM9EJ-S */
272 reg_list[EICE_DBG_CTRL].size = 6;
273 reg_list[EICE_DBG_STAT].size = 10;
274 /* DBG_STAT has MOE bits */
275 arm7_9->has_monitor_mode = 1;
276 break;
277 case 7:
278 LOG_ERROR("EmbeddedICE v%d handling might be broken",
279 eice_version);
280 reg_list[EICE_DBG_CTRL].size = 6;
281 reg_list[EICE_DBG_STAT].size = 5;
282 arm7_9->has_monitor_mode = 1;
283 break;
284 default:
285 /*
286 * The Feroceon implementation has the version number
287 * in some unusual bits. Let feroceon.c validate it
288 * and do the appropriate setup itself.
289 */
290 if (strcmp(target_type_name(target), "feroceon") == 0 ||
291 strcmp(target_type_name(target), "dragonite") == 0)
292 break;
293 LOG_ERROR("unknown EmbeddedICE version "
294 "(comms ctrl: 0x%8.8" PRIx32 ")",
295 buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
296 }
297
298 /* On Feroceon and Dragonite the second unit is seemingly missing. */
299 LOG_INFO("%s: hardware has %d breakpoint/watchpoint unit%s",
300 target_name(target), arm7_9->wp_available_max,
301 (arm7_9->wp_available_max != 1) ? "s" : "");
302
303 return reg_cache;
304 }
305
306 /**
307 * Initialize EmbeddedICE module, if needed.
308 */
309 int embeddedice_setup(struct target *target)
310 {
311 int retval;
312 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
313
314 /* Explicitly disable monitor mode. For now we only support halting
315 * debug ... we don't know how to talk with a resident debug monitor
316 * that manages break requests. ARM's "Angel Debug Monitor" is one
317 * common example of such code.
318 */
319 if (arm7_9->has_monitor_mode)
320 {
321 struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
322
323 embeddedice_read_reg(dbg_ctrl);
324 if ((retval = jtag_execute_queue()) != ERROR_OK)
325 return retval;
326 buf_set_u32(dbg_ctrl->value, 4, 1, 0);
327 embeddedice_set_reg_w_exec(dbg_ctrl, dbg_ctrl->value);
328 }
329 return jtag_execute_queue();
330 }
331
332 /**
333 * Queue a read for an EmbeddedICE register into the register cache,
334 * optionally checking the value read.
335 * Note that at this level, all registers are 32 bits wide.
336 */
337 int embeddedice_read_reg_w_check(struct reg *reg,
338 uint8_t *check_value, uint8_t *check_mask)
339 {
340 struct embeddedice_reg *ice_reg = reg->arch_info;
341 uint8_t reg_addr = ice_reg->addr & 0x1f;
342 struct scan_field fields[3];
343 uint8_t field1_out[1];
344 uint8_t field2_out[1];
345
346 jtag_set_end_state(TAP_IDLE);
347 arm_jtag_scann(ice_reg->jtag_info, 0x2);
348
349 arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
350
351 /* bits 31:0 -- data (ignored here) */
352 fields[0].tap = ice_reg->jtag_info->tap;
353 fields[0].num_bits = 32;
354 fields[0].out_value = reg->value;
355 fields[0].in_value = NULL;
356 fields[0].check_value = NULL;
357 fields[0].check_mask = NULL;
358
359 /* bits 36:32 -- register */
360 fields[1].tap = ice_reg->jtag_info->tap;
361 fields[1].num_bits = 5;
362 fields[1].out_value = field1_out;
363 fields[1].out_value[0] = reg_addr;
364 fields[1].in_value = NULL;
365 fields[1].check_value = NULL;
366 fields[1].check_mask = NULL;
367
368 /* bit 37 -- 0/read */
369 fields[2].tap = ice_reg->jtag_info->tap;
370 fields[2].num_bits = 1;
371 fields[2].out_value = field2_out;
372 fields[2].out_value[0] = 0;
373 fields[2].in_value = NULL;
374 fields[2].check_value = NULL;
375 fields[2].check_mask = NULL;
376
377 /* traverse Update-DR, setting address for the next read */
378 jtag_add_dr_scan(3, fields, jtag_get_end_state());
379
380 /* bits 31:0 -- the data we're reading (and maybe checking) */
381 fields[0].in_value = reg->value;
382 fields[0].check_value = check_value;
383 fields[0].check_mask = check_mask;
384
385 /* when reading the DCC data register, leaving the address field set to
386 * EICE_COMMS_DATA would read the register twice
387 * reading the control register is safe
388 */
389 fields[1].out_value[0] = eice_regs[EICE_COMMS_CTRL].addr;
390
391 /* traverse Update-DR, reading but with no other side effects */
392 jtag_add_dr_scan_check(3, fields, jtag_get_end_state());
393
394 return ERROR_OK;
395 }
396
397 /**
398 * Receive a block of size 32-bit words from the DCC.
399 * We assume the target is always going to be fast enough (relative to
400 * the JTAG clock) that the debugger won't need to poll the handshake
401 * bit. The JTAG clock is usually at least six times slower than the
402 * functional clock, so the 50+ JTAG clocks needed to receive the word
403 * allow hundreds of instruction cycles (per word) in the target.
404 */
405 int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
406 {
407 struct scan_field fields[3];
408 uint8_t field1_out[1];
409 uint8_t field2_out[1];
410
411 jtag_set_end_state(TAP_IDLE);
412 arm_jtag_scann(jtag_info, 0x2);
413 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
414
415 fields[0].tap = jtag_info->tap;
416 fields[0].num_bits = 32;
417 fields[0].out_value = NULL;
418 fields[0].in_value = NULL;
419
420 fields[1].tap = jtag_info->tap;
421 fields[1].num_bits = 5;
422 fields[1].out_value = field1_out;
423 fields[1].out_value[0] = eice_regs[EICE_COMMS_DATA].addr;
424 fields[1].in_value = NULL;
425
426 fields[2].tap = jtag_info->tap;
427 fields[2].num_bits = 1;
428 fields[2].out_value = field2_out;
429 fields[2].out_value[0] = 0;
430 fields[2].in_value = NULL;
431
432 jtag_add_dr_scan(3, fields, jtag_get_end_state());
433
434 while (size > 0)
435 {
436 /* when reading the last item, set the register address to the DCC control reg,
437 * to avoid reading additional data from the DCC data reg
438 */
439 if (size == 1)
440 fields[1].out_value[0] = eice_regs[EICE_COMMS_CTRL].addr;
441
442 fields[0].in_value = (uint8_t *)data;
443 jtag_add_dr_scan(3, fields, jtag_get_end_state());
444 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)data);
445
446 data++;
447 size--;
448 }
449
450 return jtag_execute_queue();
451 }
452
453 /**
454 * Queue a read for an EmbeddedICE register into the register cache,
455 * not checking the value read.
456 */
457 int embeddedice_read_reg(struct reg *reg)
458 {
459 return embeddedice_read_reg_w_check(reg, NULL, NULL);
460 }
461
462 /**
463 * Queue a write for an EmbeddedICE register, updating the register cache.
464 * Uses embeddedice_write_reg().
465 */
466 void embeddedice_set_reg(struct reg *reg, uint32_t value)
467 {
468 embeddedice_write_reg(reg, value);
469
470 buf_set_u32(reg->value, 0, reg->size, value);
471 reg->valid = 1;
472 reg->dirty = 0;
473
474 }
475
476 /**
477 * Write an EmbeddedICE register, updating the register cache.
478 * Uses embeddedice_set_reg(); not queued.
479 */
480 int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf)
481 {
482 int retval;
483
484 embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
485 if ((retval = jtag_execute_queue()) != ERROR_OK)
486 LOG_ERROR("register write failed");
487 return retval;
488 }
489
490 /**
491 * Queue a write for an EmbeddedICE register, bypassing the register cache.
492 */
493 void embeddedice_write_reg(struct reg *reg, uint32_t value)
494 {
495 struct embeddedice_reg *ice_reg = reg->arch_info;
496
497 LOG_DEBUG("%i: 0x%8.8" PRIx32 "", ice_reg->addr, value);
498
499 jtag_set_end_state(TAP_IDLE);
500 arm_jtag_scann(ice_reg->jtag_info, 0x2);
501
502 arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
503
504 uint8_t reg_addr = ice_reg->addr & 0x1f;
505 embeddedice_write_reg_inner(ice_reg->jtag_info->tap, reg_addr, value);
506 }
507
508 /**
509 * Queue a write for an EmbeddedICE register, using cached value.
510 * Uses embeddedice_write_reg().
511 */
512 void embeddedice_store_reg(struct reg *reg)
513 {
514 embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
515 }
516
517 /**
518 * Send a block of size 32-bit words to the DCC.
519 * We assume the target is always going to be fast enough (relative to
520 * the JTAG clock) that the debugger won't need to poll the handshake
521 * bit. The JTAG clock is usually at least six times slower than the
522 * functional clock, so the 50+ JTAG clocks needed to receive the word
523 * allow hundreds of instruction cycles (per word) in the target.
524 */
525 int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
526 {
527 struct scan_field fields[3];
528 uint8_t field0_out[4];
529 uint8_t field1_out[1];
530 uint8_t field2_out[1];
531
532 jtag_set_end_state(TAP_IDLE);
533 arm_jtag_scann(jtag_info, 0x2);
534 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
535
536 fields[0].tap = jtag_info->tap;
537 fields[0].num_bits = 32;
538 fields[0].out_value = field0_out;
539 fields[0].in_value = NULL;
540
541 fields[1].tap = jtag_info->tap;
542 fields[1].num_bits = 5;
543 fields[1].out_value = field1_out;
544 fields[1].out_value[0] = eice_regs[EICE_COMMS_DATA].addr;
545 fields[1].in_value = NULL;
546
547 fields[2].tap = jtag_info->tap;
548 fields[2].num_bits = 1;
549 fields[2].out_value = field2_out;
550 fields[2].out_value[0] = 1;
551
552 fields[2].in_value = NULL;
553
554 while (size > 0)
555 {
556 buf_set_u32(fields[0].out_value, 0, 32, *data);
557 jtag_add_dr_scan(3, fields, jtag_get_end_state());
558
559 data++;
560 size--;
561 }
562
563 /* call to jtag_execute_queue() intentionally omitted */
564 return ERROR_OK;
565 }
566
567 /**
568 * Poll DCC control register until read or write handshake completes.
569 */
570 int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout)
571 {
572 struct scan_field fields[3];
573 uint8_t field0_in[4];
574 uint8_t field1_out[1];
575 uint8_t field2_out[1];
576 int retval;
577 uint32_t hsact;
578 struct timeval lap;
579 struct timeval now;
580
581 if (hsbit == EICE_COMM_CTRL_WBIT)
582 hsact = 1;
583 else if (hsbit == EICE_COMM_CTRL_RBIT)
584 hsact = 0;
585 else
586 return ERROR_INVALID_ARGUMENTS;
587
588 jtag_set_end_state(TAP_IDLE);
589 arm_jtag_scann(jtag_info, 0x2);
590 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
591
592 fields[0].tap = jtag_info->tap;
593 fields[0].num_bits = 32;
594 fields[0].out_value = NULL;
595 fields[0].in_value = field0_in;
596
597 fields[1].tap = jtag_info->tap;
598 fields[1].num_bits = 5;
599 fields[1].out_value = field1_out;
600 fields[1].out_value[0] = eice_regs[EICE_COMMS_DATA].addr;
601 fields[1].in_value = NULL;
602
603 fields[2].tap = jtag_info->tap;
604 fields[2].num_bits = 1;
605 fields[2].out_value = field2_out;
606 fields[2].out_value[0] = 0;
607 fields[2].in_value = NULL;
608
609 jtag_add_dr_scan(3, fields, jtag_get_end_state());
610 gettimeofday(&lap, NULL);
611 do {
612 jtag_add_dr_scan(3, fields, jtag_get_end_state());
613 if ((retval = jtag_execute_queue()) != ERROR_OK)
614 return retval;
615
616 if (buf_get_u32(field0_in, hsbit, 1) == hsact)
617 return ERROR_OK;
618
619 gettimeofday(&now, NULL);
620 } while ((uint32_t)((now.tv_sec - lap.tv_sec) * 1000
621 + (now.tv_usec - lap.tv_usec) / 1000) <= timeout);
622
623 return ERROR_TARGET_TIMEOUT;
624 }
625
626 #ifndef HAVE_JTAG_MINIDRIVER_H
627 /**
628 * This is an inner loop of the open loop DCC write of data to target
629 */
630 void embeddedice_write_dcc(struct jtag_tap *tap,
631 int reg_addr, uint8_t *buffer, int little, int count)
632 {
633 int i;
634
635 for (i = 0; i < count; i++)
636 {
637 embeddedice_write_reg_inner(tap, reg_addr,
638 fast_target_buffer_get_u32(buffer, little));
639 buffer += 4;
640 }
641 }
642 #else
643 /* provided by minidriver */
644 #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)