drivers/kitprog: workaround KitProg firmware bug of missing ZLP
[openocd.git] / src / flash / nor / nrf5.c
1 /***************************************************************************
2 * Copyright (C) 2013 Synapse Product Development *
3 * Andrey Smirnov <andrew.smironv@gmail.com> *
4 * Angus Gratton <gus@projectgus.com> *
5 * Erdem U. Altunyurt <spamjunkeater@gmail.com> *
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, see <http://www.gnu.org/licenses/>. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "imp.h"
26 #include <target/algorithm.h>
27 #include <target/armv7m.h>
28 #include <helper/types.h>
29
30 enum {
31 NRF5_FLASH_BASE = 0x00000000,
32 };
33
34 enum nrf5_ficr_registers {
35 NRF5_FICR_BASE = 0x10000000, /* Factory Information Configuration Registers */
36
37 #define NRF5_FICR_REG(offset) (NRF5_FICR_BASE + offset)
38
39 NRF5_FICR_CODEPAGESIZE = NRF5_FICR_REG(0x010),
40 NRF5_FICR_CODESIZE = NRF5_FICR_REG(0x014),
41 NRF5_FICR_CLENR0 = NRF5_FICR_REG(0x028),
42 NRF5_FICR_PPFC = NRF5_FICR_REG(0x02C),
43 NRF5_FICR_NUMRAMBLOCK = NRF5_FICR_REG(0x034),
44 NRF5_FICR_SIZERAMBLOCK0 = NRF5_FICR_REG(0x038),
45 NRF5_FICR_SIZERAMBLOCK1 = NRF5_FICR_REG(0x03C),
46 NRF5_FICR_SIZERAMBLOCK2 = NRF5_FICR_REG(0x040),
47 NRF5_FICR_SIZERAMBLOCK3 = NRF5_FICR_REG(0x044),
48 NRF5_FICR_CONFIGID = NRF5_FICR_REG(0x05C),
49 NRF5_FICR_DEVICEID0 = NRF5_FICR_REG(0x060),
50 NRF5_FICR_DEVICEID1 = NRF5_FICR_REG(0x064),
51 NRF5_FICR_ER0 = NRF5_FICR_REG(0x080),
52 NRF5_FICR_ER1 = NRF5_FICR_REG(0x084),
53 NRF5_FICR_ER2 = NRF5_FICR_REG(0x088),
54 NRF5_FICR_ER3 = NRF5_FICR_REG(0x08C),
55 NRF5_FICR_IR0 = NRF5_FICR_REG(0x090),
56 NRF5_FICR_IR1 = NRF5_FICR_REG(0x094),
57 NRF5_FICR_IR2 = NRF5_FICR_REG(0x098),
58 NRF5_FICR_IR3 = NRF5_FICR_REG(0x09C),
59 NRF5_FICR_DEVICEADDRTYPE = NRF5_FICR_REG(0x0A0),
60 NRF5_FICR_DEVICEADDR0 = NRF5_FICR_REG(0x0A4),
61 NRF5_FICR_DEVICEADDR1 = NRF5_FICR_REG(0x0A8),
62 NRF5_FICR_OVERRIDEN = NRF5_FICR_REG(0x0AC),
63 NRF5_FICR_NRF_1MBIT0 = NRF5_FICR_REG(0x0B0),
64 NRF5_FICR_NRF_1MBIT1 = NRF5_FICR_REG(0x0B4),
65 NRF5_FICR_NRF_1MBIT2 = NRF5_FICR_REG(0x0B8),
66 NRF5_FICR_NRF_1MBIT3 = NRF5_FICR_REG(0x0BC),
67 NRF5_FICR_NRF_1MBIT4 = NRF5_FICR_REG(0x0C0),
68 NRF5_FICR_BLE_1MBIT0 = NRF5_FICR_REG(0x0EC),
69 NRF5_FICR_BLE_1MBIT1 = NRF5_FICR_REG(0x0F0),
70 NRF5_FICR_BLE_1MBIT2 = NRF5_FICR_REG(0x0F4),
71 NRF5_FICR_BLE_1MBIT3 = NRF5_FICR_REG(0x0F8),
72 NRF5_FICR_BLE_1MBIT4 = NRF5_FICR_REG(0x0FC),
73 };
74
75 enum nrf5_uicr_registers {
76 NRF5_UICR_BASE = 0x10001000, /* User Information
77 * Configuration Regsters */
78
79 NRF5_UICR_SIZE = 0x100,
80
81 #define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset)
82
83 NRF5_UICR_CLENR0 = NRF5_UICR_REG(0x000),
84 NRF5_UICR_RBPCONF = NRF5_UICR_REG(0x004),
85 NRF5_UICR_XTALFREQ = NRF5_UICR_REG(0x008),
86 NRF5_UICR_FWID = NRF5_UICR_REG(0x010),
87 };
88
89 enum nrf5_nvmc_registers {
90 NRF5_NVMC_BASE = 0x4001E000, /* Non-Volatile Memory
91 * Controller Regsters */
92
93 #define NRF5_NVMC_REG(offset) (NRF5_NVMC_BASE + offset)
94
95 NRF5_NVMC_READY = NRF5_NVMC_REG(0x400),
96 NRF5_NVMC_CONFIG = NRF5_NVMC_REG(0x504),
97 NRF5_NVMC_ERASEPAGE = NRF5_NVMC_REG(0x508),
98 NRF5_NVMC_ERASEALL = NRF5_NVMC_REG(0x50C),
99 NRF5_NVMC_ERASEUICR = NRF5_NVMC_REG(0x514),
100 };
101
102 enum nrf5_nvmc_config_bits {
103 NRF5_NVMC_CONFIG_REN = 0x00,
104 NRF5_NVMC_CONFIG_WEN = 0x01,
105 NRF5_NVMC_CONFIG_EEN = 0x02,
106
107 };
108
109 struct nrf5_info {
110 uint32_t code_page_size;
111
112 struct {
113 bool probed;
114 int (*write) (struct flash_bank *bank,
115 struct nrf5_info *chip,
116 const uint8_t *buffer, uint32_t offset, uint32_t count);
117 } bank[2];
118 struct target *target;
119 };
120
121 struct nrf5_device_spec {
122 uint16_t hwid;
123 const char *part;
124 const char *variant;
125 const char *build_code;
126 unsigned int flash_size_kb;
127 };
128
129 #define NRF5_DEVICE_DEF(id, pt, var, bcode, fsize) \
130 { \
131 .hwid = (id), \
132 .part = pt, \
133 .variant = var, \
134 .build_code = bcode, \
135 .flash_size_kb = (fsize), \
136 }
137
138 /* The known devices table below is derived from the "nRF51 Series
139 * Compatibility Matrix" document, which can be found by searching for
140 * ATTN-51 on the Nordic Semi website:
141 *
142 * http://www.nordicsemi.com/eng/content/search?SearchText=ATTN-51
143 *
144 * Up to date with Matrix v2.0, plus some additional HWIDs.
145 *
146 * The additional HWIDs apply where the build code in the matrix is
147 * shown as Gx0, Bx0, etc. In these cases the HWID in the matrix is
148 * for x==0, x!=0 means different (unspecified) HWIDs.
149 */
150 static const struct nrf5_device_spec nrf5_known_devices_table[] = {
151 /* nRF51822 Devices (IC rev 1). */
152 NRF5_DEVICE_DEF(0x001D, "51822", "QFAA", "CA/C0", 256),
153 NRF5_DEVICE_DEF(0x0026, "51822", "QFAB", "AA", 128),
154 NRF5_DEVICE_DEF(0x0027, "51822", "QFAB", "A0", 128),
155 NRF5_DEVICE_DEF(0x0020, "51822", "CEAA", "BA", 256),
156 NRF5_DEVICE_DEF(0x002F, "51822", "CEAA", "B0", 256),
157
158 /* nRF51822 Devices (IC rev 2). */
159 NRF5_DEVICE_DEF(0x002A, "51822", "QFAA", "FA0", 256),
160 NRF5_DEVICE_DEF(0x0044, "51822", "QFAA", "GC0", 256),
161 NRF5_DEVICE_DEF(0x003C, "51822", "QFAA", "G0", 256),
162 NRF5_DEVICE_DEF(0x0057, "51822", "QFAA", "G2", 256),
163 NRF5_DEVICE_DEF(0x0058, "51822", "QFAA", "G3", 256),
164 NRF5_DEVICE_DEF(0x004C, "51822", "QFAB", "B0", 128),
165 NRF5_DEVICE_DEF(0x0040, "51822", "CEAA", "CA0", 256),
166 NRF5_DEVICE_DEF(0x0047, "51822", "CEAA", "DA0", 256),
167 NRF5_DEVICE_DEF(0x004D, "51822", "CEAA", "D00", 256),
168
169 /* nRF51822 Devices (IC rev 3). */
170 NRF5_DEVICE_DEF(0x0072, "51822", "QFAA", "H0", 256),
171 NRF5_DEVICE_DEF(0x00D1, "51822", "QFAA", "H2", 256),
172 NRF5_DEVICE_DEF(0x007B, "51822", "QFAB", "C0", 128),
173 NRF5_DEVICE_DEF(0x0083, "51822", "QFAC", "A0", 256),
174 NRF5_DEVICE_DEF(0x0084, "51822", "QFAC", "A1", 256),
175 NRF5_DEVICE_DEF(0x007D, "51822", "CDAB", "A0", 128),
176 NRF5_DEVICE_DEF(0x0079, "51822", "CEAA", "E0", 256),
177 NRF5_DEVICE_DEF(0x0087, "51822", "CFAC", "A0", 256),
178
179 /* nRF51422 Devices (IC rev 1). */
180 NRF5_DEVICE_DEF(0x001E, "51422", "QFAA", "CA", 256),
181 NRF5_DEVICE_DEF(0x0024, "51422", "QFAA", "C0", 256),
182 NRF5_DEVICE_DEF(0x0031, "51422", "CEAA", "A0A", 256),
183
184 /* nRF51422 Devices (IC rev 2). */
185 NRF5_DEVICE_DEF(0x002D, "51422", "QFAA", "DAA", 256),
186 NRF5_DEVICE_DEF(0x002E, "51422", "QFAA", "E0", 256),
187 NRF5_DEVICE_DEF(0x0061, "51422", "QFAB", "A00", 128),
188 NRF5_DEVICE_DEF(0x0050, "51422", "CEAA", "B0", 256),
189
190 /* nRF51422 Devices (IC rev 3). */
191 NRF5_DEVICE_DEF(0x0073, "51422", "QFAA", "F0", 256),
192 NRF5_DEVICE_DEF(0x007C, "51422", "QFAB", "B0", 128),
193 NRF5_DEVICE_DEF(0x0085, "51422", "QFAC", "A0", 256),
194 NRF5_DEVICE_DEF(0x0086, "51422", "QFAC", "A1", 256),
195 NRF5_DEVICE_DEF(0x007E, "51422", "CDAB", "A0", 128),
196 NRF5_DEVICE_DEF(0x007A, "51422", "CEAA", "C0", 256),
197 NRF5_DEVICE_DEF(0x0088, "51422", "CFAC", "A0", 256),
198
199 /* nRF52832 Devices */
200 NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0", 512),
201
202 /* Some early nRF51-DK (PCA10028) & nRF51-Dongle (PCA10031) boards
203 with built-in jlink seem to use engineering samples not listed
204 in the nRF51 Series Compatibility Matrix V1.0. */
205 NRF5_DEVICE_DEF(0x0071, "51822", "QFAC", "AB", 256),
206 };
207
208 static int nrf5_bank_is_probed(struct flash_bank *bank)
209 {
210 struct nrf5_info *chip = bank->driver_priv;
211
212 assert(chip != NULL);
213
214 return chip->bank[bank->bank_number].probed;
215 }
216 static int nrf5_probe(struct flash_bank *bank);
217
218 static int nrf5_get_probed_chip_if_halted(struct flash_bank *bank, struct nrf5_info **chip)
219 {
220 if (bank->target->state != TARGET_HALTED) {
221 LOG_ERROR("Target not halted");
222 return ERROR_TARGET_NOT_HALTED;
223 }
224
225 *chip = bank->driver_priv;
226
227 int probed = nrf5_bank_is_probed(bank);
228 if (probed < 0)
229 return probed;
230 else if (!probed)
231 return nrf5_probe(bank);
232 else
233 return ERROR_OK;
234 }
235
236 static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
237 {
238 uint32_t ready;
239 int res;
240 int timeout = 100;
241
242 do {
243 res = target_read_u32(chip->target, NRF5_NVMC_READY, &ready);
244 if (res != ERROR_OK) {
245 LOG_ERROR("Couldn't read NVMC_READY register");
246 return res;
247 }
248
249 if (ready == 0x00000001)
250 return ERROR_OK;
251
252 alive_sleep(1);
253 } while (timeout--);
254
255 LOG_DEBUG("Timed out waiting for NVMC_READY");
256 return ERROR_FLASH_BUSY;
257 }
258
259 static int nrf5_nvmc_erase_enable(struct nrf5_info *chip)
260 {
261 int res;
262 res = target_write_u32(chip->target,
263 NRF5_NVMC_CONFIG,
264 NRF5_NVMC_CONFIG_EEN);
265
266 if (res != ERROR_OK) {
267 LOG_ERROR("Failed to enable erase operation");
268 return res;
269 }
270
271 /*
272 According to NVMC examples in Nordic SDK busy status must be
273 checked after writing to NVMC_CONFIG
274 */
275 res = nrf5_wait_for_nvmc(chip);
276 if (res != ERROR_OK)
277 LOG_ERROR("Erase enable did not complete");
278
279 return res;
280 }
281
282 static int nrf5_nvmc_write_enable(struct nrf5_info *chip)
283 {
284 int res;
285 res = target_write_u32(chip->target,
286 NRF5_NVMC_CONFIG,
287 NRF5_NVMC_CONFIG_WEN);
288
289 if (res != ERROR_OK) {
290 LOG_ERROR("Failed to enable write operation");
291 return res;
292 }
293
294 /*
295 According to NVMC examples in Nordic SDK busy status must be
296 checked after writing to NVMC_CONFIG
297 */
298 res = nrf5_wait_for_nvmc(chip);
299 if (res != ERROR_OK)
300 LOG_ERROR("Write enable did not complete");
301
302 return res;
303 }
304
305 static int nrf5_nvmc_read_only(struct nrf5_info *chip)
306 {
307 int res;
308 res = target_write_u32(chip->target,
309 NRF5_NVMC_CONFIG,
310 NRF5_NVMC_CONFIG_REN);
311
312 if (res != ERROR_OK) {
313 LOG_ERROR("Failed to enable read-only operation");
314 return res;
315 }
316 /*
317 According to NVMC examples in Nordic SDK busy status must be
318 checked after writing to NVMC_CONFIG
319 */
320 res = nrf5_wait_for_nvmc(chip);
321 if (res != ERROR_OK)
322 LOG_ERROR("Read only enable did not complete");
323
324 return res;
325 }
326
327 static int nrf5_nvmc_generic_erase(struct nrf5_info *chip,
328 uint32_t erase_register, uint32_t erase_value)
329 {
330 int res;
331
332 res = nrf5_nvmc_erase_enable(chip);
333 if (res != ERROR_OK)
334 goto error;
335
336 res = target_write_u32(chip->target,
337 erase_register,
338 erase_value);
339 if (res != ERROR_OK)
340 goto set_read_only;
341
342 res = nrf5_wait_for_nvmc(chip);
343 if (res != ERROR_OK)
344 goto set_read_only;
345
346 return nrf5_nvmc_read_only(chip);
347
348 set_read_only:
349 nrf5_nvmc_read_only(chip);
350 error:
351 LOG_ERROR("Failed to erase reg: 0x%08"PRIx32" val: 0x%08"PRIx32,
352 erase_register, erase_value);
353 return ERROR_FAIL;
354 }
355
356 static int nrf5_protect_check(struct flash_bank *bank)
357 {
358 int res;
359 uint32_t clenr0;
360
361 /* UICR cannot be write protected so just return early */
362 if (bank->base == NRF5_UICR_BASE)
363 return ERROR_OK;
364
365 struct nrf5_info *chip = bank->driver_priv;
366
367 assert(chip != NULL);
368
369 res = target_read_u32(chip->target, NRF5_FICR_CLENR0,
370 &clenr0);
371 if (res != ERROR_OK) {
372 LOG_ERROR("Couldn't read code region 0 size[FICR]");
373 return res;
374 }
375
376 if (clenr0 == 0xFFFFFFFF) {
377 res = target_read_u32(chip->target, NRF5_UICR_CLENR0,
378 &clenr0);
379 if (res != ERROR_OK) {
380 LOG_ERROR("Couldn't read code region 0 size[UICR]");
381 return res;
382 }
383 }
384
385 for (int i = 0; i < bank->num_sectors; i++)
386 bank->sectors[i].is_protected =
387 clenr0 != 0xFFFFFFFF && bank->sectors[i].offset < clenr0;
388
389 return ERROR_OK;
390 }
391
392 static int nrf5_protect(struct flash_bank *bank, int set, int first, int last)
393 {
394 int res;
395 uint32_t clenr0, ppfc;
396 struct nrf5_info *chip;
397
398 /* UICR cannot be write protected so just bail out early */
399 if (bank->base == NRF5_UICR_BASE)
400 return ERROR_FAIL;
401
402 res = nrf5_get_probed_chip_if_halted(bank, &chip);
403 if (res != ERROR_OK)
404 return res;
405
406 if (first != 0) {
407 LOG_ERROR("Code region 0 must start at the begining of the bank");
408 return ERROR_FAIL;
409 }
410
411 res = target_read_u32(chip->target, NRF5_FICR_PPFC,
412 &ppfc);
413 if (res != ERROR_OK) {
414 LOG_ERROR("Couldn't read PPFC register");
415 return res;
416 }
417
418 if ((ppfc & 0xFF) == 0x00) {
419 LOG_ERROR("Code region 0 size was pre-programmed at the factory, can't change flash protection settings");
420 return ERROR_FAIL;
421 }
422
423 res = target_read_u32(chip->target, NRF5_UICR_CLENR0,
424 &clenr0);
425 if (res != ERROR_OK) {
426 LOG_ERROR("Couldn't read code region 0 size[UICR]");
427 return res;
428 }
429
430 if (clenr0 == 0xFFFFFFFF) {
431 res = target_write_u32(chip->target, NRF5_UICR_CLENR0,
432 clenr0);
433 if (res != ERROR_OK) {
434 LOG_ERROR("Couldn't write code region 0 size[UICR]");
435 return res;
436 }
437
438 } else {
439 LOG_ERROR("You need to perform chip erase before changing the protection settings");
440 }
441
442 nrf5_protect_check(bank);
443
444 return ERROR_OK;
445 }
446
447 static int nrf5_probe(struct flash_bank *bank)
448 {
449 uint32_t hwid;
450 int res;
451 struct nrf5_info *chip = bank->driver_priv;
452
453 res = target_read_u32(chip->target, NRF5_FICR_CONFIGID, &hwid);
454 if (res != ERROR_OK) {
455 LOG_ERROR("Couldn't read CONFIGID register");
456 return res;
457 }
458
459 hwid &= 0xFFFF; /* HWID is stored in the lower two
460 * bytes of the CONFIGID register */
461
462 const struct nrf5_device_spec *spec = NULL;
463 for (size_t i = 0; i < ARRAY_SIZE(nrf5_known_devices_table); i++) {
464 if (hwid == nrf5_known_devices_table[i].hwid) {
465 spec = &nrf5_known_devices_table[i];
466 break;
467 }
468 }
469
470 if (!chip->bank[0].probed && !chip->bank[1].probed) {
471 if (spec)
472 LOG_INFO("nRF%s-%s(build code: %s) %ukB Flash",
473 spec->part, spec->variant, spec->build_code,
474 spec->flash_size_kb);
475 else
476 LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid);
477 }
478
479 if (bank->base == NRF5_FLASH_BASE) {
480 /* The value stored in NRF5_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */
481 res = target_read_u32(chip->target, NRF5_FICR_CODEPAGESIZE,
482 &chip->code_page_size);
483 if (res != ERROR_OK) {
484 LOG_ERROR("Couldn't read code page size");
485 return res;
486 }
487
488 /* Note the register name is misleading,
489 * NRF5_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */
490 uint32_t num_sectors;
491 res = target_read_u32(chip->target, NRF5_FICR_CODESIZE, &num_sectors);
492 if (res != ERROR_OK) {
493 LOG_ERROR("Couldn't read code memory size");
494 return res;
495 }
496
497 bank->num_sectors = num_sectors;
498 bank->size = num_sectors * chip->code_page_size;
499
500 if (spec && bank->size / 1024 != spec->flash_size_kb)
501 LOG_WARNING("Chip's reported Flash capacity does not match expected one");
502
503 bank->sectors = calloc(bank->num_sectors,
504 sizeof((bank->sectors)[0]));
505 if (!bank->sectors)
506 return ERROR_FLASH_BANK_NOT_PROBED;
507
508 /* Fill out the sector information: all NRF5 sectors are the same size and
509 * there is always a fixed number of them. */
510 for (int i = 0; i < bank->num_sectors; i++) {
511 bank->sectors[i].size = chip->code_page_size;
512 bank->sectors[i].offset = i * chip->code_page_size;
513
514 /* mark as unknown */
515 bank->sectors[i].is_erased = -1;
516 bank->sectors[i].is_protected = -1;
517 }
518
519 nrf5_protect_check(bank);
520
521 chip->bank[0].probed = true;
522 } else {
523 bank->size = NRF5_UICR_SIZE;
524 bank->num_sectors = 1;
525 bank->sectors = calloc(bank->num_sectors,
526 sizeof((bank->sectors)[0]));
527 if (!bank->sectors)
528 return ERROR_FLASH_BANK_NOT_PROBED;
529
530 bank->sectors[0].size = bank->size;
531 bank->sectors[0].offset = 0;
532
533 /* mark as unknown */
534 bank->sectors[0].is_erased = 0;
535 bank->sectors[0].is_protected = 0;
536
537 chip->bank[1].probed = true;
538 }
539
540 return ERROR_OK;
541 }
542
543 static int nrf5_auto_probe(struct flash_bank *bank)
544 {
545 int probed = nrf5_bank_is_probed(bank);
546
547 if (probed < 0)
548 return probed;
549 else if (probed)
550 return ERROR_OK;
551 else
552 return nrf5_probe(bank);
553 }
554
555 static struct flash_sector *nrf5_find_sector_by_address(struct flash_bank *bank, uint32_t address)
556 {
557 struct nrf5_info *chip = bank->driver_priv;
558
559 for (int i = 0; i < bank->num_sectors; i++)
560 if (bank->sectors[i].offset <= address &&
561 address < (bank->sectors[i].offset + chip->code_page_size))
562 return &bank->sectors[i];
563 return NULL;
564 }
565
566 static int nrf5_erase_all(struct nrf5_info *chip)
567 {
568 LOG_DEBUG("Erasing all non-volatile memory");
569 return nrf5_nvmc_generic_erase(chip,
570 NRF5_NVMC_ERASEALL,
571 0x00000001);
572 }
573
574 static int nrf5_erase_page(struct flash_bank *bank,
575 struct nrf5_info *chip,
576 struct flash_sector *sector)
577 {
578 int res;
579
580 LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset);
581 if (sector->is_protected) {
582 LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32, sector->offset);
583 return ERROR_FAIL;
584 }
585
586 if (bank->base == NRF5_UICR_BASE) {
587 uint32_t ppfc;
588 res = target_read_u32(chip->target, NRF5_FICR_PPFC,
589 &ppfc);
590 if (res != ERROR_OK) {
591 LOG_ERROR("Couldn't read PPFC register");
592 return res;
593 }
594
595 if ((ppfc & 0xFF) == 0xFF) {
596 /* We can't erase the UICR. Double-check to
597 see if it's already erased before complaining. */
598 default_flash_blank_check(bank);
599 if (sector->is_erased == 1)
600 return ERROR_OK;
601
602 LOG_ERROR("The chip was not pre-programmed with SoftDevice stack and UICR cannot be erased separately. Please issue mass erase before trying to write to this region");
603 return ERROR_FAIL;
604 }
605
606 res = nrf5_nvmc_generic_erase(chip,
607 NRF5_NVMC_ERASEUICR,
608 0x00000001);
609
610
611 } else {
612 res = nrf5_nvmc_generic_erase(chip,
613 NRF5_NVMC_ERASEPAGE,
614 sector->offset);
615 }
616
617 if (res == ERROR_OK)
618 sector->is_erased = 1;
619
620 return res;
621 }
622
623 static const uint8_t nrf5_flash_write_code[] = {
624 /* See contrib/loaders/flash/cortex-m0.S */
625 /* <wait_fifo>: */
626 0x0d, 0x68, /* ldr r5, [r1, #0] */
627 0x00, 0x2d, /* cmp r5, #0 */
628 0x0b, 0xd0, /* beq.n 1e <exit> */
629 0x4c, 0x68, /* ldr r4, [r1, #4] */
630 0xac, 0x42, /* cmp r4, r5 */
631 0xf9, 0xd0, /* beq.n 0 <wait_fifo> */
632 0x20, 0xcc, /* ldmia r4!, {r5} */
633 0x20, 0xc3, /* stmia r3!, {r5} */
634 0x94, 0x42, /* cmp r4, r2 */
635 0x01, 0xd3, /* bcc.n 18 <no_wrap> */
636 0x0c, 0x46, /* mov r4, r1 */
637 0x08, 0x34, /* adds r4, #8 */
638 /* <no_wrap>: */
639 0x4c, 0x60, /* str r4, [r1, #4] */
640 0x04, 0x38, /* subs r0, #4 */
641 0xf0, 0xd1, /* bne.n 0 <wait_fifo> */
642 /* <exit>: */
643 0x00, 0xbe /* bkpt 0x0000 */
644 };
645
646
647 /* Start a low level flash write for the specified region */
648 static int nrf5_ll_flash_write(struct nrf5_info *chip, uint32_t offset, const uint8_t *buffer, uint32_t bytes)
649 {
650 struct target *target = chip->target;
651 uint32_t buffer_size = 8192;
652 struct working_area *write_algorithm;
653 struct working_area *source;
654 uint32_t address = NRF5_FLASH_BASE + offset;
655 struct reg_param reg_params[4];
656 struct armv7m_algorithm armv7m_info;
657 int retval = ERROR_OK;
658
659
660 LOG_DEBUG("Writing buffer to flash offset=0x%"PRIx32" bytes=0x%"PRIx32, offset, bytes);
661 assert(bytes % 4 == 0);
662
663 /* allocate working area with flash programming code */
664 if (target_alloc_working_area(target, sizeof(nrf5_flash_write_code),
665 &write_algorithm) != ERROR_OK) {
666 LOG_WARNING("no working area available, falling back to slow memory writes");
667
668 for (; bytes > 0; bytes -= 4) {
669 retval = target_write_memory(chip->target, offset, 4, 1, buffer);
670 if (retval != ERROR_OK)
671 return retval;
672
673 retval = nrf5_wait_for_nvmc(chip);
674 if (retval != ERROR_OK)
675 return retval;
676
677 offset += 4;
678 buffer += 4;
679 }
680
681 return ERROR_OK;
682 }
683
684 LOG_WARNING("using fast async flash loader. This is currently supported");
685 LOG_WARNING("only with ST-Link and CMSIS-DAP. If you have issues, add");
686 LOG_WARNING("\"set WORKAREASIZE 0\" before sourcing nrf51.cfg/nrf52.cfg to disable it");
687
688 retval = target_write_buffer(target, write_algorithm->address,
689 sizeof(nrf5_flash_write_code),
690 nrf5_flash_write_code);
691 if (retval != ERROR_OK)
692 return retval;
693
694 /* memory buffer */
695 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
696 buffer_size /= 2;
697 buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
698 if (buffer_size <= 256) {
699 /* free working area, write algorithm already allocated */
700 target_free_working_area(target, write_algorithm);
701
702 LOG_WARNING("No large enough working area available, can't do block memory writes");
703 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
704 }
705 }
706
707 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
708 armv7m_info.core_mode = ARM_MODE_THREAD;
709
710 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* byte count */
711 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* buffer start */
712 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer end */
713 init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_OUT); /* target address */
714
715 buf_set_u32(reg_params[0].value, 0, 32, bytes);
716 buf_set_u32(reg_params[1].value, 0, 32, source->address);
717 buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size);
718 buf_set_u32(reg_params[3].value, 0, 32, address);
719
720 retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4,
721 0, NULL,
722 4, reg_params,
723 source->address, source->size,
724 write_algorithm->address, 0,
725 &armv7m_info);
726
727 target_free_working_area(target, source);
728 target_free_working_area(target, write_algorithm);
729
730 destroy_reg_param(&reg_params[0]);
731 destroy_reg_param(&reg_params[1]);
732 destroy_reg_param(&reg_params[2]);
733 destroy_reg_param(&reg_params[3]);
734
735 return retval;
736 }
737
738 /* Check and erase flash sectors in specified range then start a low level page write.
739 start/end must be sector aligned.
740 */
741 static int nrf5_write_pages(struct flash_bank *bank, uint32_t start, uint32_t end, const uint8_t *buffer)
742 {
743 int res = ERROR_FAIL;
744 struct nrf5_info *chip = bank->driver_priv;
745 struct flash_sector *sector;
746 uint32_t offset;
747
748 assert(start % chip->code_page_size == 0);
749 assert(end % chip->code_page_size == 0);
750
751 /* Erase all sectors */
752 for (offset = start; offset < end; offset += chip->code_page_size) {
753 sector = nrf5_find_sector_by_address(bank, offset);
754 if (!sector) {
755 LOG_ERROR("Invalid sector @ 0x%08"PRIx32, offset);
756 return ERROR_FLASH_SECTOR_INVALID;
757 }
758
759 if (sector->is_protected) {
760 LOG_ERROR("Can't erase protected sector @ 0x%08"PRIx32, offset);
761 goto error;
762 }
763
764 if (sector->is_erased != 1) { /* 1 = erased, 0= not erased, -1 = unknown */
765 res = nrf5_erase_page(bank, chip, sector);
766 if (res != ERROR_OK) {
767 LOG_ERROR("Failed to erase sector @ 0x%08"PRIx32, sector->offset);
768 goto error;
769 }
770 }
771 sector->is_erased = 0;
772 }
773
774 res = nrf5_nvmc_write_enable(chip);
775 if (res != ERROR_OK)
776 goto error;
777
778 res = nrf5_ll_flash_write(chip, start, buffer, (end - start));
779 if (res != ERROR_OK)
780 goto set_read_only;
781
782 return nrf5_nvmc_read_only(chip);
783
784 set_read_only:
785 nrf5_nvmc_read_only(chip);
786 error:
787 LOG_ERROR("Failed to write to nrf5 flash");
788 return res;
789 }
790
791 static int nrf5_erase(struct flash_bank *bank, int first, int last)
792 {
793 int res;
794 struct nrf5_info *chip;
795
796 res = nrf5_get_probed_chip_if_halted(bank, &chip);
797 if (res != ERROR_OK)
798 return res;
799
800 /* For each sector to be erased */
801 for (int s = first; s <= last && res == ERROR_OK; s++)
802 res = nrf5_erase_page(bank, chip, &bank->sectors[s]);
803
804 return res;
805 }
806
807 static int nrf5_code_flash_write(struct flash_bank *bank,
808 struct nrf5_info *chip,
809 const uint8_t *buffer, uint32_t offset, uint32_t count)
810 {
811
812 int res;
813 /* Need to perform reads to fill any gaps we need to preserve in the first page,
814 before the start of buffer, or in the last page, after the end of buffer */
815 uint32_t first_page = offset/chip->code_page_size;
816 uint32_t last_page = DIV_ROUND_UP(offset+count, chip->code_page_size);
817
818 uint32_t first_page_offset = first_page * chip->code_page_size;
819 uint32_t last_page_offset = last_page * chip->code_page_size;
820
821 LOG_DEBUG("Padding write from 0x%08"PRIx32"-0x%08"PRIx32" as 0x%08"PRIx32"-0x%08"PRIx32,
822 offset, offset+count, first_page_offset, last_page_offset);
823
824 uint32_t page_cnt = last_page - first_page;
825 uint8_t buffer_to_flash[page_cnt*chip->code_page_size];
826
827 /* Fill in any space between start of first page and start of buffer */
828 uint32_t pre = offset - first_page_offset;
829 if (pre > 0) {
830 res = target_read_memory(bank->target,
831 first_page_offset,
832 1,
833 pre,
834 buffer_to_flash);
835 if (res != ERROR_OK)
836 return res;
837 }
838
839 /* Fill in main contents of buffer */
840 memcpy(buffer_to_flash+pre, buffer, count);
841
842 /* Fill in any space between end of buffer and end of last page */
843 uint32_t post = last_page_offset - (offset+count);
844 if (post > 0) {
845 /* Retrieve the full row contents from Flash */
846 res = target_read_memory(bank->target,
847 offset + count,
848 1,
849 post,
850 buffer_to_flash+pre+count);
851 if (res != ERROR_OK)
852 return res;
853 }
854
855 return nrf5_write_pages(bank, first_page_offset, last_page_offset, buffer_to_flash);
856 }
857
858 static int nrf5_uicr_flash_write(struct flash_bank *bank,
859 struct nrf5_info *chip,
860 const uint8_t *buffer, uint32_t offset, uint32_t count)
861 {
862 int res;
863 uint8_t uicr[NRF5_UICR_SIZE];
864 struct flash_sector *sector = &bank->sectors[0];
865
866 if ((offset + count) > NRF5_UICR_SIZE)
867 return ERROR_FAIL;
868
869 res = target_read_memory(bank->target,
870 NRF5_UICR_BASE,
871 1,
872 NRF5_UICR_SIZE,
873 uicr);
874
875 if (res != ERROR_OK)
876 return res;
877
878 if (sector->is_erased != 1) {
879 res = nrf5_erase_page(bank, chip, sector);
880 if (res != ERROR_OK)
881 return res;
882 }
883
884 res = nrf5_nvmc_write_enable(chip);
885 if (res != ERROR_OK)
886 return res;
887
888 memcpy(&uicr[offset], buffer, count);
889
890 res = nrf5_ll_flash_write(chip, NRF5_UICR_BASE, uicr, NRF5_UICR_SIZE);
891 if (res != ERROR_OK) {
892 nrf5_nvmc_read_only(chip);
893 return res;
894 }
895
896 return nrf5_nvmc_read_only(chip);
897 }
898
899
900 static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer,
901 uint32_t offset, uint32_t count)
902 {
903 int res;
904 struct nrf5_info *chip;
905
906 res = nrf5_get_probed_chip_if_halted(bank, &chip);
907 if (res != ERROR_OK)
908 return res;
909
910 return chip->bank[bank->bank_number].write(bank, chip, buffer, offset, count);
911 }
912
913
914 FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
915 {
916 static struct nrf5_info *chip;
917
918 switch (bank->base) {
919 case NRF5_FLASH_BASE:
920 bank->bank_number = 0;
921 break;
922 case NRF5_UICR_BASE:
923 bank->bank_number = 1;
924 break;
925 default:
926 LOG_ERROR("Invalid bank address 0x%08" PRIx32, bank->base);
927 return ERROR_FAIL;
928 }
929
930 if (!chip) {
931 /* Create a new chip */
932 chip = calloc(1, sizeof(*chip));
933 if (!chip)
934 return ERROR_FAIL;
935
936 chip->target = bank->target;
937 }
938
939 switch (bank->base) {
940 case NRF5_FLASH_BASE:
941 chip->bank[bank->bank_number].write = nrf5_code_flash_write;
942 break;
943 case NRF5_UICR_BASE:
944 chip->bank[bank->bank_number].write = nrf5_uicr_flash_write;
945 break;
946 }
947
948 chip->bank[bank->bank_number].probed = false;
949 bank->driver_priv = chip;
950
951 return ERROR_OK;
952 }
953
954 COMMAND_HANDLER(nrf5_handle_mass_erase_command)
955 {
956 int res;
957 struct flash_bank *bank = NULL;
958 struct target *target = get_current_target(CMD_CTX);
959
960 res = get_flash_bank_by_addr(target, NRF5_FLASH_BASE, true, &bank);
961 if (res != ERROR_OK)
962 return res;
963
964 assert(bank != NULL);
965
966 struct nrf5_info *chip;
967
968 res = nrf5_get_probed_chip_if_halted(bank, &chip);
969 if (res != ERROR_OK)
970 return res;
971
972 uint32_t ppfc;
973
974 res = target_read_u32(target, NRF5_FICR_PPFC,
975 &ppfc);
976 if (res != ERROR_OK) {
977 LOG_ERROR("Couldn't read PPFC register");
978 return res;
979 }
980
981 if ((ppfc & 0xFF) == 0x00) {
982 LOG_ERROR("Code region 0 size was pre-programmed at the factory, "
983 "mass erase command won't work.");
984 return ERROR_FAIL;
985 }
986
987 res = nrf5_erase_all(chip);
988 if (res != ERROR_OK) {
989 LOG_ERROR("Failed to erase the chip");
990 nrf5_protect_check(bank);
991 return res;
992 }
993
994 for (int i = 0; i < bank->num_sectors; i++)
995 bank->sectors[i].is_erased = 1;
996
997 res = nrf5_protect_check(bank);
998 if (res != ERROR_OK) {
999 LOG_ERROR("Failed to check chip's write protection");
1000 return res;
1001 }
1002
1003 res = get_flash_bank_by_addr(target, NRF5_UICR_BASE, true, &bank);
1004 if (res != ERROR_OK)
1005 return res;
1006
1007 bank->sectors[0].is_erased = 1;
1008
1009 return ERROR_OK;
1010 }
1011
1012 static int nrf5_info(struct flash_bank *bank, char *buf, int buf_size)
1013 {
1014 int res;
1015
1016 struct nrf5_info *chip;
1017
1018 res = nrf5_get_probed_chip_if_halted(bank, &chip);
1019 if (res != ERROR_OK)
1020 return res;
1021
1022 static struct {
1023 const uint32_t address;
1024 uint32_t value;
1025 } ficr[] = {
1026 { .address = NRF5_FICR_CODEPAGESIZE },
1027 { .address = NRF5_FICR_CODESIZE },
1028 { .address = NRF5_FICR_CLENR0 },
1029 { .address = NRF5_FICR_PPFC },
1030 { .address = NRF5_FICR_NUMRAMBLOCK },
1031 { .address = NRF5_FICR_SIZERAMBLOCK0 },
1032 { .address = NRF5_FICR_SIZERAMBLOCK1 },
1033 { .address = NRF5_FICR_SIZERAMBLOCK2 },
1034 { .address = NRF5_FICR_SIZERAMBLOCK3 },
1035 { .address = NRF5_FICR_CONFIGID },
1036 { .address = NRF5_FICR_DEVICEID0 },
1037 { .address = NRF5_FICR_DEVICEID1 },
1038 { .address = NRF5_FICR_ER0 },
1039 { .address = NRF5_FICR_ER1 },
1040 { .address = NRF5_FICR_ER2 },
1041 { .address = NRF5_FICR_ER3 },
1042 { .address = NRF5_FICR_IR0 },
1043 { .address = NRF5_FICR_IR1 },
1044 { .address = NRF5_FICR_IR2 },
1045 { .address = NRF5_FICR_IR3 },
1046 { .address = NRF5_FICR_DEVICEADDRTYPE },
1047 { .address = NRF5_FICR_DEVICEADDR0 },
1048 { .address = NRF5_FICR_DEVICEADDR1 },
1049 { .address = NRF5_FICR_OVERRIDEN },
1050 { .address = NRF5_FICR_NRF_1MBIT0 },
1051 { .address = NRF5_FICR_NRF_1MBIT1 },
1052 { .address = NRF5_FICR_NRF_1MBIT2 },
1053 { .address = NRF5_FICR_NRF_1MBIT3 },
1054 { .address = NRF5_FICR_NRF_1MBIT4 },
1055 { .address = NRF5_FICR_BLE_1MBIT0 },
1056 { .address = NRF5_FICR_BLE_1MBIT1 },
1057 { .address = NRF5_FICR_BLE_1MBIT2 },
1058 { .address = NRF5_FICR_BLE_1MBIT3 },
1059 { .address = NRF5_FICR_BLE_1MBIT4 },
1060 }, uicr[] = {
1061 { .address = NRF5_UICR_CLENR0, },
1062 { .address = NRF5_UICR_RBPCONF },
1063 { .address = NRF5_UICR_XTALFREQ },
1064 { .address = NRF5_UICR_FWID },
1065 };
1066
1067 for (size_t i = 0; i < ARRAY_SIZE(ficr); i++) {
1068 res = target_read_u32(chip->target, ficr[i].address,
1069 &ficr[i].value);
1070 if (res != ERROR_OK) {
1071 LOG_ERROR("Couldn't read %" PRIx32, ficr[i].address);
1072 return res;
1073 }
1074 }
1075
1076 for (size_t i = 0; i < ARRAY_SIZE(uicr); i++) {
1077 res = target_read_u32(chip->target, uicr[i].address,
1078 &uicr[i].value);
1079 if (res != ERROR_OK) {
1080 LOG_ERROR("Couldn't read %" PRIx32, uicr[i].address);
1081 return res;
1082 }
1083 }
1084
1085 snprintf(buf, buf_size,
1086 "\n[factory information control block]\n\n"
1087 "code page size: %"PRIu32"B\n"
1088 "code memory size: %"PRIu32"kB\n"
1089 "code region 0 size: %"PRIu32"kB\n"
1090 "pre-programmed code: %s\n"
1091 "number of ram blocks: %"PRIu32"\n"
1092 "ram block 0 size: %"PRIu32"B\n"
1093 "ram block 1 size: %"PRIu32"B\n"
1094 "ram block 2 size: %"PRIu32"B\n"
1095 "ram block 3 size: %"PRIu32 "B\n"
1096 "config id: %" PRIx32 "\n"
1097 "device id: 0x%"PRIx32"%08"PRIx32"\n"
1098 "encryption root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
1099 "identity root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
1100 "device address type: 0x%"PRIx32"\n"
1101 "device address: 0x%"PRIx32"%08"PRIx32"\n"
1102 "override enable: %"PRIx32"\n"
1103 "NRF_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n"
1104 "BLE_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n"
1105 "\n[user information control block]\n\n"
1106 "code region 0 size: %"PRIu32"kB\n"
1107 "read back protection configuration: %"PRIx32"\n"
1108 "reset value for XTALFREQ: %"PRIx32"\n"
1109 "firmware id: 0x%04"PRIx32,
1110 ficr[0].value,
1111 (ficr[1].value * ficr[0].value) / 1024,
1112 (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024,
1113 ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present",
1114 ficr[4].value,
1115 ficr[5].value,
1116 (ficr[6].value == 0xFFFFFFFF) ? 0 : ficr[6].value,
1117 (ficr[7].value == 0xFFFFFFFF) ? 0 : ficr[7].value,
1118 (ficr[8].value == 0xFFFFFFFF) ? 0 : ficr[8].value,
1119 ficr[9].value,
1120 ficr[10].value, ficr[11].value,
1121 ficr[12].value, ficr[13].value, ficr[14].value, ficr[15].value,
1122 ficr[16].value, ficr[17].value, ficr[18].value, ficr[19].value,
1123 ficr[20].value,
1124 ficr[21].value, ficr[22].value,
1125 ficr[23].value,
1126 ficr[24].value, ficr[25].value, ficr[26].value, ficr[27].value, ficr[28].value,
1127 ficr[29].value, ficr[30].value, ficr[31].value, ficr[32].value, ficr[33].value,
1128 (uicr[0].value == 0xFFFFFFFF) ? 0 : uicr[0].value / 1024,
1129 uicr[1].value & 0xFFFF,
1130 uicr[2].value & 0xFF,
1131 uicr[3].value & 0xFFFF);
1132
1133 return ERROR_OK;
1134 }
1135
1136 static const struct command_registration nrf5_exec_command_handlers[] = {
1137 {
1138 .name = "mass_erase",
1139 .handler = nrf5_handle_mass_erase_command,
1140 .mode = COMMAND_EXEC,
1141 .help = "Erase all flash contents of the chip.",
1142 },
1143 COMMAND_REGISTRATION_DONE
1144 };
1145
1146 static const struct command_registration nrf5_command_handlers[] = {
1147 {
1148 .name = "nrf5",
1149 .mode = COMMAND_ANY,
1150 .help = "nrf5 flash command group",
1151 .usage = "",
1152 .chain = nrf5_exec_command_handlers,
1153 },
1154 {
1155 .name = "nrf51",
1156 .mode = COMMAND_ANY,
1157 .help = "nrf51 flash command group",
1158 .usage = "",
1159 .chain = nrf5_exec_command_handlers,
1160 },
1161 COMMAND_REGISTRATION_DONE
1162 };
1163
1164 struct flash_driver nrf5_flash = {
1165 .name = "nrf5",
1166 .commands = nrf5_command_handlers,
1167 .flash_bank_command = nrf5_flash_bank_command,
1168 .info = nrf5_info,
1169 .erase = nrf5_erase,
1170 .protect = nrf5_protect,
1171 .write = nrf5_write,
1172 .read = default_flash_read,
1173 .probe = nrf5_probe,
1174 .auto_probe = nrf5_auto_probe,
1175 .erase_check = default_flash_blank_check,
1176 .protect_check = nrf5_protect_check,
1177 };
1178
1179 /* We need to retain the flash-driver name as well as the commands
1180 * for backwards compatability */
1181 struct flash_driver nrf51_flash = {
1182 .name = "nrf51",
1183 .commands = nrf5_command_handlers,
1184 .flash_bank_command = nrf5_flash_bank_command,
1185 .info = nrf5_info,
1186 .erase = nrf5_erase,
1187 .protect = nrf5_protect,
1188 .write = nrf5_write,
1189 .read = default_flash_read,
1190 .probe = nrf5_probe,
1191 .auto_probe = nrf5_auto_probe,
1192 .erase_check = default_flash_blank_check,
1193 .protect_check = nrf5_protect_check,
1194 };

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)