cb21d5f6addfe8b00a51008d5fa24dc54db5e4cb
[openocd.git] / src / target / arm720t.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2009 by Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "arm720t.h"
28 #include "time_support.h"
29 #include "target_type.h"
30
31
32 /*
33 * ARM720 is an ARM7TDMI-S with MMU and ETM7. For information, see
34 * ARM DDI 0229C especially Chapter 9 about debug support.
35 */
36
37 #if 0
38 #define _DEBUG_INSTRUCTION_EXECUTION_
39 #endif
40
41 static int arm720t_scan_cp15(target_t *target,
42 uint32_t out, uint32_t *in, int instruction, int clock)
43 {
44 int retval = ERROR_OK;
45 armv4_5_common_t *armv4_5 = target->arch_info;
46 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
47 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
48 scan_field_t fields[2];
49 uint8_t out_buf[4];
50 uint8_t instruction_buf = instruction;
51
52 buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
53
54 jtag_set_end_state(TAP_DRPAUSE);
55 if ((retval = arm_jtag_scann(jtag_info, 0xf)) != ERROR_OK)
56 {
57 return retval;
58 }
59 if ((retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL)) != ERROR_OK)
60 {
61 return retval;
62 }
63
64 fields[0].tap = jtag_info->tap;
65 fields[0].num_bits = 1;
66 fields[0].out_value = &instruction_buf;
67 fields[0].in_value = NULL;
68
69 fields[1].tap = jtag_info->tap;
70 fields[1].num_bits = 32;
71 fields[1].out_value = out_buf;
72 fields[1].in_value = NULL;
73
74 if (in)
75 {
76 fields[1].in_value = (uint8_t *)in;
77 jtag_add_dr_scan(2, fields, jtag_get_end_state());
78 jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
79 } else
80 {
81 jtag_add_dr_scan(2, fields, jtag_get_end_state());
82 }
83
84 if (clock)
85 jtag_add_runtest(0, jtag_get_end_state());
86
87 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
88 if ((retval = jtag_execute_queue()) != ERROR_OK)
89 {
90 return retval;
91 }
92
93 if (in)
94 LOG_DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
95 else
96 LOG_DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);
97 #else
98 LOG_DEBUG("out: %8.8" PRIx32 ", instruction: %i, clock: %i", out, instruction, clock);
99 #endif
100
101 return ERROR_OK;
102 }
103
104 static int arm720t_read_cp15(target_t *target, uint32_t opcode, uint32_t *value)
105 {
106 /* fetch CP15 opcode */
107 arm720t_scan_cp15(target, opcode, NULL, 1, 1);
108 /* "DECODE" stage */
109 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
110 /* "EXECUTE" stage (1) */
111 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
112 arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
113 /* "EXECUTE" stage (2) */
114 arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
115 /* "EXECUTE" stage (3), CDATA is read */
116 arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);
117
118 return ERROR_OK;
119 }
120
121 static int arm720t_write_cp15(target_t *target, uint32_t opcode, uint32_t value)
122 {
123 /* fetch CP15 opcode */
124 arm720t_scan_cp15(target, opcode, NULL, 1, 1);
125 /* "DECODE" stage */
126 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
127 /* "EXECUTE" stage (1) */
128 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
129 arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
130 /* "EXECUTE" stage (2) */
131 arm720t_scan_cp15(target, value, NULL, 0, 1);
132 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
133
134 return ERROR_OK;
135 }
136
137 static uint32_t arm720t_get_ttb(target_t *target)
138 {
139 uint32_t ttb = 0x0;
140
141 arm720t_read_cp15(target, 0xee120f10, &ttb);
142 jtag_execute_queue();
143
144 ttb &= 0xffffc000;
145
146 return ttb;
147 }
148
149 static void arm720t_disable_mmu_caches(target_t *target,
150 int mmu, int d_u_cache, int i_cache)
151 {
152 uint32_t cp15_control;
153
154 /* read cp15 control register */
155 arm720t_read_cp15(target, 0xee110f10, &cp15_control);
156 jtag_execute_queue();
157
158 if (mmu)
159 cp15_control &= ~0x1U;
160
161 if (d_u_cache || i_cache)
162 cp15_control &= ~0x4U;
163
164 arm720t_write_cp15(target, 0xee010f10, cp15_control);
165 }
166
167 static void arm720t_enable_mmu_caches(target_t *target,
168 int mmu, int d_u_cache, int i_cache)
169 {
170 uint32_t cp15_control;
171
172 /* read cp15 control register */
173 arm720t_read_cp15(target, 0xee110f10, &cp15_control);
174 jtag_execute_queue();
175
176 if (mmu)
177 cp15_control |= 0x1U;
178
179 if (d_u_cache || i_cache)
180 cp15_control |= 0x4U;
181
182 arm720t_write_cp15(target, 0xee010f10, cp15_control);
183 }
184
185 static void arm720t_post_debug_entry(target_t *target)
186 {
187 armv4_5_common_t *armv4_5 = target->arch_info;
188 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
189 arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
190 arm720t_common_t *arm720t = arm7tdmi->arch_info;
191
192 /* examine cp15 control reg */
193 arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);
194 jtag_execute_queue();
195 LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm720t->cp15_control_reg);
196
197 arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
198 arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
199 arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
200
201 /* save i/d fault status and address register */
202 arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
203 arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);
204 jtag_execute_queue();
205 }
206
207 static void arm720t_pre_restore_context(target_t *target)
208 {
209 armv4_5_common_t *armv4_5 = target->arch_info;
210 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
211 arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
212 arm720t_common_t *arm720t = arm7tdmi->arch_info;
213
214 /* restore i/d fault status and address register */
215 arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);
216 arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
217 }
218
219 static int arm720t_get_arch_pointers(target_t *target,
220 armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p,
221 arm7tdmi_common_t **arm7tdmi_p, arm720t_common_t **arm720t_p)
222 {
223 armv4_5_common_t *armv4_5 = target->arch_info;
224 arm7_9_common_t *arm7_9;
225 arm7tdmi_common_t *arm7tdmi;
226 arm720t_common_t *arm720t;
227
228 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
229 {
230 return -1;
231 }
232
233 arm7_9 = armv4_5->arch_info;
234 if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
235 {
236 return -1;
237 }
238
239 arm7tdmi = arm7_9->arch_info;
240 if (arm7tdmi->common_magic != ARM7TDMI_COMMON_MAGIC)
241 {
242 return -1;
243 }
244
245 arm720t = arm7tdmi->arch_info;
246 if (arm720t->common_magic != ARM720T_COMMON_MAGIC)
247 {
248 return -1;
249 }
250
251 *armv4_5_p = armv4_5;
252 *arm7_9_p = arm7_9;
253 *arm7tdmi_p = arm7tdmi;
254 *arm720t_p = arm720t;
255
256 return ERROR_OK;
257 }
258
259 static int arm720t_arch_state(struct target_s *target)
260 {
261 armv4_5_common_t *armv4_5 = target->arch_info;
262 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
263 arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
264 arm720t_common_t *arm720t = arm7tdmi->arch_info;
265
266 static const char *state[] =
267 {
268 "disabled", "enabled"
269 };
270
271 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
272 "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
273 "MMU: %s, Cache: %s",
274 armv4_5_state_strings[armv4_5->core_state],
275 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name ,
276 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
277 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
278 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
279 state[arm720t->armv4_5_mmu.mmu_enabled],
280 state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
281
282 return ERROR_OK;
283 }
284
285 static int arm720t_read_memory(struct target_s *target,
286 uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
287 {
288 int retval;
289 armv4_5_common_t *armv4_5 = target->arch_info;
290 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
291 arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
292 arm720t_common_t *arm720t = arm7tdmi->arch_info;
293
294 /* disable cache, but leave MMU enabled */
295 if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
296 arm720t_disable_mmu_caches(target, 0, 1, 0);
297
298 retval = arm7_9_read_memory(target, address, size, count, buffer);
299
300 if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
301 arm720t_enable_mmu_caches(target, 0, 1, 0);
302
303 return retval;
304 }
305
306 static int arm720t_read_phys_memory(struct target_s *target,
307 uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
308 {
309 armv4_5_common_t *armv4_5 = target->arch_info;
310 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
311 arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
312 arm720t_common_t *arm720t = arm7tdmi->arch_info;
313
314 return armv4_5_mmu_read_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
315 }
316
317 static int arm720t_write_phys_memory(struct target_s *target,
318 uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
319 {
320 armv4_5_common_t *armv4_5 = target->arch_info;
321 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
322 arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
323 arm720t_common_t *arm720t = arm7tdmi->arch_info;
324
325 return armv4_5_mmu_write_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
326 }
327
328 static int arm720t_soft_reset_halt(struct target_s *target)
329 {
330 int retval = ERROR_OK;
331 armv4_5_common_t *armv4_5 = target->arch_info;
332 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
333 arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
334 arm720t_common_t *arm720t = arm7tdmi->arch_info;
335 reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
336
337 if ((retval = target_halt(target)) != ERROR_OK)
338 {
339 return retval;
340 }
341
342 long long then = timeval_ms();
343 int timeout;
344 while (!(timeout = ((timeval_ms()-then) > 1000)))
345 {
346 if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
347 {
348 embeddedice_read_reg(dbg_stat);
349 if ((retval = jtag_execute_queue()) != ERROR_OK)
350 {
351 return retval;
352 }
353 } else
354 {
355 break;
356 }
357 if (debug_level >= 3)
358 {
359 alive_sleep(100);
360 } else
361 {
362 keep_alive();
363 }
364 }
365 if (timeout)
366 {
367 LOG_ERROR("Failed to halt CPU after 1 sec");
368 return ERROR_TARGET_TIMEOUT;
369 }
370
371 target->state = TARGET_HALTED;
372
373 /* SVC, ARM state, IRQ and FIQ disabled */
374 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
375 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
376 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
377
378 /* start fetching from 0x0 */
379 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
380 armv4_5->core_cache->reg_list[15].dirty = 1;
381 armv4_5->core_cache->reg_list[15].valid = 1;
382
383 armv4_5->core_mode = ARMV4_5_MODE_SVC;
384 armv4_5->core_state = ARMV4_5_STATE_ARM;
385
386 arm720t_disable_mmu_caches(target, 1, 1, 1);
387 arm720t->armv4_5_mmu.mmu_enabled = 0;
388 arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
389 arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
390
391 if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
392 {
393 return retval;
394 }
395
396 return ERROR_OK;
397 }
398
399 static int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
400 {
401 return arm7tdmi_init_target(cmd_ctx, target);
402 }
403
404 static int arm720t_init_arch_info(target_t *target,
405 arm720t_common_t *arm720t, jtag_tap_t *tap)
406 {
407 arm7tdmi_common_t *arm7tdmi = &arm720t->arm7tdmi_common;
408 arm7_9_common_t *arm7_9 = &arm7tdmi->arm7_9_common;
409
410 arm7tdmi_init_arch_info(target, arm7tdmi, tap);
411
412 arm7tdmi->arch_info = arm720t;
413 arm720t->common_magic = ARM720T_COMMON_MAGIC;
414
415 arm7_9->post_debug_entry = arm720t_post_debug_entry;
416 arm7_9->pre_restore_context = arm720t_pre_restore_context;
417
418 arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;
419 arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;
420 arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;
421 arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;
422 arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
423 arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
424 arm720t->armv4_5_mmu.has_tiny_pages = 0;
425 arm720t->armv4_5_mmu.mmu_enabled = 0;
426
427 return ERROR_OK;
428 }
429
430 static int arm720t_target_create(struct target_s *target, Jim_Interp *interp)
431 {
432 arm720t_common_t *arm720t = calloc(1,sizeof(arm720t_common_t));
433
434 return arm720t_init_arch_info(target, arm720t, target->tap);
435 }
436
437 static int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx,
438 char *cmd, char **args, int argc)
439 {
440 int retval;
441 target_t *target = get_current_target(cmd_ctx);
442 armv4_5_common_t *armv4_5;
443 arm7_9_common_t *arm7_9;
444 arm7tdmi_common_t *arm7tdmi;
445 arm720t_common_t *arm720t;
446 arm_jtag_t *jtag_info;
447
448 if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
449 {
450 command_print(cmd_ctx, "current target isn't an ARM720t target");
451 return ERROR_OK;
452 }
453
454 jtag_info = &arm7_9->jtag_info;
455
456 if (target->state != TARGET_HALTED)
457 {
458 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
459 return ERROR_OK;
460 }
461
462 /* one or more argument, access a single register (write if second argument is given */
463 if (argc >= 1)
464 {
465 uint32_t opcode;
466 COMMAND_PARSE_NUMBER(u32, args[0], opcode);
467
468 if (argc == 1)
469 {
470 uint32_t value;
471 if ((retval = arm720t_read_cp15(target, opcode, &value)) != ERROR_OK)
472 {
473 command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
474 return ERROR_OK;
475 }
476
477 if ((retval = jtag_execute_queue()) != ERROR_OK)
478 {
479 return retval;
480 }
481
482 command_print(cmd_ctx, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
483 }
484 else if (argc == 2)
485 {
486 uint32_t value;
487 COMMAND_PARSE_NUMBER(u32, args[1], value);
488
489 if ((retval = arm720t_write_cp15(target, opcode, value)) != ERROR_OK)
490 {
491 command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
492 return ERROR_OK;
493 }
494 command_print(cmd_ctx, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
495 }
496 }
497
498 return ERROR_OK;
499 }
500
501 static int arm720t_mrc(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
502 {
503 if (cpnum!=15)
504 {
505 LOG_ERROR("Only cp15 is supported");
506 return ERROR_FAIL;
507 }
508
509 return arm720t_read_cp15(target, mrc_opcode(cpnum, op1, op2, CRn, CRm), value);
510
511 }
512
513 static int arm720t_mcr(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
514 {
515 if (cpnum!=15)
516 {
517 LOG_ERROR("Only cp15 is supported");
518 return ERROR_FAIL;
519 }
520
521 return arm720t_write_cp15(target, mrc_opcode(cpnum, op1, op2, CRn, CRm), value);
522 }
523
524 static int arm720t_register_commands(struct command_context_s *cmd_ctx)
525 {
526 int retval;
527 command_t *arm720t_cmd;
528
529
530 retval = arm7_9_register_commands(cmd_ctx);
531
532 arm720t_cmd = register_command(cmd_ctx, NULL, "arm720t",
533 NULL, COMMAND_ANY,
534 "arm720t specific commands");
535
536 register_command(cmd_ctx, arm720t_cmd, "cp15",
537 arm720t_handle_cp15_command, COMMAND_EXEC,
538 "display/modify cp15 register <opcode> [value]");
539
540 return ERROR_OK;
541 }
542
543 /** Holds methods for ARM720 targets. */
544 target_type_t arm720t_target =
545 {
546 .name = "arm720t",
547
548 .poll = arm7_9_poll,
549 .arch_state = arm720t_arch_state,
550
551 .halt = arm7_9_halt,
552 .resume = arm7_9_resume,
553 .step = arm7_9_step,
554
555 .assert_reset = arm7_9_assert_reset,
556 .deassert_reset = arm7_9_deassert_reset,
557 .soft_reset_halt = arm720t_soft_reset_halt,
558
559 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
560
561 .read_memory = arm720t_read_memory,
562 .write_memory = arm7_9_write_memory,
563 .read_phys_memory = arm720t_read_phys_memory,
564 .write_phys_memory = arm720t_write_phys_memory,
565 .bulk_write_memory = arm7_9_bulk_write_memory,
566 .checksum_memory = arm7_9_checksum_memory,
567 .blank_check_memory = arm7_9_blank_check_memory,
568
569 .run_algorithm = armv4_5_run_algorithm,
570
571 .add_breakpoint = arm7_9_add_breakpoint,
572 .remove_breakpoint = arm7_9_remove_breakpoint,
573 .add_watchpoint = arm7_9_add_watchpoint,
574 .remove_watchpoint = arm7_9_remove_watchpoint,
575
576 .register_commands = arm720t_register_commands,
577 .target_create = arm720t_target_create,
578 .init_target = arm720t_init_target,
579 .examine = arm7tdmi_examine,
580 .mrc = arm720t_mrc,
581 .mcr = arm720t_mcr,
582
583 };

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)