348a8652d6824ac4dfab0d3f6a2661902e493d07
[openocd.git] / src / flash / at91sam7.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
3 * lundin@mlu.mine.nu *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 /***************************************************************************
22 There are some things to notice
23
24 * AT91SAM7S64 is tested
25 * All AT91SAM7Sxx and AT91SAM7Xxx should work but is not tested
26 * All parameters are identified from onchip configuartion registers
27 *
28 * The flash controller handles erases automatically on a page (128/265 byte) basis
29 * Only an EraseAll command is supported by the controller
30 * Partial erases can be implemented in software by writing one 0xFFFFFFFF word to
31 * some location in every page in the region to be erased
32 *
33 * Lock regions (sectors) are 32 or 64 pages
34 *
35 ***************************************************************************/
36
37 #include "at91sam7.h"
38
39 #include "flash.h"
40 #include "target.h"
41 #include "log.h"
42 #include "binarybuffer.h"
43 #include "types.h"
44
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48
49 int at91sam7_register_commands(struct command_context_s *cmd_ctx);
50 int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
51 int at91sam7_erase(struct flash_bank_s *bank, int first, int last);
52 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last);
53 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
54 int at91sam7_probe(struct flash_bank_s *bank);
55 int at91sam7_erase_check(struct flash_bank_s *bank);
56 int at91sam7_protect_check(struct flash_bank_s *bank);
57 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size);
58
59 u32 at91sam7_get_flash_status(flash_bank_t *bank);
60 void at91sam7_set_flash_mode(flash_bank_t *bank,int mode);
61 u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout);
62 int at91sam7_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
63
64 flash_driver_t at91sam7_flash =
65 {
66 .name = "at91sam7",
67 .register_commands = at91sam7_register_commands,
68 .flash_bank_command = at91sam7_flash_bank_command,
69 .erase = at91sam7_erase,
70 .protect = at91sam7_protect,
71 .write = at91sam7_write,
72 .probe = at91sam7_probe,
73 .erase_check = at91sam7_erase_check,
74 .protect_check = at91sam7_protect_check,
75 .info = at91sam7_info
76 };
77
78
79 char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
80 long NVPSIZ[16] = {
81 0,
82 0x2000, /* 8K */
83 0x4000, /* 16K */
84 0x8000, /* 32K */
85 -1,
86 0x10000, /* 64K */
87 -1,
88 0x20000, /* 128K */
89 -1,
90 0x40000, /* 256K */
91 0x80000, /* 512K */
92 -1,
93 0x100000, /* 1024K */
94 -1,
95 0x200000, /* 2048K */
96 -1
97 };
98
99 long SRAMSIZ[16] = {
100 -1,
101 0x0400, /* 1K */
102 0x0800, /* 2K */
103 -1,
104 0x1c000, /* 112K */
105 0x1000, /* 4K */
106 0x14000, /* 80K */
107 0x28000, /* 160K */
108 0x2000, /* 8K */
109 0x4000, /* 16K */
110 0x8000, /* 32K */
111 0x10000, /* 64K */
112 0x20000, /* 128K */
113 0x40000, /* 256K */
114 0x18000, /* 96K */
115 0x80000, /* 512K */
116 };
117
118 u32 at91sam7_get_flash_status(flash_bank_t *bank)
119 {
120 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
121 target_t *target = at91sam7_info->target;
122 long fsr;
123
124 target->type->read_memory(target, MC_FSR, 4, 1, (u8 *)&fsr);
125
126 return fsr;
127 }
128
129 /* Setup the timimg registers for nvbits or normal flash */
130 void at91sam7_set_flash_mode(flash_bank_t *bank,int mode)
131 {
132 u32 fmcn, fmr;
133 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
134 target_t *target = at91sam7_info->target;
135
136 if (mode != at91sam7_info->flashmode) {
137 /* mainf contains the number of main clocks in approx 500uS */
138 if (mode==1)
139 /* main clocks in 1uS */
140 fmcn = (at91sam7_info->mainf>>9)+1;
141 else
142 /* main clocks in 1.5uS */
143 fmcn = (at91sam7_info->mainf>>9)+(at91sam7_info->mainf>>10)+1;
144 DEBUG("fmcn: %i", fmcn);
145 fmr = fmcn<<16;
146 target->type->write_memory(target, MC_FSR, 4, 1, (u8 *)&fmr);
147 at91sam7_info->flashmode = mode;
148 }
149 }
150
151 u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout)
152 {
153 u32 status;
154
155 while ((!((status = at91sam7_get_flash_status(bank)) & 0x01)) && (timeout-- > 0))
156 {
157 DEBUG("status: 0x%x", status);
158 usleep(1000);
159 }
160
161 DEBUG("status: 0x%x", status);
162
163 if (status&0x0C)
164 {
165 ERROR("status register: 0x%x", status);
166 if (status & 0x4)
167 ERROR("Lock Error Bit Detected, Operation Abort");
168 if (status & 0x8)
169 ERROR("Invalid command and/or bad keyword, Operation Abort");
170 if (status & 0x10)
171 ERROR("Security Bit Set, Operation Abort");
172 }
173
174 return status;
175 }
176
177 int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen)
178 {
179 u32 fcr;
180 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
181 target_t *target = at91sam7_info->target;
182
183 fcr = (0x5A<<24) | (pagen<<8) | cmd;
184 target->type->write_memory(target, MC_FCR, 4, 1, (u8 *)&fcr);
185 DEBUG("Flash command: 0x%x, pagenumber:", fcr, pagen);
186
187 if (at91sam7_wait_status_busy(bank, 10)&0x0C)
188 {
189 return ERROR_FLASH_OPERATION_FAILED;
190 }
191 return ERROR_OK;
192 }
193
194 /* Read device id register, main clock frequency register and fill in driver info structure */
195 int at91sam7_read_part_info(struct flash_bank_s *bank)
196 {
197 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
198 target_t *target = at91sam7_info->target;
199 unsigned long cidr, mcfr, status;
200
201 if (at91sam7_info->target->state != TARGET_HALTED)
202 {
203 return ERROR_TARGET_NOT_HALTED;
204 }
205
206 /* Read and parse chip identification register */
207 target->type->read_memory(target, DBGU_CIDR, 4, 1, (u8 *)&cidr);
208
209 if (cidr == 0)
210 {
211 WARNING("Cannot identify target as an AT91SAM");
212 return ERROR_FLASH_OPERATION_FAILED;
213 }
214
215 at91sam7_info->cidr = cidr;
216 at91sam7_info->cidr_ext = (cidr>>31)&0x0001;
217 at91sam7_info->cidr_nvptyp = (cidr>>28)&0x0007;
218 at91sam7_info->cidr_arch = (cidr>>20)&0x00FF;
219 at91sam7_info->cidr_sramsiz = (cidr>>16)&0x000F;
220 at91sam7_info->cidr_nvpsiz2 = (cidr>>12)&0x000F;
221 at91sam7_info->cidr_nvpsiz = (cidr>>8)&0x000F;
222 at91sam7_info->cidr_eproc = (cidr>>5)&0x0007;
223 at91sam7_info->cidr_version = cidr&0x001F;
224 bank->size = NVPSIZ[at91sam7_info->cidr_nvpsiz];
225
226 DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch );
227
228 /* Read main clock freqency register */
229 target->type->read_memory(target, CKGR_MCFR, 4, 1, (u8 *)&mcfr);
230 if (mcfr&0x10000)
231 {
232 at91sam7_info->mainrdy = 1;
233 at91sam7_info->mainf = mcfr&0xFFFF;
234 at91sam7_info->usec_clocks = mcfr>>9;
235 }
236 else
237 {
238 at91sam7_info->mainrdy = 0;
239 at91sam7_info->mainf = 0;
240 at91sam7_info->usec_clocks = 0;
241 }
242
243 status = at91sam7_get_flash_status(bank);
244 at91sam7_info->lockbits = status>>16;
245 at91sam7_info->securitybit = (status>>4)&0x01;
246
247 if (at91sam7_info->cidr_arch == 0x70 )
248 {
249 at91sam7_info->num_nvmbits = 2;
250 at91sam7_info->nvmbits = (status>>8)&0x03;
251 bank->base = 0x100000;
252 bank->bus_width = 4;
253 if (bank->size==0x40000) /* AT91SAM7S256 */
254 {
255 at91sam7_info->num_lockbits = 16;
256 at91sam7_info->pagesize = 256;
257 at91sam7_info->pages_in_lockregion = 64;
258 at91sam7_info->num_pages = 16*64;
259 }
260 if (bank->size==0x20000) /* AT91SAM7S128 */
261 {
262 at91sam7_info->num_lockbits = 8;
263 at91sam7_info->pagesize = 256;
264 at91sam7_info->pages_in_lockregion = 64;
265 at91sam7_info->num_pages = 8*64;
266 }
267 if (bank->size==0x10000) /* AT91SAM7S64 */
268 {
269 at91sam7_info->num_lockbits = 16;
270 at91sam7_info->pagesize = 128;
271 at91sam7_info->pages_in_lockregion = 32;
272 at91sam7_info->num_pages = 16*32;
273 }
274 if (bank->size==0x08000) /* AT91SAM7S321/32 */
275 {
276 at91sam7_info->num_lockbits = 8;
277 at91sam7_info->pagesize = 128;
278 at91sam7_info->pages_in_lockregion = 32;
279 at91sam7_info->num_pages = 8*32;
280 }
281
282 return ERROR_OK;
283 }
284
285 if (at91sam7_info->cidr_arch == 0x71 )
286 {
287 at91sam7_info->num_nvmbits = 2;
288 at91sam7_info->nvmbits = (status>>8)&0x03;
289 bank->base = 0x100000;
290 bank->bus_width = 4;
291 if (bank->size==0x40000) /* AT91SAM7XC256 */
292 {
293 at91sam7_info->num_lockbits = 16;
294 at91sam7_info->pagesize = 256;
295 at91sam7_info->pages_in_lockregion = 64;
296 at91sam7_info->num_pages = 16*64;
297 }
298 if (bank->size==0x20000) /* AT91SAM7XC128 */
299 {
300 at91sam7_info->num_lockbits = 8;
301 at91sam7_info->pagesize = 256;
302 at91sam7_info->pages_in_lockregion = 64;
303 at91sam7_info->num_pages = 8*64;
304 }
305
306 return ERROR_OK;
307 }
308
309 if (at91sam7_info->cidr_arch == 0x75 )
310 {
311 at91sam7_info->num_nvmbits = 3;
312 at91sam7_info->nvmbits = (status>>8)&0x07;
313 bank->base = 0x100000;
314 bank->bus_width = 4;
315 if (bank->size==0x40000) /* AT91SAM7X256 */
316 {
317 at91sam7_info->num_lockbits = 16;
318 at91sam7_info->pagesize = 256;
319 at91sam7_info->pages_in_lockregion = 64;
320 at91sam7_info->num_pages = 16*64;
321 }
322 if (bank->size==0x20000) /* AT91SAM7X128 */
323 {
324 at91sam7_info->num_lockbits = 8;
325 at91sam7_info->pagesize = 256;
326 at91sam7_info->pages_in_lockregion = 64;
327 at91sam7_info->num_pages = 8*64;
328 }
329
330 return ERROR_OK;
331 }
332
333 if (at91sam7_info->cidr_arch == 0x60 )
334 {
335 at91sam7_info->num_nvmbits = 3;
336 at91sam7_info->nvmbits = (status>>8)&0x07;
337 bank->base = 0x100000;
338 bank->bus_width = 4;
339
340 if (bank->size == 0x40000) /* AT91SAM7A3 */
341 {
342 at91sam7_info->num_lockbits = 16;
343 at91sam7_info->pagesize = 256;
344 at91sam7_info->pages_in_lockregion = 64;
345 at91sam7_info->num_pages = 16*64;
346 }
347 return ERROR_OK;
348 }
349
350 WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
351
352 return ERROR_OK;
353 }
354
355 int at91sam7_erase_check(struct flash_bank_s *bank)
356 {
357 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
358 target_t *target = at91sam7_info->target;
359 int i;
360
361 if (!at91sam7_info->working_area_size)
362 {
363 }
364 else
365 {
366 }
367
368 return ERROR_OK;
369 }
370
371 int at91sam7_protect_check(struct flash_bank_s *bank)
372 {
373 u32 status;
374
375 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
376 target_t *target = at91sam7_info->target;
377
378 if (at91sam7_info->cidr == 0)
379 {
380 at91sam7_read_part_info(bank);
381 }
382
383 if (at91sam7_info->cidr == 0)
384 {
385 WARNING("Cannot identify target as an AT91SAM");
386 return ERROR_FLASH_OPERATION_FAILED;
387 }
388
389 status = at91sam7_get_flash_status(bank);
390 at91sam7_info->lockbits = status>>16;
391
392 return ERROR_OK;
393 }
394
395
396 int at91sam7_register_commands(struct command_context_s *cmd_ctx)
397 {
398 command_t *at91sam7_cmd = register_command(cmd_ctx, NULL, "at91sam7", NULL, COMMAND_ANY, "at91sam7 specific commands");
399
400 return ERROR_OK;
401 }
402
403 int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
404 {
405 at91sam7_flash_bank_t *at91sam7_info;
406
407 if (argc < 6)
408 {
409 WARNING("incomplete flash_bank at91sam7 configuration");
410 return ERROR_FLASH_BANK_INVALID;
411 }
412
413 at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t));
414 bank->driver_priv = at91sam7_info;
415
416 at91sam7_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
417 if (!at91sam7_info->target)
418 {
419 ERROR("no target '%i' configured", args[5]);
420 exit(-1);
421 }
422
423
424 /* part wasn't probed for info yet */
425 at91sam7_info->cidr = 0;
426
427 return ERROR_OK;
428 }
429
430 int at91sam7_erase(struct flash_bank_s *bank, int first, int last)
431 {
432 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
433
434 if (at91sam7_info->target->state != TARGET_HALTED)
435 {
436 return ERROR_TARGET_NOT_HALTED;
437 }
438
439 if (at91sam7_info->cidr == 0)
440 {
441 at91sam7_read_part_info(bank);
442 }
443
444 if (at91sam7_info->cidr == 0)
445 {
446 WARNING("Cannot identify target as an AT91SAM");
447 return ERROR_FLASH_OPERATION_FAILED;
448 }
449
450 if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits))
451 {
452 return ERROR_FLASH_SECTOR_INVALID;
453 }
454
455 if ((first == 0) && (last == (at91sam7_info->num_lockbits-1)))
456 {
457 return at91sam7_flash_command(bank, EA, 0);
458 }
459
460 WARNING("Can only erase the whole flash area, pages are autoerased on write");
461 return ERROR_FLASH_OPERATION_FAILED;
462 }
463
464 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
465 {
466 u32 cmd, pagen, status;
467 int lockregion;
468
469 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
470 target_t *target = at91sam7_info->target;
471
472 if (at91sam7_info->target->state != TARGET_HALTED)
473 {
474 return ERROR_TARGET_NOT_HALTED;
475 }
476
477 if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits))
478 {
479 return ERROR_FLASH_SECTOR_INVALID;
480 }
481
482 if (at91sam7_info->cidr == 0)
483 {
484 at91sam7_read_part_info(bank);
485 }
486
487 if (at91sam7_info->cidr == 0)
488 {
489 WARNING("Cannot identify target as an AT91SAM");
490 return ERROR_FLASH_OPERATION_FAILED;
491 }
492
493 /* Configure the flash controller timing */
494 at91sam7_set_flash_mode(bank,1);
495
496 for (lockregion=first;lockregion<=last;lockregion++)
497 {
498 pagen = lockregion*at91sam7_info->pages_in_lockregion;
499 if (set)
500 cmd = SLB;
501 else
502 cmd = CLB;
503 if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
504 {
505 return ERROR_FLASH_OPERATION_FAILED;
506 }
507 }
508
509 status = at91sam7_get_flash_status(bank);
510 at91sam7_info->lockbits = status>>16;
511
512 return ERROR_OK;
513 }
514
515
516 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
517 {
518 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
519 target_t *target = at91sam7_info->target;
520 u32 dst_min_alignment, wcount, bytes_remaining = count;
521 u32 first_page, last_page, pagen, buffer_pos;
522 u32 fcr;
523
524 if (at91sam7_info->target->state != TARGET_HALTED)
525 {
526 return ERROR_TARGET_NOT_HALTED;
527 }
528
529 if (at91sam7_info->cidr == 0)
530 {
531 at91sam7_read_part_info(bank);
532 }
533
534 if (at91sam7_info->cidr == 0)
535 {
536 WARNING("Cannot identify target as an AT91SAM");
537 return ERROR_FLASH_OPERATION_FAILED;
538 }
539
540 if (offset + count > bank->size)
541 return ERROR_FLASH_DST_OUT_OF_BANK;
542
543 dst_min_alignment = at91sam7_info->pagesize;
544
545 if (offset % dst_min_alignment)
546 {
547 WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
548 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
549 }
550
551 if (offset + count > bank->size)
552 return ERROR_FLASH_DST_OUT_OF_BANK;
553
554 if (at91sam7_info->cidr_arch == 0)
555 return ERROR_FLASH_BANK_NOT_PROBED;
556
557 first_page = offset/dst_min_alignment;
558 last_page = CEIL(offset + count, dst_min_alignment);
559
560 DEBUG("first_page: %i, last_page: %i, count %i", first_page, last_page, count);
561
562 /* Configure the flash controller timing */
563 at91sam7_set_flash_mode(bank,2);
564
565 for (pagen=first_page; pagen<last_page; pagen++) {
566 if (bytes_remaining<dst_min_alignment)
567 count = bytes_remaining;
568 else
569 count = dst_min_alignment;
570 bytes_remaining -= count;
571
572 /* Write one block to the PageWriteBuffer */
573 buffer_pos = (pagen-first_page)*dst_min_alignment;
574 wcount = CEIL(count,4);
575 target->type->write_memory(target, bank->base, 4, wcount, buffer+buffer_pos);
576
577 /* Send Write Page command to Flash Controller */
578 if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
579 {
580 return ERROR_FLASH_OPERATION_FAILED;
581 }
582 DEBUG("Flash command: 0x%x, pagenumber:", fcr, pagen);
583 }
584
585 return ERROR_OK;
586 }
587
588
589 int at91sam7_probe(struct flash_bank_s *bank)
590 {
591 /* we can't probe on an at91sam7
592 * if this is an at91sam7, it has the configured flash
593 */
594 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
595
596 if (at91sam7_info->cidr == 0)
597 {
598 at91sam7_read_part_info(bank);
599 }
600
601 if (at91sam7_info->cidr == 0)
602 {
603 WARNING("Cannot identify target as an AT91SAM");
604 return ERROR_FLASH_OPERATION_FAILED;
605 }
606 return ERROR_OK;
607 }
608
609 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
610 {
611 int printed;
612 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
613
614 if (at91sam7_info->cidr == 0)
615 {
616 at91sam7_read_part_info(bank);
617 }
618
619 if (at91sam7_info->cidr == 0)
620 {
621 printed = snprintf(buf, buf_size, "Cannot identify target as an AT91SAM\n");
622 buf += printed;
623 buf_size -= printed;
624 return ERROR_FLASH_OPERATION_FAILED;
625 }
626
627 printed = snprintf(buf, buf_size, "\nat91sam7 information:\n");
628 buf += printed;
629 buf_size -= printed;
630
631 printed = snprintf(buf, buf_size, "cidr: 0x%8.8x, arch: 0x%4.4x, eproc: %s, version:0x%3.3x, flashsize: 0x%8.8x\n", at91sam7_info->cidr, at91sam7_info->cidr_arch, EPROC[at91sam7_info->cidr_eproc], at91sam7_info->cidr_version, bank->size);
632 buf += printed;
633 buf_size -= printed;
634
635 printed = snprintf(buf, buf_size, "main clock(estimated): %ikHz \n", at91sam7_info->mainf*2);
636 buf += printed;
637 buf_size -= printed;
638
639 if (at91sam7_info->num_lockbits>0) {
640 printed = snprintf(buf, buf_size, "pagesize: %i, lockbits: %i 0x%4.4x, pages in lock region: %i \n", at91sam7_info->pagesize, at91sam7_info->num_lockbits, at91sam7_info->lockbits,at91sam7_info->num_pages/at91sam7_info->num_lockbits);
641 buf += printed;
642 buf_size -= printed;
643 }
644
645 printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->nvmbits);
646 buf += printed;
647 buf_size -= printed;
648
649 return ERROR_OK;
650 }

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)