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

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)