- slight mips32 cleanup/reformat
[openocd.git] / src / target / mips_m4k.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
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 "mips32.h"
27 #include "mips_m4k.h"
28 #include "mips32_dmaacc.h"
29 #include "jtag.h"
30 #include "log.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 /* cli handling */
36
37 /* forward declarations */
38 int mips_m4k_poll(target_t *target);
39 int mips_m4k_halt(struct target_s *target);
40 int mips_m4k_soft_reset_halt(struct target_s *target);
41 int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
42 int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
43 int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
44 int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
45 int mips_m4k_register_commands(struct command_context_s *cmd_ctx);
46 int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
47 int mips_m4k_quit(void);
48 int mips_m4k_target_create(struct target_s *target, Jim_Interp *interp);
49
50 int mips_m4k_examine(struct target_s *target);
51 int mips_m4k_assert_reset(target_t *target);
52 int mips_m4k_deassert_reset(target_t *target);
53
54 target_type_t mips_m4k_target =
55 {
56 .name = "mips_m4k",
57
58 .poll = mips_m4k_poll,
59 .arch_state = mips32_arch_state,
60
61 .target_request_data = NULL,
62
63 .halt = mips_m4k_halt,
64 .resume = mips_m4k_resume,
65 .step = mips_m4k_step,
66
67 .assert_reset = mips_m4k_assert_reset,
68 .deassert_reset = mips_m4k_deassert_reset,
69 .soft_reset_halt = mips_m4k_soft_reset_halt,
70
71 .get_gdb_reg_list = mips32_get_gdb_reg_list,
72
73 .read_memory = mips_m4k_read_memory,
74 .write_memory = mips_m4k_write_memory,
75 .bulk_write_memory = mips_m4k_bulk_write_memory,
76 .checksum_memory = NULL,
77 .blank_check_memory = NULL,
78
79 .run_algorithm = mips32_run_algorithm,
80
81 .add_breakpoint = mips_m4k_add_breakpoint,
82 .remove_breakpoint = mips_m4k_remove_breakpoint,
83 .add_watchpoint = mips_m4k_add_watchpoint,
84 .remove_watchpoint = mips_m4k_remove_watchpoint,
85
86 .register_commands = mips_m4k_register_commands,
87 .target_create = mips_m4k_target_create,
88 .init_target = mips_m4k_init_target,
89 .examine = mips_m4k_examine,
90 .quit = mips_m4k_quit
91 };
92
93 int mips_m4k_debug_entry(target_t *target)
94 {
95 u32 debug_reg;
96 mips32_common_t *mips32 = target->arch_info;
97 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
98
99 /* read debug register */
100 mips_ejtag_read_debug(ejtag_info, &debug_reg);
101
102 if ((target->debug_reason != DBG_REASON_DBGRQ)
103 && (target->debug_reason != DBG_REASON_SINGLESTEP))
104 {
105 // if (cortex_m3->nvic_dfsr & DFSR_BKPT)
106 // {
107 // target->debug_reason = DBG_REASON_BREAKPOINT;
108 // if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
109 // target->debug_reason = DBG_REASON_WPTANDBKPT;
110 // }
111 // else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
112 // target->debug_reason = DBG_REASON_WATCHPOINT;
113 }
114
115 if (debug_reg & EJTAG_DEBUG_DSS)
116 {
117 /* stopped due to single step - clear step bit */
118 mips_ejtag_config_step(ejtag_info, 0);
119 }
120
121 mips32_save_context(target);
122
123 LOG_DEBUG("entered debug state at PC 0x%x, target->state: %s",
124 *(u32*)(mips32->core_cache->reg_list[MIPS32_PC].value),
125 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
126
127 return ERROR_OK;
128 }
129
130 int mips_m4k_poll(target_t *target)
131 {
132 int retval;
133 mips32_common_t *mips32 = target->arch_info;
134 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
135 u32 ejtag_ctrl = ejtag_info->ejtag_ctrl;
136
137 /* read ejtag control reg */
138 jtag_add_end_state(TAP_RTI);
139 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
140 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
141
142 if (ejtag_ctrl & EJTAG_CTRL_BRKST)
143 {
144 if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
145 {
146 jtag_add_end_state(TAP_RTI);
147 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
148
149 target->state = TARGET_HALTED;
150
151 if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
152 return retval;
153
154 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
155 }
156 else if (target->state == TARGET_DEBUG_RUNNING)
157 {
158 target->state = TARGET_HALTED;
159
160 if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
161 return retval;
162
163 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
164 }
165 }
166 else
167 {
168 target->state = TARGET_RUNNING;
169 }
170
171 if (ejtag_ctrl & EJTAG_CTRL_ROCC)
172 {
173 /* we have detected a reset, clear flag
174 * otherwise ejtag will not work */
175 jtag_add_end_state(TAP_RTI);
176 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC;
177
178 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
179 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
180 LOG_DEBUG("Reset Detected");
181 }
182
183 // LOG_DEBUG("ctrl=0x%08X", ejtag_ctrl);
184
185 return ERROR_OK;
186 }
187
188 int mips_m4k_halt(struct target_s *target)
189 {
190 mips32_common_t *mips32 = target->arch_info;
191 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
192
193 LOG_DEBUG("target->state: %s",
194 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
195
196 if (target->state == TARGET_HALTED)
197 {
198 LOG_DEBUG("target was already halted");
199 return ERROR_OK;
200 }
201
202 if (target->state == TARGET_UNKNOWN)
203 {
204 LOG_WARNING("target was in unknown state when halt was requested");
205 }
206
207 if (target->state == TARGET_RESET)
208 {
209 if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst)
210 {
211 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
212 return ERROR_TARGET_FAILURE;
213 }
214 else
215 {
216 /* we came here in a reset_halt or reset_init sequence
217 * debug entry was already prepared in mips32_prepare_reset_halt()
218 */
219 target->debug_reason = DBG_REASON_DBGRQ;
220
221 return ERROR_OK;
222 }
223 }
224
225 /* break processor */
226 mips_ejtag_enter_debug(ejtag_info);
227
228 target->debug_reason = DBG_REASON_DBGRQ;
229
230 return ERROR_OK;
231 }
232
233 int mips_m4k_assert_reset(target_t *target)
234 {
235 mips32_common_t *mips32 = target->arch_info;
236 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
237
238 LOG_DEBUG("target->state: %s",
239 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
240
241 if (!(jtag_reset_config & RESET_HAS_SRST))
242 {
243 LOG_ERROR("Can't assert SRST");
244 return ERROR_FAIL;
245 }
246
247 if (target->reset_halt)
248 {
249 /* use hardware to catch reset */
250 jtag_add_end_state(TAP_RTI);
251 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT, NULL);
252 }
253 else
254 {
255 jtag_add_end_state(TAP_RTI);
256 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
257 }
258
259 if (strcmp(target->variant, "ejtag_srst") == 0)
260 {
261 u32 ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST;
262 LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor...");
263 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
264 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
265 }
266 else
267 {
268 /* here we should issue a srst only, but we may have to assert trst as well */
269 if (jtag_reset_config & RESET_SRST_PULLS_TRST)
270 {
271 jtag_add_reset(1, 1);
272 }
273 else
274 {
275 jtag_add_reset(0, 1);
276 }
277 }
278
279 target->state = TARGET_RESET;
280 jtag_add_sleep(50000);
281
282 mips32_invalidate_core_regs(target);
283
284 if (target->reset_halt)
285 {
286 int retval;
287 if ((retval = target_halt(target))!=ERROR_OK)
288 return retval;
289 }
290
291
292 return ERROR_OK;
293 }
294
295 int mips_m4k_deassert_reset(target_t *target)
296 {
297 LOG_DEBUG("target->state: %s",
298 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
299
300 /* deassert reset lines */
301 jtag_add_reset(0, 0);
302
303 return ERROR_OK;
304 }
305
306 int mips_m4k_soft_reset_halt(struct target_s *target)
307 {
308 /* TODO */
309 return ERROR_OK;
310 }
311
312 int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
313 {
314 mips32_common_t *mips32 = target->arch_info;
315 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
316 breakpoint_t *breakpoint = NULL;
317 u32 resume_pc;
318
319 if (target->state != TARGET_HALTED)
320 {
321 LOG_WARNING("target not halted");
322 return ERROR_TARGET_NOT_HALTED;
323 }
324
325 if (!debug_execution)
326 {
327 target_free_all_working_areas(target);
328 mips_m4k_enable_breakpoints(target);
329 mips_m4k_enable_watchpoints(target);
330 }
331
332 /* current = 1: continue on current pc, otherwise continue at <address> */
333 if (!current)
334 {
335 buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
336 mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
337 mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
338 }
339
340 resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
341
342 mips32_restore_context(target);
343
344 /* the front-end may request us not to handle breakpoints */
345 if (handle_breakpoints)
346 {
347 /* Single step past breakpoint at current address */
348 if ((breakpoint = breakpoint_find(target, resume_pc)))
349 {
350 LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
351 mips_m4k_unset_breakpoint(target, breakpoint);
352 //mips_m4k_single_step_core(target);
353 mips_m4k_set_breakpoint(target, breakpoint);
354 }
355 }
356
357 /* exit debug mode - enable interrupts if required */
358 mips_ejtag_exit_debug(ejtag_info, !debug_execution);
359
360 /* registers are now invalid */
361 mips32_invalidate_core_regs(target);
362
363 if (!debug_execution)
364 {
365 target->state = TARGET_RUNNING;
366 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
367 LOG_DEBUG("target resumed at 0x%x", resume_pc);
368 }
369 else
370 {
371 target->state = TARGET_DEBUG_RUNNING;
372 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
373 LOG_DEBUG("target debug resumed at 0x%x", resume_pc);
374 }
375
376 return ERROR_OK;
377 }
378
379 int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
380 {
381 /* get pointers to arch-specific information */
382 mips32_common_t *mips32 = target->arch_info;
383 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
384 breakpoint_t *breakpoint = NULL;
385
386 if (target->state != TARGET_HALTED)
387 {
388 LOG_WARNING("target not halted");
389 return ERROR_TARGET_NOT_HALTED;
390 }
391
392 /* current = 1: continue on current pc, otherwise continue at <address> */
393 if (!current)
394 buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
395
396 /* the front-end may request us not to handle breakpoints */
397 if (handle_breakpoints)
398 if ((breakpoint = breakpoint_find(target, buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32))))
399 mips_m4k_unset_breakpoint(target, breakpoint);
400
401 /* restore context */
402 mips32_restore_context(target);
403
404 /* configure single step mode */
405 mips_ejtag_config_step(ejtag_info, 1);
406
407 target->debug_reason = DBG_REASON_SINGLESTEP;
408
409 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
410
411 /* exit debug mode */
412 mips_ejtag_exit_debug(ejtag_info, 1);
413
414 /* registers are now invalid */
415 mips32_invalidate_core_regs(target);
416
417 if (breakpoint)
418 mips_m4k_set_breakpoint(target, breakpoint);
419
420 LOG_DEBUG("target stepped ");
421
422 mips_m4k_debug_entry(target);
423 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
424
425 return ERROR_OK;
426 }
427
428 void mips_m4k_enable_breakpoints(struct target_s *target)
429 {
430 breakpoint_t *breakpoint = target->breakpoints;
431
432 /* set any pending breakpoints */
433 while (breakpoint)
434 {
435 if (breakpoint->set == 0)
436 mips_m4k_set_breakpoint(target, breakpoint);
437 breakpoint = breakpoint->next;
438 }
439 }
440
441 int mips_m4k_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
442 {
443 /* TODO */
444 return ERROR_OK;
445 }
446
447 int mips_m4k_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
448 {
449 /* TODO */
450 return ERROR_OK;
451 }
452
453 int mips_m4k_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
454 {
455 /* TODO */
456 return ERROR_OK;
457 }
458
459 int mips_m4k_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
460 {
461 /* TODO */
462 return ERROR_OK;
463 }
464
465 int mips_m4k_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
466 {
467 /* TODO */
468 return ERROR_OK;
469 }
470
471 int mips_m4k_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
472 {
473 /* TODO */
474 return ERROR_OK;
475 }
476
477 int mips_m4k_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
478 {
479 /* TODO */
480 return ERROR_OK;
481 }
482
483 int mips_m4k_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
484 {
485 /* TODO */
486 return ERROR_OK;
487 }
488
489 void mips_m4k_enable_watchpoints(struct target_s *target)
490 {
491 watchpoint_t *watchpoint = target->watchpoints;
492
493 /* set any pending watchpoints */
494 while (watchpoint)
495 {
496 if (watchpoint->set == 0)
497 mips_m4k_set_watchpoint(target, watchpoint);
498 watchpoint = watchpoint->next;
499 }
500 }
501
502 int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
503 {
504 mips32_common_t *mips32 = target->arch_info;
505 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
506
507 LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
508
509 if (target->state != TARGET_HALTED)
510 {
511 LOG_WARNING("target not halted");
512 return ERROR_TARGET_NOT_HALTED;
513 }
514
515 /* sanitize arguments */
516 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
517 return ERROR_INVALID_ARGUMENTS;
518
519 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
520 return ERROR_TARGET_UNALIGNED_ACCESS;
521
522 switch (size)
523 {
524 case 4:
525 case 2:
526 case 1:
527 /* if noDMA off, use DMAACC mode for memory read */
528 if(ejtag_info->impcode & EJTAG_IMP_NODMA)
529 return mips32_pracc_read_mem(ejtag_info, address, size, count, (void *)buffer);
530 else
531 return mips32_dmaacc_read_mem(ejtag_info, address, size, count, (void *)buffer);
532 default:
533 LOG_ERROR("BUG: we shouldn't get here");
534 exit(-1);
535 break;
536 }
537
538 return ERROR_OK;
539 }
540
541 int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
542 {
543 mips32_common_t *mips32 = target->arch_info;
544 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
545
546 LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
547
548 if (target->state != TARGET_HALTED)
549 {
550 LOG_WARNING("target not halted");
551 return ERROR_TARGET_NOT_HALTED;
552 }
553
554 /* sanitize arguments */
555 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
556 return ERROR_INVALID_ARGUMENTS;
557
558 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
559 return ERROR_TARGET_UNALIGNED_ACCESS;
560
561 switch (size)
562 {
563 case 4:
564 case 2:
565 case 1:
566 /* if noDMA off, use DMAACC mode for memory write */
567 if(ejtag_info->impcode & EJTAG_IMP_NODMA)
568 mips32_pracc_write_mem(ejtag_info, address, size, count, (void *)buffer);
569 else
570 mips32_dmaacc_write_mem(ejtag_info, address, size, count, (void *)buffer);
571 break;
572 default:
573 LOG_ERROR("BUG: we shouldn't get here");
574 exit(-1);
575 break;
576 }
577
578 return ERROR_OK;
579 }
580
581 int mips_m4k_register_commands(struct command_context_s *cmd_ctx)
582 {
583 int retval;
584
585 retval = mips32_register_commands(cmd_ctx);
586 return retval;
587 }
588
589 int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
590 {
591 mips32_build_reg_cache(target);
592
593 return ERROR_OK;
594 }
595
596 int mips_m4k_quit(void)
597 {
598 return ERROR_OK;
599 }
600
601 int mips_m4k_init_arch_info(target_t *target, mips_m4k_common_t *mips_m4k, int chain_pos, const char *variant)
602 {
603 mips32_common_t *mips32 = &mips_m4k->mips32_common;
604
605 if (variant)
606 {
607 mips_m4k->variant = strdup(variant);
608 }
609 else
610 {
611 mips_m4k->variant = strdup("");
612 }
613
614 mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC;
615
616 /* initialize mips4k specific info */
617 mips32_init_arch_info(target, mips32, chain_pos, variant);
618 mips32->arch_info = mips_m4k;
619
620 return ERROR_OK;
621 }
622
623 int mips_m4k_target_create(struct target_s *target, Jim_Interp *interp)
624 {
625 mips_m4k_common_t *mips_m4k = calloc(1,sizeof(mips_m4k_common_t));
626
627 mips_m4k_init_arch_info(target, mips_m4k, target->chain_position, target->variant);
628
629 return ERROR_OK;
630 }
631
632 int mips_m4k_examine(struct target_s *target)
633 {
634 int retval;
635 mips32_common_t *mips32 = target->arch_info;
636 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
637 u32 idcode = 0;
638
639 target->type->examined = 1;
640
641 mips_ejtag_get_idcode(ejtag_info, &idcode, NULL);
642
643 if (((idcode >> 1) & 0x7FF) == 0x29)
644 {
645 /* we are using a pic32mx so select ejtag port
646 * as it is not selected by default */
647 mips_ejtag_set_instr(ejtag_info, 0x05, NULL);
648 LOG_DEBUG("PIC32MX Detected - using EJTAG Interface");
649 }
650
651 /* init rest of ejtag interface */
652 if ((retval = mips_ejtag_init(ejtag_info)) != ERROR_OK)
653 return retval;
654
655 return ERROR_OK;
656 }
657
658 int mips_m4k_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
659 {
660 return mips_m4k_write_memory(target, address, 4, count, buffer);
661 }

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)