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

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)