jim tests: use installed
[openocd.git] / src / target / avr32_ap7k.c
1 /***************************************************************************
2 * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
3 * Based on mips_m4k code: *
4 * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "jtag/jtag.h"
27 #include "register.h"
28 #include "algorithm.h"
29 #include "target.h"
30 #include "breakpoints.h"
31 #include "target_type.h"
32 #include "avr32_jtag.h"
33 #include "avr32_mem.h"
34 #include "avr32_regs.h"
35 #include "avr32_ap7k.h"
36
37 static char* avr32_core_reg_list[] =
38 {
39 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
40 "r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr"
41 };
42
43 static struct avr32_core_reg
44 avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] =
45 {
46 {0, NULL, NULL},
47 {1, NULL, NULL},
48 {2, NULL, NULL},
49 {3, NULL, NULL},
50 {4, NULL, NULL},
51 {5, NULL, NULL},
52 {6, NULL, NULL},
53 {7, NULL, NULL},
54 {8, NULL, NULL},
55 {9, NULL, NULL},
56 {10, NULL, NULL},
57 {11, NULL, NULL},
58 {12, NULL, NULL},
59 {13, NULL, NULL},
60 {14, NULL, NULL},
61 {15, NULL, NULL},
62 {16, NULL, NULL},
63 };
64
65
66 static int avr32_read_core_reg(struct target *target, int num);
67 static int avr32_write_core_reg(struct target *target, int num);
68
69 int avr32_ap7k_save_context(struct target *target)
70 {
71 int retval, i;
72 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
73
74 retval = avr32_jtag_read_regs(&ap7k->jtag, ap7k->core_regs);
75 if (retval != ERROR_OK)
76 return retval;
77
78 for (i = 0; i < AVR32NUMCOREREGS; i++)
79 {
80 if (!ap7k->core_cache->reg_list[i].valid)
81 {
82 avr32_read_core_reg(target, i);
83 }
84 }
85
86 return ERROR_OK;
87 }
88
89 int avr32_ap7k_restore_context(struct target *target)
90 {
91 int i;
92
93 /* get pointers to arch-specific information */
94 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
95
96 for (i = 0; i < AVR32NUMCOREREGS; i++)
97 {
98 if (ap7k->core_cache->reg_list[i].dirty)
99 {
100 avr32_write_core_reg(target, i);
101 }
102 }
103
104 /* write core regs */
105 avr32_jtag_write_regs(&ap7k->jtag, ap7k->core_regs);
106
107 return ERROR_OK;
108 }
109
110 static int avr32_read_core_reg(struct target *target, int num)
111 {
112 uint32_t reg_value;
113 struct avr32_core_reg *mips_core_reg;
114
115 /* get pointers to arch-specific information */
116 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
117
118 if ((num < 0) || (num >= AVR32NUMCOREREGS))
119 return ERROR_INVALID_ARGUMENTS;
120
121 mips_core_reg = ap7k->core_cache->reg_list[num].arch_info;
122 reg_value = ap7k->core_regs[num];
123 buf_set_u32(ap7k->core_cache->reg_list[num].value, 0, 32, reg_value);
124 ap7k->core_cache->reg_list[num].valid = 1;
125 ap7k->core_cache->reg_list[num].dirty = 0;
126
127 return ERROR_OK;
128 }
129
130 static int avr32_write_core_reg(struct target *target, int num)
131 {
132 uint32_t reg_value;
133 struct avr32_core_reg *mips_core_reg;
134
135 /* get pointers to arch-specific information */
136 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
137
138 if ((num < 0) || (num >= AVR32NUMCOREREGS))
139 return ERROR_INVALID_ARGUMENTS;
140
141 reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32);
142 mips_core_reg = ap7k->core_cache->reg_list[num].arch_info;
143 ap7k->core_regs[num] = reg_value;
144 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
145 ap7k->core_cache->reg_list[num].valid = 1;
146 ap7k->core_cache->reg_list[num].dirty = 0;
147
148 return ERROR_OK;
149 }
150
151 static int avr32_get_core_reg(struct reg *reg)
152 {
153 int retval;
154 struct avr32_core_reg *avr32_reg = reg->arch_info;
155 struct target *target = avr32_reg->target;
156
157 if (target->state != TARGET_HALTED)
158 {
159 return ERROR_TARGET_NOT_HALTED;
160 }
161
162 retval = avr32_read_core_reg(target, avr32_reg->num);
163
164 return retval;
165 }
166
167 static int avr32_set_core_reg(struct reg *reg, uint8_t *buf)
168 {
169 struct avr32_core_reg *avr32_reg = reg->arch_info;
170 struct target *target = avr32_reg->target;
171 uint32_t value = buf_get_u32(buf, 0, 32);
172
173 if (target->state != TARGET_HALTED)
174 {
175 return ERROR_TARGET_NOT_HALTED;
176 }
177
178 buf_set_u32(reg->value, 0, 32, value);
179 reg->dirty = 1;
180 reg->valid = 1;
181
182 return ERROR_OK;
183 }
184
185 static const struct reg_arch_type avr32_reg_type = {
186 .get = avr32_get_core_reg,
187 .set = avr32_set_core_reg,
188 };
189
190 static struct reg_cache *avr32_build_reg_cache(struct target *target)
191 {
192 int num_regs = AVR32NUMCOREREGS;
193 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
194 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
195 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
196 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
197 struct avr32_core_reg *arch_info =
198 malloc(sizeof(struct avr32_core_reg) * num_regs);
199 int i;
200
201 /* Build the process context cache */
202 cache->name = "avr32 registers";
203 cache->next = NULL;
204 cache->reg_list = reg_list;
205 cache->num_regs = num_regs;
206 (*cache_p) = cache;
207 ap7k->core_cache = cache;
208
209 for (i = 0; i < num_regs; i++)
210 {
211 arch_info[i] = avr32_core_reg_list_arch_info[i];
212 arch_info[i].target = target;
213 arch_info[i].avr32_common = ap7k;
214 reg_list[i].name = avr32_core_reg_list[i];
215 reg_list[i].size = 32;
216 reg_list[i].value = calloc(1, 4);
217 reg_list[i].dirty = 0;
218 reg_list[i].valid = 0;
219 reg_list[i].type = &avr32_reg_type;
220 reg_list[i].arch_info = &arch_info[i];
221 }
222
223 return cache;
224 }
225
226 static int avr32_ap7k_debug_entry(struct target *target)
227 {
228
229 uint32_t dpc, dinst;
230 int retval;
231 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
232
233 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DPC, &dpc);
234 if (retval != ERROR_OK)
235 return retval;
236
237 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DINST, &dinst);
238 if (retval != ERROR_OK)
239 return retval;
240
241 ap7k->jtag.dpc = dpc;
242
243 avr32_ap7k_save_context(target);
244
245 return ERROR_OK;
246 }
247
248
249 static int avr32_ap7k_poll(struct target *target)
250 {
251 uint32_t ds;
252 int retval;
253 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
254
255 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
256 if (retval != ERROR_OK)
257 return retval;
258
259 /* check for processor halted */
260 if (ds & OCDREG_DS_DBA)
261 {
262 if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
263 {
264 target->state = TARGET_HALTED;
265
266 if ((retval = avr32_ap7k_debug_entry(target)) != ERROR_OK)
267 return retval;
268
269 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
270 }
271 else if (target->state == TARGET_DEBUG_RUNNING)
272 {
273 target->state = TARGET_HALTED;
274
275 if ((retval = avr32_ap7k_debug_entry(target)) != ERROR_OK)
276 return retval;
277
278 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
279 }
280 }
281 else
282 {
283 target->state = TARGET_RUNNING;
284 }
285
286
287 return ERROR_OK;
288 }
289
290 static int avr32_ap7k_halt(struct target *target)
291 {
292 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
293
294 LOG_DEBUG("target->state: %s",
295 target_state_name(target));
296
297 if (target->state == TARGET_HALTED)
298 {
299 LOG_DEBUG("target was already halted");
300 return ERROR_OK;
301 }
302
303 if (target->state == TARGET_UNKNOWN)
304 {
305 LOG_WARNING("target was in unknown state when halt was requested");
306 }
307
308 if (target->state == TARGET_RESET)
309 {
310 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
311 {
312 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
313 return ERROR_TARGET_FAILURE;
314 }
315 else
316 {
317 target->debug_reason = DBG_REASON_DBGRQ;
318
319 return ERROR_OK;
320 }
321 }
322
323
324 avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR);
325 target->debug_reason = DBG_REASON_DBGRQ;
326
327 return ERROR_OK;
328 }
329
330 static int avr32_ap7k_assert_reset(struct target *target)
331 {
332 LOG_ERROR("%s: implement me", __func__);
333
334 return ERROR_OK;
335 }
336
337 static int avr32_ap7k_deassert_reset(struct target *target)
338 {
339 LOG_ERROR("%s: implement me", __func__);
340
341 return ERROR_OK;
342 }
343
344 static int avr32_ap7k_soft_reset_halt(struct target *target)
345 {
346 LOG_ERROR("%s: implement me", __func__);
347
348 return ERROR_OK;
349 }
350
351 static int avr32_ap7k_resume(struct target *target, int current,
352 uint32_t address, int handle_breakpoints, int debug_execution)
353 {
354 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
355 struct breakpoint *breakpoint = NULL;
356 uint32_t resume_pc;
357 int retval;
358
359 if (target->state != TARGET_HALTED)
360 {
361 LOG_WARNING("target not halted");
362 return ERROR_TARGET_NOT_HALTED;
363 }
364
365 if (!debug_execution)
366 {
367 target_free_all_working_areas(target);
368 /*
369 avr32_ap7k_enable_breakpoints(target);
370 avr32_ap7k_enable_watchpoints(target);
371 */
372 }
373
374 /* current = 1: continue on current pc, otherwise continue at <address> */
375 if (!current)
376 {
377 #if 0
378 if (retval != ERROR_OK)
379 return retval;
380 #endif
381 }
382
383 resume_pc =
384 buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
385 avr32_ap7k_restore_context(target);
386
387 /* the front-end may request us not to handle breakpoints */
388 if (handle_breakpoints)
389 {
390 /* Single step past breakpoint at current address */
391 if ((breakpoint = breakpoint_find(target, resume_pc)))
392 {
393 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
394 #if 0
395 avr32_ap7k_unset_breakpoint(target, breakpoint);
396 avr32_ap7k_single_step_core(target);
397 avr32_ap7k_set_breakpoint(target, breakpoint);
398 #endif
399 }
400 }
401
402 #if 0
403 /* enable interrupts if we are running */
404 avr32_ap7k_enable_interrupts(target, !debug_execution);
405
406 /* exit debug mode */
407 mips_ejtag_exit_debug(ejtag_info);
408 #endif
409
410
411 retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC,
412 OCDREG_DC_DBR);
413 if (retval != ERROR_OK)
414 return retval;
415
416 retval = avr32_jtag_exec(&ap7k->jtag, RETD);
417 if (retval != ERROR_OK)
418 return retval;
419
420 target->debug_reason = DBG_REASON_NOTHALTED;
421
422 /* registers are now invalid */
423 register_cache_invalidate(ap7k->core_cache);
424
425 if (!debug_execution)
426 {
427 target->state = TARGET_RUNNING;
428 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
429 LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
430 }
431 else
432 {
433 target->state = TARGET_DEBUG_RUNNING;
434 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
435 LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
436 }
437
438 return ERROR_OK;
439 }
440
441 static int avr32_ap7k_step(struct target *target, int current,
442 uint32_t address, int handle_breakpoints)
443 {
444 LOG_ERROR("%s: implement me", __func__);
445
446 return ERROR_OK;
447 }
448
449 static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
450 {
451 LOG_ERROR("%s: implement me", __func__);
452
453 return ERROR_OK;
454 }
455
456 static int avr32_ap7k_remove_breakpoint(struct target *target,
457 struct breakpoint *breakpoint)
458 {
459 LOG_ERROR("%s: implement me", __func__);
460
461 return ERROR_OK;
462 }
463
464 static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
465 {
466 LOG_ERROR("%s: implement me", __func__);
467
468 return ERROR_OK;
469 }
470
471 static int avr32_ap7k_remove_watchpoint(struct target *target,
472 struct watchpoint *watchpoint)
473 {
474 LOG_ERROR("%s: implement me", __func__);
475
476 return ERROR_OK;
477 }
478
479 static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
480 uint32_t size, uint32_t count, uint8_t *buffer)
481 {
482 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
483
484 LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count);
485
486 if (target->state != TARGET_HALTED)
487 {
488 LOG_WARNING("target not halted");
489 return ERROR_TARGET_NOT_HALTED;
490 }
491
492 /* sanitize arguments */
493 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
494 return ERROR_INVALID_ARGUMENTS;
495
496 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
497 return ERROR_TARGET_UNALIGNED_ACCESS;
498
499 switch (size)
500 {
501 case 4:
502 return avr32_jtag_read_memory32(&ap7k->jtag, address, count, (uint32_t*)(void *)buffer);
503 break;
504 case 2:
505 return avr32_jtag_read_memory16(&ap7k->jtag, address, count, (uint16_t*)(void *)buffer);
506 break;
507 case 1:
508 return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
509 break;
510 default:
511 break;
512 }
513
514 return ERROR_OK;
515 }
516
517 static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
518 uint32_t size, uint32_t count, uint8_t *buffer)
519 {
520 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
521
522 LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count);
523
524 if (target->state != TARGET_HALTED)
525 {
526 LOG_WARNING("target not halted");
527 return ERROR_TARGET_NOT_HALTED;
528 }
529
530 /* sanitize arguments */
531 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
532 return ERROR_INVALID_ARGUMENTS;
533
534 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
535 return ERROR_TARGET_UNALIGNED_ACCESS;
536
537 switch (size)
538 {
539 case 4:
540 return avr32_jtag_write_memory32(&ap7k->jtag, address, count, (uint32_t*)(void *)buffer);
541 break;
542 case 2:
543 return avr32_jtag_write_memory16(&ap7k->jtag, address, count, (uint16_t*)(void *)buffer);
544 break;
545 case 1:
546 return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
547 break;
548 default:
549 break;
550 }
551
552 return ERROR_OK;
553 }
554
555 static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
556 struct target *target)
557 {
558 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
559
560 ap7k->jtag.tap = target->tap;
561 avr32_build_reg_cache(target);
562 return ERROR_OK;
563 }
564
565 static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
566 {
567 struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
568 avr32_ap7k_common));
569
570 ap7k->common_magic = AP7k_COMMON_MAGIC;
571 target->arch_info = ap7k;
572
573 return ERROR_OK;
574 }
575
576 static int avr32_ap7k_examine(struct target *target)
577 {
578 uint32_t devid, ds;
579 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
580
581 if (!target_was_examined(target))
582 {
583 target_set_examined(target);
584 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
585 LOG_INFO("device id: %08x", devid);
586 avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC,OCDREG_DC_DBE);
587 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
588
589 /* check for processor halted */
590 if (ds & OCDREG_DS_DBA)
591 {
592 LOG_INFO("target is halted");
593 target->state = TARGET_HALTED;
594 }
595 else
596 target->state = TARGET_RUNNING;
597 }
598
599 return ERROR_OK;
600 }
601
602 static int avr32_ap7k_bulk_write_memory(struct target *target, uint32_t address,
603 uint32_t count, uint8_t *buffer)
604 {
605 LOG_ERROR("%s: implement me", __func__);
606
607 return ERROR_OK;
608 }
609
610
611 int avr32_ap7k_arch_state(struct target *target)
612 {
613 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
614
615 LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
616 debug_reason_name(target), ap7k->jtag.dpc);
617
618 return ERROR_OK;
619 }
620
621 int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
622 {
623 #if 0
624 /* get pointers to arch-specific information */
625 int i;
626
627 /* include floating point registers */
628 *reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
629 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
630
631 for (i = 0; i < AVR32NUMCOREREGS; i++)
632 {
633 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
634 }
635
636 /* add dummy floating points regs */
637 for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
638 {
639 (*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
640 }
641 #endif
642
643 LOG_ERROR("%s: implement me", __func__);
644 return ERROR_FAIL;
645 }
646
647
648
649 struct target_type avr32_ap7k_target =
650 {
651 .name = "avr32_ap7k",
652
653 .poll = avr32_ap7k_poll,
654 .arch_state = avr32_ap7k_arch_state,
655
656 .target_request_data = NULL,
657
658 .halt = avr32_ap7k_halt,
659 .resume = avr32_ap7k_resume,
660 .step = avr32_ap7k_step,
661
662 .assert_reset = avr32_ap7k_assert_reset,
663 .deassert_reset = avr32_ap7k_deassert_reset,
664 .soft_reset_halt = avr32_ap7k_soft_reset_halt,
665
666 .get_gdb_reg_list = avr32_ap7k_get_gdb_reg_list,
667
668 .read_memory = avr32_ap7k_read_memory,
669 .write_memory = avr32_ap7k_write_memory,
670 .bulk_write_memory = avr32_ap7k_bulk_write_memory,
671 // .checksum_memory = avr32_ap7k_checksum_memory,
672 // .blank_check_memory = avr32_ap7k_blank_check_memory,
673
674 // .run_algorithm = avr32_ap7k_run_algorithm,
675
676 .add_breakpoint = avr32_ap7k_add_breakpoint,
677 .remove_breakpoint = avr32_ap7k_remove_breakpoint,
678 .add_watchpoint = avr32_ap7k_add_watchpoint,
679 .remove_watchpoint = avr32_ap7k_remove_watchpoint,
680
681 .target_create = avr32_ap7k_target_create,
682 .init_target = avr32_ap7k_init_target,
683 .examine = avr32_ap7k_examine,
684 };

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)