- remove build warnings
[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 u32 ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST;
261 LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor...");
262 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
263 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
264 } else {
265 /* here we should issue a srst only, but we may have to assert trst as well */
266 if (jtag_reset_config & RESET_SRST_PULLS_TRST)
267 {
268 jtag_add_reset(1, 1);
269 }
270 else
271 {
272 jtag_add_reset(0, 1);
273 }
274 }
275
276 target->state = TARGET_RESET;
277 jtag_add_sleep(50000);
278
279 mips32_invalidate_core_regs(target);
280
281 if (target->reset_halt)
282 {
283 int retval;
284 if ((retval = target_halt(target))!=ERROR_OK)
285 return retval;
286 }
287
288
289 return ERROR_OK;
290 }
291
292 int mips_m4k_deassert_reset(target_t *target)
293 {
294 LOG_DEBUG("target->state: %s",
295 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
296
297 /* deassert reset lines */
298 jtag_add_reset(0, 0);
299
300 return ERROR_OK;
301 }
302
303 int mips_m4k_soft_reset_halt(struct target_s *target)
304 {
305 /* TODO */
306 return ERROR_OK;
307 }
308
309 int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
310 {
311 mips32_common_t *mips32 = target->arch_info;
312 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
313 breakpoint_t *breakpoint = NULL;
314 u32 resume_pc;
315
316 if (target->state != TARGET_HALTED)
317 {
318 LOG_WARNING("target not halted");
319 return ERROR_TARGET_NOT_HALTED;
320 }
321
322 if (!debug_execution)
323 {
324 target_free_all_working_areas(target);
325 mips_m4k_enable_breakpoints(target);
326 mips_m4k_enable_watchpoints(target);
327 }
328
329 /* current = 1: continue on current pc, otherwise continue at <address> */
330 if (!current)
331 {
332 buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
333 mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
334 mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
335 }
336
337 resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
338
339 mips32_restore_context(target);
340
341 /* the front-end may request us not to handle breakpoints */
342 if (handle_breakpoints)
343 {
344 /* Single step past breakpoint at current address */
345 if ((breakpoint = breakpoint_find(target, resume_pc)))
346 {
347 LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
348 mips_m4k_unset_breakpoint(target, breakpoint);
349 //mips_m4k_single_step_core(target);
350 mips_m4k_set_breakpoint(target, breakpoint);
351 }
352 }
353
354 /* exit debug mode - enable interrupts if required */
355 mips_ejtag_exit_debug(ejtag_info, !debug_execution);
356
357 /* registers are now invalid */
358 mips32_invalidate_core_regs(target);
359
360 if (!debug_execution)
361 {
362 target->state = TARGET_RUNNING;
363 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
364 LOG_DEBUG("target resumed at 0x%x", resume_pc);
365 }
366 else
367 {
368 target->state = TARGET_DEBUG_RUNNING;
369 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
370 LOG_DEBUG("target debug resumed at 0x%x", resume_pc);
371 }
372
373 return ERROR_OK;
374 }
375
376 int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
377 {
378 /* get pointers to arch-specific information */
379 mips32_common_t *mips32 = target->arch_info;
380 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
381 breakpoint_t *breakpoint = NULL;
382
383 if (target->state != TARGET_HALTED)
384 {
385 LOG_WARNING("target not halted");
386 return ERROR_TARGET_NOT_HALTED;
387 }
388
389 /* current = 1: continue on current pc, otherwise continue at <address> */
390 if (!current)
391 buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
392
393 /* the front-end may request us not to handle breakpoints */
394 if (handle_breakpoints)
395 if ((breakpoint = breakpoint_find(target, buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32))))
396 mips_m4k_unset_breakpoint(target, breakpoint);
397
398 /* restore context */
399 mips32_restore_context(target);
400
401 /* configure single step mode */
402 mips_ejtag_config_step(ejtag_info, 1);
403
404 target->debug_reason = DBG_REASON_SINGLESTEP;
405
406 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
407
408 /* exit debug mode */
409 mips_ejtag_exit_debug(ejtag_info, 1);
410
411 /* registers are now invalid */
412 mips32_invalidate_core_regs(target);
413
414 if (breakpoint)
415 mips_m4k_set_breakpoint(target, breakpoint);
416
417 LOG_DEBUG("target stepped ");
418
419 mips_m4k_debug_entry(target);
420 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
421
422 return ERROR_OK;
423 }
424
425 void mips_m4k_enable_breakpoints(struct target_s *target)
426 {
427 breakpoint_t *breakpoint = target->breakpoints;
428
429 /* set any pending breakpoints */
430 while (breakpoint)
431 {
432 if (breakpoint->set == 0)
433 mips_m4k_set_breakpoint(target, breakpoint);
434 breakpoint = breakpoint->next;
435 }
436 }
437
438 int mips_m4k_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
439 {
440 /* TODO */
441 return ERROR_OK;
442 }
443
444 int mips_m4k_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
445 {
446 /* TODO */
447 return ERROR_OK;
448 }
449
450 int mips_m4k_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
451 {
452 /* TODO */
453 return ERROR_OK;
454 }
455
456 int mips_m4k_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
457 {
458 /* TODO */
459 return ERROR_OK;
460 }
461
462 int mips_m4k_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
463 {
464 /* TODO */
465 return ERROR_OK;
466 }
467
468 int mips_m4k_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
469 {
470 /* TODO */
471 return ERROR_OK;
472 }
473
474 int mips_m4k_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
475 {
476 /* TODO */
477 return ERROR_OK;
478 }
479
480 int mips_m4k_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
481 {
482 /* TODO */
483 return ERROR_OK;
484 }
485
486 void mips_m4k_enable_watchpoints(struct target_s *target)
487 {
488 watchpoint_t *watchpoint = target->watchpoints;
489
490 /* set any pending watchpoints */
491 while (watchpoint)
492 {
493 if (watchpoint->set == 0)
494 mips_m4k_set_watchpoint(target, watchpoint);
495 watchpoint = watchpoint->next;
496 }
497 }
498
499 int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
500 {
501 mips32_common_t *mips32 = target->arch_info;
502 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
503
504 LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
505
506 if (target->state != TARGET_HALTED)
507 {
508 LOG_WARNING("target not halted");
509 return ERROR_TARGET_NOT_HALTED;
510 }
511
512 /* sanitize arguments */
513 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
514 return ERROR_INVALID_ARGUMENTS;
515
516 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
517 return ERROR_TARGET_UNALIGNED_ACCESS;
518
519 switch (size)
520 {
521 case 4:
522 case 2:
523 case 1:
524 /* if noDMA off, use DMAACC mode for memory read */
525 if(ejtag_info->impcode & (1<<14))
526 return mips32_pracc_read_mem(ejtag_info, address, size, count, (void *)buffer);
527 else
528 return mips32_dmaacc_read_mem(ejtag_info, address, size, count, (void *)buffer);
529 default:
530 LOG_ERROR("BUG: we shouldn't get here");
531 exit(-1);
532 break;
533 }
534
535 return ERROR_OK;
536 }
537
538 int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
539 {
540 mips32_common_t *mips32 = target->arch_info;
541 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
542
543 LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
544
545 if (target->state != TARGET_HALTED)
546 {
547 LOG_WARNING("target not halted");
548 return ERROR_TARGET_NOT_HALTED;
549 }
550
551 /* sanitize arguments */
552 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
553 return ERROR_INVALID_ARGUMENTS;
554
555 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
556 return ERROR_TARGET_UNALIGNED_ACCESS;
557
558 switch (size)
559 {
560 case 4:
561 case 2:
562 case 1:
563 /* if noDMA off, use DMAACC mode for memory write */
564 if(ejtag_info->impcode & (1<<14))
565 mips32_pracc_write_mem(ejtag_info, address, size, count, (void *)buffer);
566 else
567 mips32_dmaacc_write_mem(ejtag_info, address, size, count, (void *)buffer);
568 break;
569 default:
570 LOG_ERROR("BUG: we shouldn't get here");
571 exit(-1);
572 break;
573 }
574
575 return ERROR_OK;
576 }
577
578 int mips_m4k_register_commands(struct command_context_s *cmd_ctx)
579 {
580 int retval;
581
582 retval = mips32_register_commands(cmd_ctx);
583 return retval;
584 }
585
586 int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
587 {
588 mips32_build_reg_cache(target);
589
590 return ERROR_OK;
591 }
592
593 int mips_m4k_quit(void)
594 {
595 return ERROR_OK;
596 }
597
598 int mips_m4k_init_arch_info(target_t *target, mips_m4k_common_t *mips_m4k, int chain_pos, const char *variant)
599 {
600 mips32_common_t *mips32 = &mips_m4k->mips32_common;
601
602 if (variant)
603 {
604 mips_m4k->variant = strdup(variant);
605 }
606 else
607 {
608 mips_m4k->variant = strdup("");
609 }
610
611 mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC;
612
613 /* initialize mips4k specific info */
614 mips32_init_arch_info(target, mips32, chain_pos, variant);
615 mips32->arch_info = mips_m4k;
616
617 return ERROR_OK;
618 }
619
620 int mips_m4k_target_create(struct target_s *target, Jim_Interp *interp)
621 {
622 mips_m4k_common_t *mips_m4k = calloc(1,sizeof(mips_m4k_common_t));
623
624 mips_m4k_init_arch_info(target, mips_m4k, target->chain_position, target->variant);
625
626 return ERROR_OK;
627 }
628
629 int mips_m4k_examine(struct target_s *target)
630 {
631 int retval;
632 mips32_common_t *mips32 = target->arch_info;
633 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
634 u32 idcode = 0;
635
636 target->type->examined = 1;
637
638 mips_ejtag_get_idcode(ejtag_info, &idcode, NULL);
639
640 if (((idcode >> 1) & 0x7FF) == 0x29)
641 {
642 /* we are using a pic32mx so select ejtag port
643 * as it is not selected by default */
644 mips_ejtag_set_instr(ejtag_info, 0x05, NULL);
645 LOG_DEBUG("PIC32MX Detected - using EJTAG Interface");
646 }
647
648 /* init rest of ejtag interface */
649 if ((retval = mips_ejtag_init(ejtag_info)) != ERROR_OK)
650 return retval;
651
652 return ERROR_OK;
653 }
654
655 int mips_m4k_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
656 {
657 return mips_m4k_write_memory(target, address, 4, count, buffer);
658 }

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)