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 return ERROR_TARGET_NOT_HALTED
;
236 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVWPAR
), &retval
);
238 for (i
= 0; i
< bank
->num_sectors
; i
++)
240 if (retval
& str7x_info
->sector_bits
[i
])
241 bank
->sectors
[i
].is_protected
= 0;
243 bank
->sectors
[i
].is_protected
= 1;
249 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
)
251 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
252 target_t
*target
= bank
->target
;
259 if (bank
->target
->state
!= TARGET_HALTED
)
261 return ERROR_TARGET_NOT_HALTED
;
264 for (i
= first
; i
<= last
; i
++)
266 sectors
|= str7x_info
->sector_bits
[i
];
269 LOG_DEBUG("sectors: 0x%x", sectors
);
271 /* clear FLASH_ER register */
272 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
275 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
278 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
280 cmd
= FLASH_SER
|FLASH_WMS
;
281 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
283 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
287 retval
= str7x_result(bank
);
291 LOG_ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval
);
292 return ERROR_FLASH_OPERATION_FAILED
;
295 for (i
= first
; i
<= last
; i
++)
296 bank
->sectors
[i
].is_erased
= 1;
301 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
303 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
304 target_t
*target
= bank
->target
;
310 if (bank
->target
->state
!= TARGET_HALTED
)
312 return ERROR_TARGET_NOT_HALTED
;
315 protect_blocks
= 0xFFFFFFFF;
319 for (i
= first
; i
<= last
; i
++)
320 protect_blocks
&= ~(str7x_info
->sector_bits
[i
]);
323 /* clear FLASH_ER register */
324 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
327 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
329 cmd
= str7x_get_flash_adr(bank
, FLASH_NVWPAR
);
330 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), cmd
);
332 cmd
= protect_blocks
;
333 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), cmd
);
335 cmd
= FLASH_SPR
|FLASH_WMS
;
336 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
338 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
342 retval
= str7x_result(bank
);
344 LOG_DEBUG("retval: 0x%8.8x", retval
);
346 if (retval
& FLASH_ERER
)
347 return ERROR_FLASH_SECTOR_NOT_ERASED
;
348 else if (retval
& FLASH_WPF
)
349 return ERROR_FLASH_OPERATION_FAILED
;
354 int str7x_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
356 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
357 target_t
*target
= bank
->target
;
358 u32 buffer_size
= 8192;
359 working_area_t
*source
;
360 u32 address
= bank
->base
+ offset
;
361 reg_param_t reg_params
[6];
362 armv4_5_algorithm_t armv4_5_info
;
363 int retval
= ERROR_OK
;
365 u32 str7x_flash_write_code
[] = {
367 0xe3a04201, /* mov r4, #0x10000000 */
368 0xe5824000, /* str r4, [r2, #0x0] */
369 0xe5821010, /* str r1, [r2, #0x10] */
370 0xe4904004, /* ldr r4, [r0], #4 */
371 0xe5824008, /* str r4, [r2, #0x8] */
372 0xe4904004, /* ldr r4, [r0], #4 */
373 0xe582400c, /* str r4, [r2, #0xc] */
374 0xe3a04209, /* mov r4, #0x90000000 */
375 0xe5824000, /* str r4, [r2, #0x0] */
377 0xe5924000, /* ldr r4, [r2, #0x0] */
378 0xe1140005, /* tst r4, r5 */
379 0x1afffffc, /* bne busy */
380 0xe5924014, /* ldr r4, [r2, #0x14] */
381 0xe31400ff, /* tst r4, #0xff */
382 0x03140c01, /* tsteq r4, #0x100 */
383 0x1a000002, /* bne exit */
384 0xe2811008, /* add r1, r1, #0x8 */
385 0xe2533001, /* subs r3, r3, #1 */
386 0x1affffec, /* bne write */
388 0xeafffffe, /* b exit */
391 /* flash write code */
392 if (target_alloc_working_area(target
, 4 * 20, &str7x_info
->write_algorithm
) != ERROR_OK
)
394 LOG_WARNING("no working area available, can't do block memory writes");
395 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
398 target_write_buffer(target
, str7x_info
->write_algorithm
->address
, 20 * 4, (u8
*)str7x_flash_write_code
);
401 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
404 if (buffer_size
<= 256)
406 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
407 if (str7x_info
->write_algorithm
)
408 target_free_working_area(target
, str7x_info
->write_algorithm
);
410 LOG_WARNING("no large enough working area available, can't do block memory writes");
411 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
415 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
416 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
417 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
419 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
420 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
421 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
422 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
423 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
424 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
428 u32 thisrun_count
= (count
> (buffer_size
/ 8)) ? (buffer_size
/ 8) : count
;
430 target_write_buffer(target
, source
->address
, thisrun_count
* 8, buffer
);
432 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
433 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
434 buf_set_u32(reg_params
[2].value
, 0, 32, str7x_get_flash_adr(bank
, FLASH_CR0
));
435 buf_set_u32(reg_params
[3].value
, 0, 32, thisrun_count
);
436 buf_set_u32(reg_params
[5].value
, 0, 32, str7x_info
->busy_bits
);
438 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
)
440 LOG_ERROR("error executing str7x flash write algorithm");
441 retval
= ERROR_FLASH_OPERATION_FAILED
;
445 if (buf_get_u32(reg_params
[4].value
, 0, 32) != 0x00)
447 retval
= ERROR_FLASH_OPERATION_FAILED
;
451 buffer
+= thisrun_count
* 8;
452 address
+= thisrun_count
* 8;
453 count
-= thisrun_count
;
456 target_free_working_area(target
, source
);
457 target_free_working_area(target
, str7x_info
->write_algorithm
);
459 destroy_reg_param(®_params
[0]);
460 destroy_reg_param(®_params
[1]);
461 destroy_reg_param(®_params
[2]);
462 destroy_reg_param(®_params
[3]);
463 destroy_reg_param(®_params
[4]);
464 destroy_reg_param(®_params
[5]);
469 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
471 target_t
*target
= bank
->target
;
472 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
473 u32 dwords_remaining
= (count
/ 8);
474 u32 bytes_remaining
= (count
& 0x00000007);
475 u32 address
= bank
->base
+ offset
;
476 u32 bytes_written
= 0;
479 u32 check_address
= offset
;
482 if (bank
->target
->state
!= TARGET_HALTED
)
484 return ERROR_TARGET_NOT_HALTED
;
489 LOG_WARNING("offset 0x%x breaks required 8-byte alignment", offset
);
490 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
493 for (i
= 0; i
< bank
->num_sectors
; i
++)
495 u32 sec_start
= bank
->sectors
[i
].offset
;
496 u32 sec_end
= sec_start
+ bank
->sectors
[i
].size
;
498 /* check if destination falls within the current sector */
499 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
501 /* check if destination ends in the current sector */
502 if (offset
+ count
< sec_end
)
503 check_address
= offset
+ count
;
505 check_address
= sec_end
;
509 if (check_address
!= offset
+ count
)
510 return ERROR_FLASH_DST_OUT_OF_BANK
;
512 /* clear FLASH_ER register */
513 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
515 /* multiple dwords (8-byte) to be programmed? */
516 if (dwords_remaining
> 0)
518 /* try using a block write */
519 if ((retval
= str7x_write_block(bank
, buffer
, offset
, dwords_remaining
)) != ERROR_OK
)
521 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
523 /* if block write failed (no sufficient working area),
524 * we use normal (slow) single dword accesses */
525 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
527 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
529 /* if an error occured, we examine the reason, and quit */
530 retval
= str7x_result(bank
);
532 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
533 return ERROR_FLASH_OPERATION_FAILED
;
538 buffer
+= dwords_remaining
* 8;
539 address
+= dwords_remaining
* 8;
540 dwords_remaining
= 0;
544 while (dwords_remaining
> 0)
548 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
551 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
554 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, buffer
+ bytes_written
);
558 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, buffer
+ bytes_written
);
561 /* start programming cycle */
562 cmd
= FLASH_DWPG
| FLASH_WMS
;
563 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
565 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
570 retval
= str7x_result(bank
);
572 if (retval
& FLASH_PGER
)
573 return ERROR_FLASH_OPERATION_FAILED
;
574 else if (retval
& FLASH_WPF
)
575 return ERROR_FLASH_OPERATION_FAILED
;
583 u8 last_dword
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
586 while(bytes_remaining
> 0)
588 last_dword
[i
++] = *(buffer
+ bytes_written
);
595 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
598 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
601 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, last_dword
);
605 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, last_dword
+ 4);
608 /* start programming cycle */
609 cmd
= FLASH_DWPG
| FLASH_WMS
;
610 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
612 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
617 retval
= str7x_result(bank
);
619 if (retval
& FLASH_PGER
)
620 return ERROR_FLASH_OPERATION_FAILED
;
621 else if (retval
& FLASH_WPF
)
622 return ERROR_FLASH_OPERATION_FAILED
;
628 int str7x_probe(struct flash_bank_s
*bank
)
633 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
638 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
640 snprintf(buf
, buf_size
, "str7x flash driver info" );
644 int str7x_handle_disable_jtag_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
647 target_t
*target
= NULL
;
648 str7x_flash_bank_t
*str7x_info
= NULL
;
652 u16 ProtectionLevel
= 0;
657 command_print(cmd_ctx
, "str7x disable_jtag <bank>");
661 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
664 command_print(cmd_ctx
, "str7x disable_jtag <bank> ok");
668 str7x_info
= bank
->driver_priv
;
670 target
= bank
->target
;
672 if (target
->state
!= TARGET_HALTED
)
674 return ERROR_TARGET_NOT_HALTED
;
677 /* first we get protection status */
678 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR0
), &retval
);
680 if (!(retval
& str7x_info
->disable_bit
))
685 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR1
), &retval
);
686 ProtectionRegs
= ~(retval
>> 16);
688 while (((ProtectionRegs
) != 0) && (ProtectionLevel
< 16))
690 ProtectionRegs
>>= 1;
694 if (ProtectionLevel
== 0)
696 flash_cmd
= FLASH_SPR
;
697 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
698 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFB8);
699 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 0xFFFFFFFD);
700 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
701 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
705 flash_cmd
= FLASH_SPR
;
706 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
707 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFBC);
708 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), ~(1<<(15+ProtectionLevel
)));
709 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
710 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)