1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
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. *
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. *
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 ***************************************************************************/
27 #include "replacements.h"
34 #include "algorithm.h"
35 #include "binarybuffer.h"
41 str7x_mem_layout_t mem_layout_str7bank0
[] = {
42 {0x00000000, 0x02000, 0x01},
43 {0x00002000, 0x02000, 0x02},
44 {0x00004000, 0x02000, 0x04},
45 {0x00006000, 0x02000, 0x08},
46 {0x00008000, 0x08000, 0x10},
47 {0x00010000, 0x10000, 0x20},
48 {0x00020000, 0x10000, 0x40},
49 {0x00030000, 0x10000, 0x80}
52 str7x_mem_layout_t mem_layout_str7bank1
[] = {
53 {0x00000000, 0x02000, 0x10000},
54 {0x00002000, 0x02000, 0x20000}
57 int str7x_register_commands(struct command_context_s
*cmd_ctx
);
58 int str7x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
59 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
);
60 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
61 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
62 int str7x_probe(struct flash_bank_s
*bank
);
63 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
64 int str7x_protect_check(struct flash_bank_s
*bank
);
65 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
67 int str7x_handle_disable_jtag_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
69 flash_driver_t str7x_flash
=
72 .register_commands
= str7x_register_commands
,
73 .flash_bank_command
= str7x_flash_bank_command
,
75 .protect
= str7x_protect
,
78 .auto_probe
= str7x_probe
,
79 .erase_check
= default_flash_blank_check
,
80 .protect_check
= str7x_protect_check
,
84 int str7x_register_commands(struct command_context_s
*cmd_ctx
)
86 command_t
*str7x_cmd
= register_command(cmd_ctx
, NULL
, "str7x", NULL
, COMMAND_ANY
, NULL
);
88 register_command(cmd_ctx
, str7x_cmd
, "disable_jtag", str7x_handle_disable_jtag_command
, COMMAND_EXEC
,
89 "disable jtag access");
94 int str7x_get_flash_adr(struct flash_bank_s
*bank
, u32 reg
)
96 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
97 return (str7x_info
->register_base
| reg
);
100 int str7x_build_block_list(struct flash_bank_s
*bank
)
102 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
106 int b0_sectors
= 0, b1_sectors
= 0;
123 LOG_ERROR("BUG: unknown bank->size encountered");
127 num_sectors
= b0_sectors
+ b1_sectors
;
129 bank
->num_sectors
= num_sectors
;
130 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
131 str7x_info
->sector_bits
= malloc(sizeof(u32
) * num_sectors
);
135 for (i
= 0; i
< b0_sectors
; i
++)
137 bank
->sectors
[num_sectors
].offset
= mem_layout_str7bank0
[i
].sector_start
;
138 bank
->sectors
[num_sectors
].size
= mem_layout_str7bank0
[i
].sector_size
;
139 bank
->sectors
[num_sectors
].is_erased
= -1;
140 bank
->sectors
[num_sectors
].is_protected
= 1;
141 str7x_info
->sector_bits
[num_sectors
++] = mem_layout_str7bank0
[i
].sector_bit
;
144 for (i
= 0; i
< b1_sectors
; i
++)
146 bank
->sectors
[num_sectors
].offset
= mem_layout_str7bank1
[i
].sector_start
;
147 bank
->sectors
[num_sectors
].size
= mem_layout_str7bank1
[i
].sector_size
;
148 bank
->sectors
[num_sectors
].is_erased
= -1;
149 bank
->sectors
[num_sectors
].is_protected
= 1;
150 str7x_info
->sector_bits
[num_sectors
++] = mem_layout_str7bank1
[i
].sector_bit
;
156 /* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
158 int str7x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
160 str7x_flash_bank_t
*str7x_info
;
164 LOG_WARNING("incomplete flash_bank str7x configuration");
165 return ERROR_FLASH_BANK_INVALID
;
168 str7x_info
= malloc(sizeof(str7x_flash_bank_t
));
169 bank
->driver_priv
= str7x_info
;
171 /* set default bits for str71x flash */
172 str7x_info
->busy_bits
= (FLASH_LOCK
|FLASH_BSYA1
|FLASH_BSYA0
);
173 str7x_info
->disable_bit
= (1<<1);
175 if (strcmp(args
[6], "STR71x") == 0)
177 str7x_info
->register_base
= 0x40100000;
179 else if (strcmp(args
[6], "STR73x") == 0)
181 str7x_info
->register_base
= 0x80100000;
182 str7x_info
->busy_bits
= (FLASH_LOCK
|FLASH_BSYA0
);
184 else if (strcmp(args
[6], "STR75x") == 0)
186 str7x_info
->register_base
= 0x20100000;
187 str7x_info
->disable_bit
= (1<<0);
191 LOG_ERROR("unknown STR7x variant: '%s'", args
[6]);
193 return ERROR_FLASH_BANK_INVALID
;
196 str7x_build_block_list(bank
);
198 str7x_info
->write_algorithm
= NULL
;
203 u32
str7x_status(struct flash_bank_s
*bank
)
205 target_t
*target
= bank
->target
;
208 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), &retval
);
213 u32
str7x_result(struct flash_bank_s
*bank
)
215 target_t
*target
= bank
->target
;
218 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), &retval
);
223 int str7x_protect_check(struct flash_bank_s
*bank
)
225 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
226 target_t
*target
= bank
->target
;
231 if (bank
->target
->state
!= TARGET_HALTED
)
233 LOG_ERROR("Target not halted");
234 return ERROR_TARGET_NOT_HALTED
;
237 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVWPAR
), &retval
);
239 for (i
= 0; i
< bank
->num_sectors
; i
++)
241 if (retval
& str7x_info
->sector_bits
[i
])
242 bank
->sectors
[i
].is_protected
= 0;
244 bank
->sectors
[i
].is_protected
= 1;
250 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
)
252 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
253 target_t
*target
= bank
->target
;
260 if (bank
->target
->state
!= TARGET_HALTED
)
262 LOG_ERROR("Target not halted");
263 return ERROR_TARGET_NOT_HALTED
;
266 for (i
= first
; i
<= last
; i
++)
268 sectors
|= str7x_info
->sector_bits
[i
];
271 LOG_DEBUG("sectors: 0x%x", sectors
);
273 /* clear FLASH_ER register */
274 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
277 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
280 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
282 cmd
= FLASH_SER
|FLASH_WMS
;
283 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
285 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
289 retval
= str7x_result(bank
);
293 LOG_ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval
);
294 return ERROR_FLASH_OPERATION_FAILED
;
297 for (i
= first
; i
<= last
; i
++)
298 bank
->sectors
[i
].is_erased
= 1;
303 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
305 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
306 target_t
*target
= bank
->target
;
312 if (bank
->target
->state
!= TARGET_HALTED
)
314 LOG_ERROR("Target not halted");
315 return ERROR_TARGET_NOT_HALTED
;
318 protect_blocks
= 0xFFFFFFFF;
322 for (i
= first
; i
<= last
; i
++)
323 protect_blocks
&= ~(str7x_info
->sector_bits
[i
]);
326 /* clear FLASH_ER register */
327 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
330 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
332 cmd
= str7x_get_flash_adr(bank
, FLASH_NVWPAR
);
333 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), cmd
);
335 cmd
= protect_blocks
;
336 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), cmd
);
338 cmd
= FLASH_SPR
|FLASH_WMS
;
339 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
341 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
345 retval
= str7x_result(bank
);
347 LOG_DEBUG("retval: 0x%8.8x", retval
);
349 if (retval
& FLASH_ERER
)
350 return ERROR_FLASH_SECTOR_NOT_ERASED
;
351 else if (retval
& FLASH_WPF
)
352 return ERROR_FLASH_OPERATION_FAILED
;
357 int str7x_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
359 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
360 target_t
*target
= bank
->target
;
361 u32 buffer_size
= 8192;
362 working_area_t
*source
;
363 u32 address
= bank
->base
+ offset
;
364 reg_param_t reg_params
[6];
365 armv4_5_algorithm_t armv4_5_info
;
366 int retval
= ERROR_OK
;
368 u32 str7x_flash_write_code
[] = {
370 0xe3a04201, /* mov r4, #0x10000000 */
371 0xe5824000, /* str r4, [r2, #0x0] */
372 0xe5821010, /* str r1, [r2, #0x10] */
373 0xe4904004, /* ldr r4, [r0], #4 */
374 0xe5824008, /* str r4, [r2, #0x8] */
375 0xe4904004, /* ldr r4, [r0], #4 */
376 0xe582400c, /* str r4, [r2, #0xc] */
377 0xe3a04209, /* mov r4, #0x90000000 */
378 0xe5824000, /* str r4, [r2, #0x0] */
380 0xe5924000, /* ldr r4, [r2, #0x0] */
381 0xe1140005, /* tst r4, r5 */
382 0x1afffffc, /* bne busy */
383 0xe5924014, /* ldr r4, [r2, #0x14] */
384 0xe31400ff, /* tst r4, #0xff */
385 0x03140c01, /* tsteq r4, #0x100 */
386 0x1a000002, /* bne exit */
387 0xe2811008, /* add r1, r1, #0x8 */
388 0xe2533001, /* subs r3, r3, #1 */
389 0x1affffec, /* bne write */
391 0xeafffffe, /* b exit */
394 /* flash write code */
395 if (target_alloc_working_area(target
, 4 * 20, &str7x_info
->write_algorithm
) != ERROR_OK
)
397 LOG_WARNING("no working area available, can't do block memory writes");
398 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
401 target_write_buffer(target
, str7x_info
->write_algorithm
->address
, 20 * 4, (u8
*)str7x_flash_write_code
);
404 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
407 if (buffer_size
<= 256)
409 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
410 if (str7x_info
->write_algorithm
)
411 target_free_working_area(target
, str7x_info
->write_algorithm
);
413 LOG_WARNING("no large enough working area available, can't do block memory writes");
414 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
418 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
419 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
420 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
422 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
423 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
424 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
425 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
426 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
427 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
431 u32 thisrun_count
= (count
> (buffer_size
/ 8)) ? (buffer_size
/ 8) : count
;
433 target_write_buffer(target
, source
->address
, thisrun_count
* 8, buffer
);
435 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
436 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
437 buf_set_u32(reg_params
[2].value
, 0, 32, str7x_get_flash_adr(bank
, FLASH_CR0
));
438 buf_set_u32(reg_params
[3].value
, 0, 32, thisrun_count
);
439 buf_set_u32(reg_params
[5].value
, 0, 32, str7x_info
->busy_bits
);
441 if ((retval
= target
->type
->run_algorithm(target
, 0, NULL
, 6, reg_params
, str7x_info
->write_algorithm
->address
, str7x_info
->write_algorithm
->address
+ (19 * 4), 10000, &armv4_5_info
)) != ERROR_OK
)
443 LOG_ERROR("error executing str7x flash write algorithm");
444 retval
= ERROR_FLASH_OPERATION_FAILED
;
448 if (buf_get_u32(reg_params
[4].value
, 0, 32) != 0x00)
450 retval
= ERROR_FLASH_OPERATION_FAILED
;
454 buffer
+= thisrun_count
* 8;
455 address
+= thisrun_count
* 8;
456 count
-= thisrun_count
;
459 target_free_working_area(target
, source
);
460 target_free_working_area(target
, str7x_info
->write_algorithm
);
462 destroy_reg_param(®_params
[0]);
463 destroy_reg_param(®_params
[1]);
464 destroy_reg_param(®_params
[2]);
465 destroy_reg_param(®_params
[3]);
466 destroy_reg_param(®_params
[4]);
467 destroy_reg_param(®_params
[5]);
472 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
474 target_t
*target
= bank
->target
;
475 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
476 u32 dwords_remaining
= (count
/ 8);
477 u32 bytes_remaining
= (count
& 0x00000007);
478 u32 address
= bank
->base
+ offset
;
479 u32 bytes_written
= 0;
482 u32 check_address
= offset
;
485 if (bank
->target
->state
!= TARGET_HALTED
)
487 LOG_ERROR("Target not halted");
488 return ERROR_TARGET_NOT_HALTED
;
493 LOG_WARNING("offset 0x%x breaks required 8-byte alignment", offset
);
494 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
497 for (i
= 0; i
< bank
->num_sectors
; i
++)
499 u32 sec_start
= bank
->sectors
[i
].offset
;
500 u32 sec_end
= sec_start
+ bank
->sectors
[i
].size
;
502 /* check if destination falls within the current sector */
503 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
505 /* check if destination ends in the current sector */
506 if (offset
+ count
< sec_end
)
507 check_address
= offset
+ count
;
509 check_address
= sec_end
;
513 if (check_address
!= offset
+ count
)
514 return ERROR_FLASH_DST_OUT_OF_BANK
;
516 /* clear FLASH_ER register */
517 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
519 /* multiple dwords (8-byte) to be programmed? */
520 if (dwords_remaining
> 0)
522 /* try using a block write */
523 if ((retval
= str7x_write_block(bank
, buffer
, offset
, dwords_remaining
)) != ERROR_OK
)
525 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
527 /* if block write failed (no sufficient working area),
528 * we use normal (slow) single dword accesses */
529 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
531 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
533 /* if an error occured, we examine the reason, and quit */
534 retval
= str7x_result(bank
);
536 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
537 return ERROR_FLASH_OPERATION_FAILED
;
542 buffer
+= dwords_remaining
* 8;
543 address
+= dwords_remaining
* 8;
544 dwords_remaining
= 0;
548 while (dwords_remaining
> 0)
552 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
555 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
558 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, buffer
+ bytes_written
);
562 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, buffer
+ bytes_written
);
565 /* start programming cycle */
566 cmd
= FLASH_DWPG
| FLASH_WMS
;
567 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
569 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
574 retval
= str7x_result(bank
);
576 if (retval
& FLASH_PGER
)
577 return ERROR_FLASH_OPERATION_FAILED
;
578 else if (retval
& FLASH_WPF
)
579 return ERROR_FLASH_OPERATION_FAILED
;
587 u8 last_dword
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
590 while(bytes_remaining
> 0)
592 last_dword
[i
++] = *(buffer
+ bytes_written
);
599 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
602 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
605 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, last_dword
);
609 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, last_dword
+ 4);
612 /* start programming cycle */
613 cmd
= FLASH_DWPG
| FLASH_WMS
;
614 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
616 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
621 retval
= str7x_result(bank
);
623 if (retval
& FLASH_PGER
)
624 return ERROR_FLASH_OPERATION_FAILED
;
625 else if (retval
& FLASH_WPF
)
626 return ERROR_FLASH_OPERATION_FAILED
;
632 int str7x_probe(struct flash_bank_s
*bank
)
637 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
642 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
644 snprintf(buf
, buf_size
, "str7x flash driver info" );
648 int str7x_handle_disable_jtag_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
651 target_t
*target
= NULL
;
652 str7x_flash_bank_t
*str7x_info
= NULL
;
656 u16 ProtectionLevel
= 0;
661 command_print(cmd_ctx
, "str7x disable_jtag <bank>");
665 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
668 command_print(cmd_ctx
, "str7x disable_jtag <bank> ok");
672 str7x_info
= bank
->driver_priv
;
674 target
= bank
->target
;
676 if (target
->state
!= TARGET_HALTED
)
678 LOG_ERROR("Target not halted");
679 return ERROR_TARGET_NOT_HALTED
;
682 /* first we get protection status */
683 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR0
), &retval
);
685 if (!(retval
& str7x_info
->disable_bit
))
690 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR1
), &retval
);
691 ProtectionRegs
= ~(retval
>> 16);
693 while (((ProtectionRegs
) != 0) && (ProtectionLevel
< 16))
695 ProtectionRegs
>>= 1;
699 if (ProtectionLevel
== 0)
701 flash_cmd
= FLASH_SPR
;
702 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
703 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFB8);
704 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 0xFFFFFFFD);
705 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
706 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
710 flash_cmd
= FLASH_SPR
;
711 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
712 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFBC);
713 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), ~(1<<(15+ProtectionLevel
)));
714 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
715 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
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)