types: write memory now uses const
[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 * 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 static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf);
51
52 /*
53 * From: ARM9E-S TRM, DDI 0165, table C-4 (and similar, for other cores)
54 */
55 static const struct {
56 char *name;
57 unsigned short addr;
58 unsigned short width;
59 } eice_regs[] = {
60 [EICE_DBG_CTRL] = {
61 .name = "debug_ctrl",
62 .addr = 0,
63 /* width is assigned based on EICE version */
64 },
65 [EICE_DBG_STAT] = {
66 .name = "debug_status",
67 .addr = 1,
68 /* width is assigned based on EICE version */
69 },
70 [EICE_COMMS_CTRL] = {
71 .name = "comms_ctrl",
72 .addr = 4,
73 .width = 6,
74 },
75 [EICE_COMMS_DATA] = {
76 .name = "comms_data",
77 .addr = 5,
78 .width = 32,
79 },
80 [EICE_W0_ADDR_VALUE] = {
81 .name = "watch_0_addr_value",
82 .addr = 8,
83 .width = 32,
84 },
85 [EICE_W0_ADDR_MASK] = {
86 .name = "watch_0_addr_mask",
87 .addr = 9,
88 .width = 32,
89 },
90 [EICE_W0_DATA_VALUE ] = {
91 .name = "watch_0_data_value",
92 .addr = 10,
93 .width = 32,
94 },
95 [EICE_W0_DATA_MASK] = {
96 .name = "watch_0_data_mask",
97 .addr = 11,
98 .width = 32,
99 },
100 [EICE_W0_CONTROL_VALUE] = {
101 .name = "watch_0_control_value",
102 .addr = 12,
103 .width = 9,
104 },
105 [EICE_W0_CONTROL_MASK] = {
106 .name = "watch_0_control_mask",
107 .addr = 13,
108 .width = 8,
109 },
110 [EICE_W1_ADDR_VALUE] = {
111 .name = "watch_1_addr_value",
112 .addr = 16,
113 .width = 32,
114 },
115 [EICE_W1_ADDR_MASK] = {
116 .name = "watch_1_addr_mask",
117 .addr = 17,
118 .width = 32,
119 },
120 [EICE_W1_DATA_VALUE] = {
121 .name = "watch_1_data_value",
122 .addr = 18,
123 .width = 32,
124 },
125 [EICE_W1_DATA_MASK] = {
126 .name = "watch_1_data_mask",
127 .addr = 19,
128 .width = 32,
129 },
130 [EICE_W1_CONTROL_VALUE] = {
131 .name = "watch_1_control_value",
132 .addr = 20,
133 .width = 9,
134 },
135 [EICE_W1_CONTROL_MASK] = {
136 .name = "watch_1_control_mask",
137 .addr = 21,
138 .width = 8,
139 },
140 /* vector_catch isn't always present */
141 [EICE_VEC_CATCH] = {
142 .name = "vector_catch",
143 .addr = 2,
144 .width = 8,
145 },
146 };
147
148
149 static int embeddedice_get_reg(struct reg *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 static const struct reg_arch_type eice_reg_type = {
162 .get = embeddedice_get_reg,
163 .set = embeddedice_set_reg_w_exec,
164 };
165
166 /**
167 * Probe EmbeddedICE module and set up local records of its registers.
168 * Different versions of the modules have different capabilities, such as
169 * hardware support for vector_catch, single stepping, and monitor mode.
170 */
171 struct reg_cache *
172 embeddedice_build_reg_cache(struct target *target, struct arm7_9_common *arm7_9)
173 {
174 int retval;
175 struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
176 struct reg *reg_list = NULL;
177 struct embeddedice_reg *arch_info = NULL;
178 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
179 int num_regs = ARRAY_SIZE(eice_regs);
180 int i;
181 int eice_version = 0;
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(struct reg));
189 arch_info = calloc(num_regs, sizeof(struct embeddedice_reg));
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 /* FIXME the second watchpoint unit on Feroceon and Dragonite
198 * seems not to work ... we should have a way to not set up
199 * its four registers here!
200 */
201
202 /* set up registers */
203 for (i = 0; i < num_regs; i++)
204 {
205 reg_list[i].name = eice_regs[i].name;
206 reg_list[i].size = eice_regs[i].width;
207 reg_list[i].dirty = 0;
208 reg_list[i].valid = 0;
209 reg_list[i].value = calloc(1, 4);
210 reg_list[i].arch_info = &arch_info[i];
211 reg_list[i].type = &eice_reg_type;
212 arch_info[i].addr = eice_regs[i].addr;
213 arch_info[i].jtag_info = jtag_info;
214 }
215
216 /* identify EmbeddedICE version by reading DCC control register */
217 embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);
218 if ((retval = jtag_execute_queue()) != ERROR_OK)
219 {
220 for (i = 0; i < num_regs; i++)
221 {
222 free(reg_list[i].value);
223 }
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 {
235 case 1:
236 /* ARM7TDMI r3, ARM7TDMI-S r3
237 *
238 * REVISIT docs say ARM7TDMI-S r4 uses version 1 but
239 * that it has 6-bit CTRL and 5-bit STAT... doc bug?
240 * ARM7TDMI r4 docs say EICE v4.
241 */
242 reg_list[EICE_DBG_CTRL].size = 3;
243 reg_list[EICE_DBG_STAT].size = 5;
244 break;
245 case 2:
246 /* ARM9TDMI */
247 reg_list[EICE_DBG_CTRL].size = 4;
248 reg_list[EICE_DBG_STAT].size = 5;
249 arm7_9->has_single_step = 1;
250 break;
251 case 3:
252 LOG_ERROR("EmbeddedICE v%d handling might be broken",
253 eice_version);
254 reg_list[EICE_DBG_CTRL].size = 6;
255 reg_list[EICE_DBG_STAT].size = 5;
256 arm7_9->has_single_step = 1;
257 arm7_9->has_monitor_mode = 1;
258 break;
259 case 4:
260 /* ARM7TDMI r4 */
261 reg_list[EICE_DBG_CTRL].size = 6;
262 reg_list[EICE_DBG_STAT].size = 5;
263 arm7_9->has_monitor_mode = 1;
264 break;
265 case 5:
266 /* ARM9E-S rev 1 */
267 reg_list[EICE_DBG_CTRL].size = 6;
268 reg_list[EICE_DBG_STAT].size = 5;
269 arm7_9->has_single_step = 1;
270 arm7_9->has_monitor_mode = 1;
271 break;
272 case 6:
273 /* ARM7EJ-S, ARM9E-S rev 2, ARM9EJ-S */
274 reg_list[EICE_DBG_CTRL].size = 6;
275 reg_list[EICE_DBG_STAT].size = 10;
276 /* DBG_STAT has MOE bits */
277 arm7_9->has_monitor_mode = 1;
278 break;
279 case 7:
280 LOG_ERROR("EmbeddedICE v%d handling might be broken",
281 eice_version);
282 reg_list[EICE_DBG_CTRL].size = 6;
283 reg_list[EICE_DBG_STAT].size = 5;
284 arm7_9->has_monitor_mode = 1;
285 break;
286 default:
287 /*
288 * The Feroceon implementation has the version number
289 * in some unusual bits. Let feroceon.c validate it
290 * and do the appropriate setup itself.
291 */
292 if (strcmp(target_type_name(target), "feroceon") == 0 ||
293 strcmp(target_type_name(target), "dragonite") == 0)
294 break;
295 LOG_ERROR("unknown EmbeddedICE version "
296 "(comms ctrl: 0x%8.8" PRIx32 ")",
297 buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
298 }
299
300 /* On Feroceon and Dragonite the second unit is seemingly missing. */
301 LOG_INFO("%s: hardware has %d breakpoint/watchpoint unit%s",
302 target_name(target), arm7_9->wp_available_max,
303 (arm7_9->wp_available_max != 1) ? "s" : "");
304
305 return reg_cache;
306 }
307
308 /**
309 * Initialize EmbeddedICE module, if needed.
310 */
311 int embeddedice_setup(struct target *target)
312 {
313 int retval;
314 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
315
316 /* Explicitly disable monitor mode. For now we only support halting
317 * debug ... we don't know how to talk with a resident debug monitor
318 * that manages break requests. ARM's "Angel Debug Monitor" is one
319 * common example of such code.
320 */
321 if (arm7_9->has_monitor_mode)
322 {
323 struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
324
325 embeddedice_read_reg(dbg_ctrl);
326 if ((retval = jtag_execute_queue()) != ERROR_OK)
327 return retval;
328 buf_set_u32(dbg_ctrl->value, 4, 1, 0);
329 embeddedice_set_reg_w_exec(dbg_ctrl, dbg_ctrl->value);
330 }
331 return jtag_execute_queue();
332 }
333
334 /**
335 * Queue a read for an EmbeddedICE register into the register cache,
336 * optionally checking the value read.
337 * Note that at this level, all registers are 32 bits wide.
338 */
339 int embeddedice_read_reg_w_check(struct reg *reg,
340 uint8_t *check_value, uint8_t *check_mask)
341 {
342 struct embeddedice_reg *ice_reg = reg->arch_info;
343 uint8_t reg_addr = ice_reg->addr & 0x1f;
344 struct scan_field fields[3];
345 uint8_t field1_out[1];
346 uint8_t field2_out[1];
347 int retval;
348
349 retval = arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE);
350 if (retval != ERROR_OK)
351 return retval;
352
353 retval = arm_jtag_set_instr(ice_reg->jtag_info, 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 {
440 /* when reading the last item, set the register address to the DCC control reg,
441 * to avoid reading additional data from the DCC data reg
442 */
443 if (size == 1)
444 field1_out[0] = eice_regs[EICE_COMMS_CTRL].addr;
445
446 fields[0].in_value = (uint8_t *)data;
447 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
448 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)data);
449
450 data++;
451 size--;
452 }
453
454 return jtag_execute_queue();
455 }
456
457 /**
458 * Queue a read for an EmbeddedICE register into the register cache,
459 * not checking the value read.
460 */
461 int embeddedice_read_reg(struct reg *reg)
462 {
463 return embeddedice_read_reg_w_check(reg, NULL, NULL);
464 }
465
466 /**
467 * Queue a write for an EmbeddedICE register, updating the register cache.
468 * Uses embeddedice_write_reg().
469 */
470 void embeddedice_set_reg(struct reg *reg, uint32_t value)
471 {
472 embeddedice_write_reg(reg, value);
473
474 buf_set_u32(reg->value, 0, reg->size, value);
475 reg->valid = 1;
476 reg->dirty = 0;
477
478 }
479
480 /**
481 * Write an EmbeddedICE register, updating the register cache.
482 * Uses embeddedice_set_reg(); not queued.
483 */
484 static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf)
485 {
486 int retval;
487
488 embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
489 if ((retval = jtag_execute_queue()) != 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 int retval;
501
502 LOG_DEBUG("%i: 0x%8.8" PRIx32 "", ice_reg->addr, value);
503
504 retval = arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE);
505
506 retval = arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE);
507
508 uint8_t reg_addr = ice_reg->addr & 0x1f;
509 embeddedice_write_reg_inner(ice_reg->jtag_info->tap, reg_addr, value);
510 }
511
512 /**
513 * Queue a write for an EmbeddedICE register, using cached value.
514 * Uses embeddedice_write_reg().
515 */
516 void embeddedice_store_reg(struct reg *reg)
517 {
518 embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
519 }
520
521 /**
522 * Send a block of size 32-bit words to the DCC.
523 * We assume the target is always going to be fast enough (relative to
524 * the JTAG clock) that the debugger won't need to poll the handshake
525 * bit. The JTAG clock is usually at least six times slower than the
526 * functional clock, so the 50+ JTAG clocks needed to receive the word
527 * allow hundreds of instruction cycles (per word) in the target.
528 */
529 int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
530 {
531 struct scan_field fields[3];
532 uint8_t field0_out[4];
533 uint8_t field1_out[1];
534 uint8_t field2_out[1];
535 int retval;
536
537 retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
538 if (retval != ERROR_OK)
539 return retval;
540 retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
541 if (retval != ERROR_OK)
542 return retval;
543
544 fields[0].num_bits = 32;
545 fields[0].out_value = field0_out;
546 fields[0].in_value = NULL;
547
548 fields[1].num_bits = 5;
549 fields[1].out_value = field1_out;
550 field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
551 fields[1].in_value = NULL;
552
553 fields[2].num_bits = 1;
554 fields[2].out_value = field2_out;
555 field2_out[0] = 1;
556
557 fields[2].in_value = NULL;
558
559 while (size > 0)
560 {
561 buf_set_u32(field0_out, 0, 32, *data);
562 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
563
564 data++;
565 size--;
566 }
567
568 /* call to jtag_execute_queue() intentionally omitted */
569 return ERROR_OK;
570 }
571
572 /**
573 * Poll DCC control register until read or write handshake completes.
574 */
575 int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout)
576 {
577 struct scan_field fields[3];
578 uint8_t field0_in[4];
579 uint8_t field1_out[1];
580 uint8_t field2_out[1];
581 int retval;
582 uint32_t hsact;
583 struct timeval lap;
584 struct timeval now;
585
586 if (hsbit == EICE_COMM_CTRL_WBIT)
587 hsact = 1;
588 else if (hsbit == EICE_COMM_CTRL_RBIT)
589 hsact = 0;
590 else
591 {
592 LOG_ERROR("Invalid arguments");
593 return ERROR_INVALID_ARGUMENTS;
594 }
595
596 retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
597 if (retval != ERROR_OK)
598 return retval;
599 retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
600 if (retval != ERROR_OK)
601 return retval;
602
603 fields[0].num_bits = 32;
604 fields[0].out_value = NULL;
605 fields[0].in_value = field0_in;
606
607 fields[1].num_bits = 5;
608 fields[1].out_value = field1_out;
609 field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
610 fields[1].in_value = NULL;
611
612 fields[2].num_bits = 1;
613 fields[2].out_value = field2_out;
614 field2_out[0] = 0;
615 fields[2].in_value = NULL;
616
617 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
618 gettimeofday(&lap, NULL);
619 do {
620 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
621 if ((retval = jtag_execute_queue()) != ERROR_OK)
622 return retval;
623
624 if (buf_get_u32(field0_in, hsbit, 1) == hsact)
625 return ERROR_OK;
626
627 gettimeofday(&now, NULL);
628 } while ((uint32_t)((now.tv_sec - lap.tv_sec) * 1000
629 + (now.tv_usec - lap.tv_usec) / 1000) <= timeout);
630
631 LOG_ERROR("embeddedice handshake timeout");
632 return ERROR_TARGET_TIMEOUT;
633 }
634
635 #ifndef HAVE_JTAG_MINIDRIVER_H
636 /**
637 * This is an inner loop of the open loop DCC write of data to target
638 */
639 void embeddedice_write_dcc(struct jtag_tap *tap,
640 int reg_addr, const uint8_t *buffer, int little, int count)
641 {
642 int i;
643
644 for (i = 0; i < count; i++)
645 {
646 embeddedice_write_reg_inner(tap, reg_addr,
647 fast_target_buffer_get_u32(buffer, little));
648 buffer += 4;
649 }
650 }
651 #else
652 /* provided by minidriver */
653 #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)