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> *
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. *
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. *
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 ***************************************************************************/
26 #include <target/algorithm.h>
27 #include <target/armv7m.h>
28 #include <helper/types.h>
29 #include <helper/time_support.h>
32 NRF5_FLASH_BASE
= 0x00000000,
35 enum nrf5_ficr_registers
{
36 NRF5_FICR_BASE
= 0x10000000, /* Factory Information Configuration Registers */
38 #define NRF5_FICR_REG(offset) (NRF5_FICR_BASE + offset)
40 NRF5_FICR_CODEPAGESIZE
= NRF5_FICR_REG(0x010),
41 NRF5_FICR_CODESIZE
= NRF5_FICR_REG(0x014),
43 NRF51_FICR_CLENR0
= NRF5_FICR_REG(0x028),
44 NRF51_FICR_PPFC
= NRF5_FICR_REG(0x02C),
45 NRF51_FICR_NUMRAMBLOCK
= NRF5_FICR_REG(0x034),
46 NRF51_FICR_SIZERAMBLOCK0
= NRF5_FICR_REG(0x038),
47 NRF51_FICR_SIZERAMBLOCK1
= NRF5_FICR_REG(0x03C),
48 NRF51_FICR_SIZERAMBLOCK2
= NRF5_FICR_REG(0x040),
49 NRF51_FICR_SIZERAMBLOCK3
= NRF5_FICR_REG(0x044),
51 NRF5_FICR_CONFIGID
= NRF5_FICR_REG(0x05C),
52 NRF5_FICR_DEVICEID0
= NRF5_FICR_REG(0x060),
53 NRF5_FICR_DEVICEID1
= NRF5_FICR_REG(0x064),
54 NRF5_FICR_ER0
= NRF5_FICR_REG(0x080),
55 NRF5_FICR_ER1
= NRF5_FICR_REG(0x084),
56 NRF5_FICR_ER2
= NRF5_FICR_REG(0x088),
57 NRF5_FICR_ER3
= NRF5_FICR_REG(0x08C),
58 NRF5_FICR_IR0
= NRF5_FICR_REG(0x090),
59 NRF5_FICR_IR1
= NRF5_FICR_REG(0x094),
60 NRF5_FICR_IR2
= NRF5_FICR_REG(0x098),
61 NRF5_FICR_IR3
= NRF5_FICR_REG(0x09C),
62 NRF5_FICR_DEVICEADDRTYPE
= NRF5_FICR_REG(0x0A0),
63 NRF5_FICR_DEVICEADDR0
= NRF5_FICR_REG(0x0A4),
64 NRF5_FICR_DEVICEADDR1
= NRF5_FICR_REG(0x0A8),
66 NRF51_FICR_OVERRIDEN
= NRF5_FICR_REG(0x0AC),
67 NRF51_FICR_NRF_1MBIT0
= NRF5_FICR_REG(0x0B0),
68 NRF51_FICR_NRF_1MBIT1
= NRF5_FICR_REG(0x0B4),
69 NRF51_FICR_NRF_1MBIT2
= NRF5_FICR_REG(0x0B8),
70 NRF51_FICR_NRF_1MBIT3
= NRF5_FICR_REG(0x0BC),
71 NRF51_FICR_NRF_1MBIT4
= NRF5_FICR_REG(0x0C0),
72 NRF51_FICR_BLE_1MBIT0
= NRF5_FICR_REG(0x0EC),
73 NRF51_FICR_BLE_1MBIT1
= NRF5_FICR_REG(0x0F0),
74 NRF51_FICR_BLE_1MBIT2
= NRF5_FICR_REG(0x0F4),
75 NRF51_FICR_BLE_1MBIT3
= NRF5_FICR_REG(0x0F8),
76 NRF51_FICR_BLE_1MBIT4
= NRF5_FICR_REG(0x0FC),
78 /* Following registers are available on nRF52 and on nRF51 since rev 3 */
79 NRF5_FICR_INFO_PART
= NRF5_FICR_REG(0x100),
80 NRF5_FICR_INFO_VARIANT
= NRF5_FICR_REG(0x104),
81 NRF5_FICR_INFO_PACKAGE
= NRF5_FICR_REG(0x108),
82 NRF5_FICR_INFO_RAM
= NRF5_FICR_REG(0x10C),
83 NRF5_FICR_INFO_FLASH
= NRF5_FICR_REG(0x110),
86 enum nrf5_uicr_registers
{
87 NRF5_UICR_BASE
= 0x10001000, /* User Information
88 * Configuration Regsters */
90 #define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset)
92 NRF51_UICR_CLENR0
= NRF5_UICR_REG(0x000),
93 NRF51_UICR_RBPCONF
= NRF5_UICR_REG(0x004),
94 NRF51_UICR_XTALFREQ
= NRF5_UICR_REG(0x008),
95 NRF51_UICR_FWID
= NRF5_UICR_REG(0x010),
98 enum nrf5_nvmc_registers
{
99 NRF5_NVMC_BASE
= 0x4001E000, /* Non-Volatile Memory
100 * Controller Registers */
102 #define NRF5_NVMC_REG(offset) (NRF5_NVMC_BASE + offset)
104 NRF5_NVMC_READY
= NRF5_NVMC_REG(0x400),
105 NRF5_NVMC_CONFIG
= NRF5_NVMC_REG(0x504),
106 NRF5_NVMC_ERASEPAGE
= NRF5_NVMC_REG(0x508),
107 NRF5_NVMC_ERASEALL
= NRF5_NVMC_REG(0x50C),
108 NRF5_NVMC_ERASEUICR
= NRF5_NVMC_REG(0x514),
110 NRF5_BPROT_BASE
= 0x40000000,
113 enum nrf5_nvmc_config_bits
{
114 NRF5_NVMC_CONFIG_REN
= 0x00,
115 NRF5_NVMC_CONFIG_WEN
= 0x01,
116 NRF5_NVMC_CONFIG_EEN
= 0x02,
120 struct nrf52_ficr_info
{
129 NRF5_FEATURE_SERIES_51
= 1 << 0,
130 NRF5_FEATURE_SERIES_52
= 1 << 1,
131 NRF5_FEATURE_BPROT
= 1 << 2,
132 NRF5_FEATURE_ACL_PROT
= 1 << 3,
135 struct nrf5_device_spec
{
139 const char *build_code
;
140 unsigned int flash_size_kb
;
141 enum nrf5_features features
;
148 struct nrf5_info
*chip
;
151 struct target
*target
;
153 /* chip identification stored in nrf5_probe() for use in nrf5_info() */
154 bool ficr_info_valid
;
155 struct nrf52_ficr_info ficr_info
;
156 const struct nrf5_device_spec
*spec
;
158 enum nrf5_features features
;
159 unsigned int flash_size_kb
;
162 #define NRF51_DEVICE_DEF(id, pt, var, bcode, fsize) \
167 .build_code = bcode, \
168 .flash_size_kb = (fsize), \
169 .features = NRF5_FEATURE_SERIES_51, \
172 #define NRF5_DEVICE_DEF(id, pt, var, bcode, fsize, features) \
177 .build_code = bcode, \
178 .flash_size_kb = (fsize), \
179 .features = features, \
182 /* The known devices table below is derived from the "nRF5x series
183 * compatibility matrix" documents, which can be found in the "DocLib" of
186 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51422_ic_revision_overview
187 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51822_ic_revision_overview
188 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51824_ic_revision_overview
189 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52810/latest/COMP/nrf52810/nRF52810_ic_revision_overview
190 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52832/latest/COMP/nrf52832/ic_revision_overview
191 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52840/latest/COMP/nrf52840/nRF52840_ic_revision_overview
193 * Up to date with Matrix v2.0, plus some additional HWIDs.
195 * The additional HWIDs apply where the build code in the matrix is
196 * shown as Gx0, Bx0, etc. In these cases the HWID in the matrix is
197 * for x==0, x!=0 means different (unspecified) HWIDs.
199 static const struct nrf5_device_spec nrf5_known_devices_table
[] = {
200 /* nRF51822 Devices (IC rev 1). */
201 NRF51_DEVICE_DEF(0x001D, "51822", "QFAA", "CA/C0", 256),
202 NRF51_DEVICE_DEF(0x0026, "51822", "QFAB", "AA", 128),
203 NRF51_DEVICE_DEF(0x0027, "51822", "QFAB", "A0", 128),
204 NRF51_DEVICE_DEF(0x0020, "51822", "CEAA", "BA", 256),
205 NRF51_DEVICE_DEF(0x002F, "51822", "CEAA", "B0", 256),
207 /* Some early nRF51-DK (PCA10028) & nRF51-Dongle (PCA10031) boards
208 with built-in jlink seem to use engineering samples not listed
209 in the nRF51 Series Compatibility Matrix V1.0. */
210 NRF51_DEVICE_DEF(0x0071, "51822", "QFAC", "AB", 256),
212 /* nRF51822 Devices (IC rev 2). */
213 NRF51_DEVICE_DEF(0x002A, "51822", "QFAA", "FA0", 256),
214 NRF51_DEVICE_DEF(0x0044, "51822", "QFAA", "GC0", 256),
215 NRF51_DEVICE_DEF(0x003C, "51822", "QFAA", "G0", 256),
216 NRF51_DEVICE_DEF(0x0057, "51822", "QFAA", "G2", 256),
217 NRF51_DEVICE_DEF(0x0058, "51822", "QFAA", "G3", 256),
218 NRF51_DEVICE_DEF(0x004C, "51822", "QFAB", "B0", 128),
219 NRF51_DEVICE_DEF(0x0040, "51822", "CEAA", "CA0", 256),
220 NRF51_DEVICE_DEF(0x0047, "51822", "CEAA", "DA0", 256),
221 NRF51_DEVICE_DEF(0x004D, "51822", "CEAA", "D00", 256),
223 /* nRF51822 Devices (IC rev 3). */
224 NRF51_DEVICE_DEF(0x0072, "51822", "QFAA", "H0", 256),
225 NRF51_DEVICE_DEF(0x00D1, "51822", "QFAA", "H2", 256),
226 NRF51_DEVICE_DEF(0x007B, "51822", "QFAB", "C0", 128),
227 NRF51_DEVICE_DEF(0x0083, "51822", "QFAC", "A0", 256),
228 NRF51_DEVICE_DEF(0x0084, "51822", "QFAC", "A1", 256),
229 NRF51_DEVICE_DEF(0x007D, "51822", "CDAB", "A0", 128),
230 NRF51_DEVICE_DEF(0x0079, "51822", "CEAA", "E0", 256),
231 NRF51_DEVICE_DEF(0x0087, "51822", "CFAC", "A0", 256),
232 NRF51_DEVICE_DEF(0x008F, "51822", "QFAA", "H1", 256),
234 /* nRF51422 Devices (IC rev 1). */
235 NRF51_DEVICE_DEF(0x001E, "51422", "QFAA", "CA", 256),
236 NRF51_DEVICE_DEF(0x0024, "51422", "QFAA", "C0", 256),
237 NRF51_DEVICE_DEF(0x0031, "51422", "CEAA", "A0A", 256),
239 /* nRF51422 Devices (IC rev 2). */
240 NRF51_DEVICE_DEF(0x002D, "51422", "QFAA", "DAA", 256),
241 NRF51_DEVICE_DEF(0x002E, "51422", "QFAA", "E0", 256),
242 NRF51_DEVICE_DEF(0x0061, "51422", "QFAB", "A00", 128),
243 NRF51_DEVICE_DEF(0x0050, "51422", "CEAA", "B0", 256),
245 /* nRF51422 Devices (IC rev 3). */
246 NRF51_DEVICE_DEF(0x0073, "51422", "QFAA", "F0", 256),
247 NRF51_DEVICE_DEF(0x007C, "51422", "QFAB", "B0", 128),
248 NRF51_DEVICE_DEF(0x0085, "51422", "QFAC", "A0", 256),
249 NRF51_DEVICE_DEF(0x0086, "51422", "QFAC", "A1", 256),
250 NRF51_DEVICE_DEF(0x007E, "51422", "CDAB", "A0", 128),
251 NRF51_DEVICE_DEF(0x007A, "51422", "CEAA", "C0", 256),
252 NRF51_DEVICE_DEF(0x0088, "51422", "CFAC", "A0", 256),
254 /* The driver fully autodects nRF52 series devices by FICR INFO,
255 * no need for nRF52xxx HWIDs in this table */
257 /* nRF52810 Devices */
258 NRF5_DEVICE_DEF(0x0142, "52810", "QFAA", "B0", 192, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
259 NRF5_DEVICE_DEF(0x0143, "52810", "QCAA", "C0", 192, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
261 /* nRF52832 Devices */
262 NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0", 512, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
263 NRF5_DEVICE_DEF(0x0139, "52832", "QFAA", "E0", 512, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
264 NRF5_DEVICE_DEF(0x00E3, "52832", "CIAA", "B0", 512, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
266 /* nRF52840 Devices */
267 NRF5_DEVICE_DEF(0x0150, "52840", "QIAA", "C0", 1024, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_ACL_PROT
),
271 struct nrf5_device_package
{
276 /* Newer devices have FICR INFO.PACKAGE.
277 * This table converts its value to two character code */
278 static const struct nrf5_device_package nrf5_packages_table
[] = {
285 static int nrf5_bank_is_probed(struct flash_bank
*bank
)
287 struct nrf5_bank
*nbank
= bank
->driver_priv
;
289 assert(nbank
!= NULL
);
291 return nbank
->probed
;
293 static int nrf5_probe(struct flash_bank
*bank
);
295 static int nrf5_get_probed_chip_if_halted(struct flash_bank
*bank
, struct nrf5_info
**chip
)
297 if (bank
->target
->state
!= TARGET_HALTED
) {
298 LOG_ERROR("Target not halted");
299 return ERROR_TARGET_NOT_HALTED
;
302 struct nrf5_bank
*nbank
= bank
->driver_priv
;
305 int probed
= nrf5_bank_is_probed(bank
);
309 return nrf5_probe(bank
);
314 static int nrf5_wait_for_nvmc(struct nrf5_info
*chip
)
318 int timeout_ms
= 340;
319 int64_t ts_start
= timeval_ms();
322 res
= target_read_u32(chip
->target
, NRF5_NVMC_READY
, &ready
);
323 if (res
!= ERROR_OK
) {
324 LOG_ERROR("Couldn't read NVMC_READY register");
328 if (ready
== 0x00000001)
333 } while ((timeval_ms()-ts_start
) < timeout_ms
);
335 LOG_DEBUG("Timed out waiting for NVMC_READY");
336 return ERROR_FLASH_BUSY
;
339 static int nrf5_nvmc_erase_enable(struct nrf5_info
*chip
)
342 res
= target_write_u32(chip
->target
,
344 NRF5_NVMC_CONFIG_EEN
);
346 if (res
!= ERROR_OK
) {
347 LOG_ERROR("Failed to enable erase operation");
352 According to NVMC examples in Nordic SDK busy status must be
353 checked after writing to NVMC_CONFIG
355 res
= nrf5_wait_for_nvmc(chip
);
357 LOG_ERROR("Erase enable did not complete");
362 static int nrf5_nvmc_write_enable(struct nrf5_info
*chip
)
365 res
= target_write_u32(chip
->target
,
367 NRF5_NVMC_CONFIG_WEN
);
369 if (res
!= ERROR_OK
) {
370 LOG_ERROR("Failed to enable write operation");
375 According to NVMC examples in Nordic SDK busy status must be
376 checked after writing to NVMC_CONFIG
378 res
= nrf5_wait_for_nvmc(chip
);
380 LOG_ERROR("Write enable did not complete");
385 static int nrf5_nvmc_read_only(struct nrf5_info
*chip
)
388 res
= target_write_u32(chip
->target
,
390 NRF5_NVMC_CONFIG_REN
);
392 if (res
!= ERROR_OK
) {
393 LOG_ERROR("Failed to enable read-only operation");
397 According to NVMC examples in Nordic SDK busy status must be
398 checked after writing to NVMC_CONFIG
400 res
= nrf5_wait_for_nvmc(chip
);
402 LOG_ERROR("Read only enable did not complete");
407 static int nrf5_nvmc_generic_erase(struct nrf5_info
*chip
,
408 uint32_t erase_register
, uint32_t erase_value
)
412 res
= nrf5_nvmc_erase_enable(chip
);
416 res
= target_write_u32(chip
->target
,
422 res
= nrf5_wait_for_nvmc(chip
);
426 return nrf5_nvmc_read_only(chip
);
429 nrf5_nvmc_read_only(chip
);
431 LOG_ERROR("Failed to erase reg: 0x%08"PRIx32
" val: 0x%08"PRIx32
,
432 erase_register
, erase_value
);
436 static int nrf5_protect_check_bprot(struct flash_bank
*bank
)
438 struct nrf5_bank
*nbank
= bank
->driver_priv
;
439 struct nrf5_info
*chip
= nbank
->chip
;
441 assert(chip
!= NULL
);
443 static uint32_t nrf5_bprot_offsets
[4] = { 0x600, 0x604, 0x610, 0x614 };
444 uint32_t bprot_reg
= 0;
447 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
448 unsigned int bit
= i
% 32;
450 unsigned int n_reg
= i
/ 32;
451 if (n_reg
>= ARRAY_SIZE(nrf5_bprot_offsets
))
454 res
= target_read_u32(chip
->target
, NRF5_BPROT_BASE
+ nrf5_bprot_offsets
[n_reg
], &bprot_reg
);
458 bank
->sectors
[i
].is_protected
= (bprot_reg
& (1 << bit
)) ? 1 : 0;
463 static int nrf5_protect_check(struct flash_bank
*bank
)
468 /* UICR cannot be write protected so just return early */
469 if (bank
->base
== NRF5_UICR_BASE
)
472 struct nrf5_bank
*nbank
= bank
->driver_priv
;
473 struct nrf5_info
*chip
= nbank
->chip
;
475 assert(chip
!= NULL
);
477 if (chip
->features
& NRF5_FEATURE_BPROT
)
478 return nrf5_protect_check_bprot(bank
);
480 if (!(chip
->features
& NRF5_FEATURE_SERIES_51
)) {
481 LOG_WARNING("Flash protection of this nRF device is not supported");
482 return ERROR_FLASH_OPER_UNSUPPORTED
;
485 res
= target_read_u32(chip
->target
, NRF51_FICR_CLENR0
,
487 if (res
!= ERROR_OK
) {
488 LOG_ERROR("Couldn't read code region 0 size[FICR]");
492 if (clenr0
== 0xFFFFFFFF) {
493 res
= target_read_u32(chip
->target
, NRF51_UICR_CLENR0
,
495 if (res
!= ERROR_OK
) {
496 LOG_ERROR("Couldn't read code region 0 size[UICR]");
501 for (int i
= 0; i
< bank
->num_sectors
; i
++)
502 bank
->sectors
[i
].is_protected
=
503 clenr0
!= 0xFFFFFFFF && bank
->sectors
[i
].offset
< clenr0
;
508 static int nrf5_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
511 uint32_t clenr0
, ppfc
;
512 struct nrf5_info
*chip
;
514 /* UICR cannot be write protected so just bail out early */
515 if (bank
->base
== NRF5_UICR_BASE
)
518 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
522 if (!(chip
->features
& NRF5_FEATURE_SERIES_51
)) {
523 LOG_ERROR("Flash protection setting of this nRF device is not supported");
524 return ERROR_FLASH_OPER_UNSUPPORTED
;
528 LOG_ERROR("Code region 0 must start at the begining of the bank");
532 res
= target_read_u32(chip
->target
, NRF51_FICR_PPFC
,
534 if (res
!= ERROR_OK
) {
535 LOG_ERROR("Couldn't read PPFC register");
539 if ((ppfc
& 0xFF) == 0x00) {
540 LOG_ERROR("Code region 0 size was pre-programmed at the factory, can't change flash protection settings");
544 res
= target_read_u32(chip
->target
, NRF51_UICR_CLENR0
,
546 if (res
!= ERROR_OK
) {
547 LOG_ERROR("Couldn't read code region 0 size[UICR]");
551 if (clenr0
== 0xFFFFFFFF) {
552 res
= target_write_u32(chip
->target
, NRF51_UICR_CLENR0
,
554 if (res
!= ERROR_OK
) {
555 LOG_ERROR("Couldn't write code region 0 size[UICR]");
560 LOG_ERROR("You need to perform chip erase before changing the protection settings");
563 nrf5_protect_check(bank
);
568 static bool nrf5_info_variant_to_str(uint32_t variant
, char *bf
)
570 h_u32_to_be((uint8_t *)bf
, variant
);
572 if (isalnum(bf
[0]) && isalnum(bf
[1]) && isalnum(bf
[2]) && isalnum(bf
[3]))
579 static const char *nrf5_decode_info_package(uint32_t package
)
581 for (size_t i
= 0; i
< ARRAY_SIZE(nrf5_packages_table
); i
++) {
582 if (nrf5_packages_table
[i
].package
== package
)
583 return nrf5_packages_table
[i
].code
;
588 static int nrf5_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
590 struct nrf5_bank
*nbank
= bank
->driver_priv
;
591 struct nrf5_info
*chip
= nbank
->chip
;
594 snprintf(buf
, buf_size
,
595 "nRF%s-%s(build code: %s) %ukB Flash",
596 chip
->spec
->part
, chip
->spec
->variant
, chip
->spec
->build_code
,
597 chip
->flash_size_kb
);
599 } else if (chip
->ficr_info_valid
) {
601 nrf5_info_variant_to_str(chip
->ficr_info
.variant
, variant
);
602 snprintf(buf
, buf_size
,
603 "nRF%" PRIx32
"-%s%.2s(build code: %s) %" PRIu32
604 "kB Flash, %" PRIu32
"kB RAM",
605 chip
->ficr_info
.part
,
606 nrf5_decode_info_package(chip
->ficr_info
.package
),
607 variant
, &variant
[2],
609 chip
->ficr_info
.ram
);
612 snprintf(buf
, buf_size
, "nRF51xxx (HWID 0x%04" PRIx16
") %ukB Flash",
613 chip
->hwid
, chip
->flash_size_kb
);
618 static int nrf5_read_ficr_info(struct nrf5_info
*chip
)
621 struct target
*target
= chip
->target
;
623 chip
->ficr_info_valid
= false;
625 res
= target_read_u32(target
, NRF5_FICR_INFO_PART
, &chip
->ficr_info
.part
);
626 if (res
!= ERROR_OK
) {
627 LOG_DEBUG("Couldn't read FICR INFO.PART register");
631 uint32_t series
= chip
->ficr_info
.part
& 0xfffff000;
634 chip
->features
= NRF5_FEATURE_SERIES_51
;
638 chip
->features
= NRF5_FEATURE_SERIES_52
;
640 switch (chip
->ficr_info
.part
) {
643 chip
->features
|= NRF5_FEATURE_BPROT
;
647 chip
->features
|= NRF5_FEATURE_ACL_PROT
;
653 LOG_DEBUG("FICR INFO likely not implemented. Invalid PART value 0x%08"
654 PRIx32
, chip
->ficr_info
.part
);
655 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
658 /* Now we know the device has FICR INFO filled by something relevant:
659 * Although it is not documented, the tested nRF51 rev 3 devices
660 * have FICR INFO.PART, RAM and FLASH of the same format as nRF52.
661 * VARIANT and PACKAGE coding is unknown for a nRF51 device.
662 * nRF52 devices have FICR INFO documented and always filled. */
664 res
= target_read_u32(target
, NRF5_FICR_INFO_VARIANT
, &chip
->ficr_info
.variant
);
668 res
= target_read_u32(target
, NRF5_FICR_INFO_PACKAGE
, &chip
->ficr_info
.package
);
672 res
= target_read_u32(target
, NRF5_FICR_INFO_RAM
, &chip
->ficr_info
.ram
);
676 res
= target_read_u32(target
, NRF5_FICR_INFO_FLASH
, &chip
->ficr_info
.flash
);
680 chip
->ficr_info_valid
= true;
684 static int nrf5_probe(struct flash_bank
*bank
)
687 struct nrf5_bank
*nbank
= bank
->driver_priv
;
688 struct nrf5_info
*chip
= nbank
->chip
;
689 struct target
*target
= chip
->target
;
691 res
= target_read_u32(target
, NRF5_FICR_CONFIGID
, &chip
->hwid
);
692 if (res
!= ERROR_OK
) {
693 LOG_ERROR("Couldn't read CONFIGID register");
697 chip
->hwid
&= 0xFFFF; /* HWID is stored in the lower two
698 * bytes of the CONFIGID register */
700 /* guess a nRF51 series if the device has no FICR INFO and we don't know HWID */
701 chip
->features
= NRF5_FEATURE_SERIES_51
;
703 /* Don't bail out on error for the case that some old engineering
704 * sample has FICR INFO registers unreadable. We can proceed anyway. */
705 (void)nrf5_read_ficr_info(chip
);
708 for (size_t i
= 0; i
< ARRAY_SIZE(nrf5_known_devices_table
); i
++) {
709 if (chip
->hwid
== nrf5_known_devices_table
[i
].hwid
) {
710 chip
->spec
= &nrf5_known_devices_table
[i
];
711 chip
->features
= chip
->spec
->features
;
716 if (chip
->spec
&& chip
->ficr_info_valid
) {
717 /* check if HWID table gives the same part as FICR INFO */
718 if (chip
->ficr_info
.part
!= strtoul(chip
->spec
->part
, NULL
, 16))
719 LOG_WARNING("HWID 0x%04" PRIx32
" mismatch: FICR INFO.PART %"
720 PRIx32
, chip
->hwid
, chip
->ficr_info
.part
);
723 /* The value stored in NRF5_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */
724 uint32_t flash_page_size
;
725 res
= target_read_u32(chip
->target
, NRF5_FICR_CODEPAGESIZE
,
727 if (res
!= ERROR_OK
) {
728 LOG_ERROR("Couldn't read code page size");
732 /* Note the register name is misleading,
733 * NRF5_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */
734 uint32_t num_sectors
;
735 res
= target_read_u32(chip
->target
, NRF5_FICR_CODESIZE
, &num_sectors
);
736 if (res
!= ERROR_OK
) {
737 LOG_ERROR("Couldn't read code memory size");
741 chip
->flash_size_kb
= num_sectors
* flash_page_size
/ 1024;
743 if (!chip
->bank
[0].probed
&& !chip
->bank
[1].probed
) {
745 nrf5_info(bank
, buf
, sizeof(buf
));
746 if (!chip
->spec
&& !chip
->ficr_info_valid
) {
747 LOG_INFO("Unknown device: %s", buf
);
753 if (bank
->base
== NRF5_FLASH_BASE
) {
755 if (chip
->spec
&& chip
->flash_size_kb
!= chip
->spec
->flash_size_kb
)
756 LOG_WARNING("Chip's reported Flash capacity does not match expected one");
757 if (chip
->ficr_info_valid
&& chip
->flash_size_kb
!= chip
->ficr_info
.flash
)
758 LOG_WARNING("Chip's reported Flash capacity does not match FICR INFO.FLASH");
760 bank
->num_sectors
= num_sectors
;
761 bank
->size
= num_sectors
* flash_page_size
;
763 bank
->sectors
= alloc_block_array(0, flash_page_size
, num_sectors
);
767 nrf5_protect_check(bank
);
769 chip
->bank
[0].probed
= true;
772 bank
->num_sectors
= 1;
773 bank
->size
= flash_page_size
;
775 bank
->sectors
= alloc_block_array(0, flash_page_size
, num_sectors
);
779 bank
->sectors
[0].is_protected
= 0;
781 chip
->bank
[1].probed
= true;
787 static int nrf5_auto_probe(struct flash_bank
*bank
)
789 int probed
= nrf5_bank_is_probed(bank
);
796 return nrf5_probe(bank
);
799 static int nrf5_erase_all(struct nrf5_info
*chip
)
801 LOG_DEBUG("Erasing all non-volatile memory");
802 return nrf5_nvmc_generic_erase(chip
,
807 static int nrf5_erase_page(struct flash_bank
*bank
,
808 struct nrf5_info
*chip
,
809 struct flash_sector
*sector
)
813 LOG_DEBUG("Erasing page at 0x%"PRIx32
, sector
->offset
);
814 if (sector
->is_protected
) {
815 LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32
, sector
->offset
);
819 if (bank
->base
== NRF5_UICR_BASE
) {
820 if (chip
->features
& NRF5_FEATURE_SERIES_51
) {
822 res
= target_read_u32(chip
->target
, NRF51_FICR_PPFC
,
824 if (res
!= ERROR_OK
) {
825 LOG_ERROR("Couldn't read PPFC register");
829 if ((ppfc
& 0xFF) == 0xFF) {
830 /* We can't erase the UICR. Double-check to
831 see if it's already erased before complaining. */
832 default_flash_blank_check(bank
);
833 if (sector
->is_erased
== 1)
836 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");
841 res
= nrf5_nvmc_generic_erase(chip
,
847 res
= nrf5_nvmc_generic_erase(chip
,
855 static const uint8_t nrf5_flash_write_code
[] = {
856 /* See contrib/loaders/flash/cortex-m0.S */
858 0x0d, 0x68, /* ldr r5, [r1, #0] */
859 0x00, 0x2d, /* cmp r5, #0 */
860 0x0b, 0xd0, /* beq.n 1e <exit> */
861 0x4c, 0x68, /* ldr r4, [r1, #4] */
862 0xac, 0x42, /* cmp r4, r5 */
863 0xf9, 0xd0, /* beq.n 0 <wait_fifo> */
864 0x20, 0xcc, /* ldmia r4!, {r5} */
865 0x20, 0xc3, /* stmia r3!, {r5} */
866 0x94, 0x42, /* cmp r4, r2 */
867 0x01, 0xd3, /* bcc.n 18 <no_wrap> */
868 0x0c, 0x46, /* mov r4, r1 */
869 0x08, 0x34, /* adds r4, #8 */
871 0x4c, 0x60, /* str r4, [r1, #4] */
872 0x04, 0x38, /* subs r0, #4 */
873 0xf0, 0xd1, /* bne.n 0 <wait_fifo> */
875 0x00, 0xbe /* bkpt 0x0000 */
879 /* Start a low level flash write for the specified region */
880 static int nrf5_ll_flash_write(struct nrf5_info
*chip
, uint32_t address
, const uint8_t *buffer
, uint32_t bytes
)
882 struct target
*target
= chip
->target
;
883 uint32_t buffer_size
= 8192;
884 struct working_area
*write_algorithm
;
885 struct working_area
*source
;
886 struct reg_param reg_params
[4];
887 struct armv7m_algorithm armv7m_info
;
888 int retval
= ERROR_OK
;
890 LOG_DEBUG("Writing buffer to flash address=0x%"PRIx32
" bytes=0x%"PRIx32
, address
, bytes
);
891 assert(bytes
% 4 == 0);
893 /* allocate working area with flash programming code */
894 if (target_alloc_working_area(target
, sizeof(nrf5_flash_write_code
),
895 &write_algorithm
) != ERROR_OK
) {
896 LOG_WARNING("no working area available, falling back to slow memory writes");
898 for (; bytes
> 0; bytes
-= 4) {
899 retval
= target_write_memory(target
, address
, 4, 1, buffer
);
900 if (retval
!= ERROR_OK
)
903 retval
= nrf5_wait_for_nvmc(chip
);
904 if (retval
!= ERROR_OK
)
914 retval
= target_write_buffer(target
, write_algorithm
->address
,
915 sizeof(nrf5_flash_write_code
),
916 nrf5_flash_write_code
);
917 if (retval
!= ERROR_OK
)
921 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
) {
923 buffer_size
&= ~3UL; /* Make sure it's 4 byte aligned */
924 if (buffer_size
<= 256) {
925 /* free working area, write algorithm already allocated */
926 target_free_working_area(target
, write_algorithm
);
928 LOG_WARNING("No large enough working area available, can't do block memory writes");
929 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
933 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
934 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
936 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
); /* byte count */
937 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
); /* buffer start */
938 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
); /* buffer end */
939 init_reg_param(®_params
[3], "r3", 32, PARAM_IN_OUT
); /* target address */
941 buf_set_u32(reg_params
[0].value
, 0, 32, bytes
);
942 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
);
943 buf_set_u32(reg_params
[2].value
, 0, 32, source
->address
+ source
->size
);
944 buf_set_u32(reg_params
[3].value
, 0, 32, address
);
946 retval
= target_run_flash_async_algorithm(target
, buffer
, bytes
/4, 4,
949 source
->address
, source
->size
,
950 write_algorithm
->address
, 0,
953 target_free_working_area(target
, source
);
954 target_free_working_area(target
, write_algorithm
);
956 destroy_reg_param(®_params
[0]);
957 destroy_reg_param(®_params
[1]);
958 destroy_reg_param(®_params
[2]);
959 destroy_reg_param(®_params
[3]);
964 static int nrf5_write(struct flash_bank
*bank
, const uint8_t *buffer
,
965 uint32_t offset
, uint32_t count
)
967 struct nrf5_info
*chip
;
969 int res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
973 assert(offset
% 4 == 0);
974 assert(count
% 4 == 0);
976 res
= nrf5_nvmc_write_enable(chip
);
980 res
= nrf5_ll_flash_write(chip
, bank
->base
+ offset
, buffer
, count
);
984 return nrf5_nvmc_read_only(chip
);
987 nrf5_nvmc_read_only(chip
);
988 LOG_ERROR("Failed to write to nrf5 flash");
992 static int nrf5_erase(struct flash_bank
*bank
, int first
, int last
)
995 struct nrf5_info
*chip
;
997 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
1001 /* For each sector to be erased */
1002 for (int s
= first
; s
<= last
&& res
== ERROR_OK
; s
++)
1003 res
= nrf5_erase_page(bank
, chip
, &bank
->sectors
[s
]);
1008 static void nrf5_free_driver_priv(struct flash_bank
*bank
)
1010 struct nrf5_bank
*nbank
= bank
->driver_priv
;
1011 struct nrf5_info
*chip
= nbank
->chip
;
1016 if (chip
->refcount
== 0) {
1018 bank
->driver_priv
= NULL
;
1022 FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command
)
1024 static struct nrf5_info
*chip
;
1025 struct nrf5_bank
*nbank
= NULL
;
1027 switch (bank
->base
) {
1028 case NRF5_FLASH_BASE
:
1029 case NRF5_UICR_BASE
:
1032 LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT
, bank
->base
);
1037 /* Create a new chip */
1038 chip
= calloc(1, sizeof(*chip
));
1042 chip
->target
= bank
->target
;
1045 switch (bank
->base
) {
1046 case NRF5_FLASH_BASE
:
1047 nbank
= &chip
->bank
[0];
1049 case NRF5_UICR_BASE
:
1050 nbank
= &chip
->bank
[1];
1053 assert(nbank
!= NULL
);
1057 nbank
->probed
= false;
1058 bank
->driver_priv
= nbank
;
1059 bank
->write_start_alignment
= bank
->write_end_alignment
= 4;
1064 COMMAND_HANDLER(nrf5_handle_mass_erase_command
)
1067 struct flash_bank
*bank
= NULL
;
1068 struct target
*target
= get_current_target(CMD_CTX
);
1070 res
= get_flash_bank_by_addr(target
, NRF5_FLASH_BASE
, true, &bank
);
1071 if (res
!= ERROR_OK
)
1074 assert(bank
!= NULL
);
1076 struct nrf5_info
*chip
;
1078 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
1079 if (res
!= ERROR_OK
)
1082 if (chip
->features
& NRF5_FEATURE_SERIES_51
) {
1084 res
= target_read_u32(target
, NRF51_FICR_PPFC
,
1086 if (res
!= ERROR_OK
) {
1087 LOG_ERROR("Couldn't read PPFC register");
1091 if ((ppfc
& 0xFF) == 0x00) {
1092 LOG_ERROR("Code region 0 size was pre-programmed at the factory, "
1093 "mass erase command won't work.");
1098 res
= nrf5_erase_all(chip
);
1099 if (res
!= ERROR_OK
) {
1100 LOG_ERROR("Failed to erase the chip");
1101 nrf5_protect_check(bank
);
1105 res
= nrf5_protect_check(bank
);
1106 if (res
!= ERROR_OK
) {
1107 LOG_ERROR("Failed to check chip's write protection");
1111 res
= get_flash_bank_by_addr(target
, NRF5_UICR_BASE
, true, &bank
);
1112 if (res
!= ERROR_OK
)
1118 COMMAND_HANDLER(nrf5_handle_info_command
)
1121 struct flash_bank
*bank
= NULL
;
1122 struct target
*target
= get_current_target(CMD_CTX
);
1124 res
= get_flash_bank_by_addr(target
, NRF5_FLASH_BASE
, true, &bank
);
1125 if (res
!= ERROR_OK
)
1128 assert(bank
!= NULL
);
1130 struct nrf5_info
*chip
;
1132 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
1133 if (res
!= ERROR_OK
)
1137 const uint32_t address
;
1140 { .address
= NRF5_FICR_CODEPAGESIZE
},
1141 { .address
= NRF5_FICR_CODESIZE
},
1142 { .address
= NRF51_FICR_CLENR0
},
1143 { .address
= NRF51_FICR_PPFC
},
1144 { .address
= NRF51_FICR_NUMRAMBLOCK
},
1145 { .address
= NRF51_FICR_SIZERAMBLOCK0
},
1146 { .address
= NRF51_FICR_SIZERAMBLOCK1
},
1147 { .address
= NRF51_FICR_SIZERAMBLOCK2
},
1148 { .address
= NRF51_FICR_SIZERAMBLOCK3
},
1149 { .address
= NRF5_FICR_CONFIGID
},
1150 { .address
= NRF5_FICR_DEVICEID0
},
1151 { .address
= NRF5_FICR_DEVICEID1
},
1152 { .address
= NRF5_FICR_ER0
},
1153 { .address
= NRF5_FICR_ER1
},
1154 { .address
= NRF5_FICR_ER2
},
1155 { .address
= NRF5_FICR_ER3
},
1156 { .address
= NRF5_FICR_IR0
},
1157 { .address
= NRF5_FICR_IR1
},
1158 { .address
= NRF5_FICR_IR2
},
1159 { .address
= NRF5_FICR_IR3
},
1160 { .address
= NRF5_FICR_DEVICEADDRTYPE
},
1161 { .address
= NRF5_FICR_DEVICEADDR0
},
1162 { .address
= NRF5_FICR_DEVICEADDR1
},
1163 { .address
= NRF51_FICR_OVERRIDEN
},
1164 { .address
= NRF51_FICR_NRF_1MBIT0
},
1165 { .address
= NRF51_FICR_NRF_1MBIT1
},
1166 { .address
= NRF51_FICR_NRF_1MBIT2
},
1167 { .address
= NRF51_FICR_NRF_1MBIT3
},
1168 { .address
= NRF51_FICR_NRF_1MBIT4
},
1169 { .address
= NRF51_FICR_BLE_1MBIT0
},
1170 { .address
= NRF51_FICR_BLE_1MBIT1
},
1171 { .address
= NRF51_FICR_BLE_1MBIT2
},
1172 { .address
= NRF51_FICR_BLE_1MBIT3
},
1173 { .address
= NRF51_FICR_BLE_1MBIT4
},
1175 { .address
= NRF51_UICR_CLENR0
, },
1176 { .address
= NRF51_UICR_RBPCONF
},
1177 { .address
= NRF51_UICR_XTALFREQ
},
1178 { .address
= NRF51_UICR_FWID
},
1181 for (size_t i
= 0; i
< ARRAY_SIZE(ficr
); i
++) {
1182 res
= target_read_u32(chip
->target
, ficr
[i
].address
,
1184 if (res
!= ERROR_OK
) {
1185 LOG_ERROR("Couldn't read %" PRIx32
, ficr
[i
].address
);
1190 for (size_t i
= 0; i
< ARRAY_SIZE(uicr
); i
++) {
1191 res
= target_read_u32(chip
->target
, uicr
[i
].address
,
1193 if (res
!= ERROR_OK
) {
1194 LOG_ERROR("Couldn't read %" PRIx32
, uicr
[i
].address
);
1200 "\n[factory information control block]\n\n"
1201 "code page size: %"PRIu32
"B\n"
1202 "code memory size: %"PRIu32
"kB\n"
1203 "code region 0 size: %"PRIu32
"kB\n"
1204 "pre-programmed code: %s\n"
1205 "number of ram blocks: %"PRIu32
"\n"
1206 "ram block 0 size: %"PRIu32
"B\n"
1207 "ram block 1 size: %"PRIu32
"B\n"
1208 "ram block 2 size: %"PRIu32
"B\n"
1209 "ram block 3 size: %"PRIu32
"B\n"
1210 "config id: %" PRIx32
"\n"
1211 "device id: 0x%"PRIx32
"%08"PRIx32
"\n"
1212 "encryption root: 0x%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"\n"
1213 "identity root: 0x%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"\n"
1214 "device address type: 0x%"PRIx32
"\n"
1215 "device address: 0x%"PRIx32
"%08"PRIx32
"\n"
1216 "override enable: %"PRIx32
"\n"
1217 "NRF_1MBIT values: %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
"\n"
1218 "BLE_1MBIT values: %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
"\n"
1219 "\n[user information control block]\n\n"
1220 "code region 0 size: %"PRIu32
"kB\n"
1221 "read back protection configuration: %"PRIx32
"\n"
1222 "reset value for XTALFREQ: %"PRIx32
"\n"
1223 "firmware id: 0x%04"PRIx32
,
1225 (ficr
[1].value
* ficr
[0].value
) / 1024,
1226 (ficr
[2].value
== 0xFFFFFFFF) ? 0 : ficr
[2].value
/ 1024,
1227 ((ficr
[3].value
& 0xFF) == 0x00) ? "present" : "not present",
1230 (ficr
[6].value
== 0xFFFFFFFF) ? 0 : ficr
[6].value
,
1231 (ficr
[7].value
== 0xFFFFFFFF) ? 0 : ficr
[7].value
,
1232 (ficr
[8].value
== 0xFFFFFFFF) ? 0 : ficr
[8].value
,
1234 ficr
[10].value
, ficr
[11].value
,
1235 ficr
[12].value
, ficr
[13].value
, ficr
[14].value
, ficr
[15].value
,
1236 ficr
[16].value
, ficr
[17].value
, ficr
[18].value
, ficr
[19].value
,
1238 ficr
[21].value
, ficr
[22].value
,
1240 ficr
[24].value
, ficr
[25].value
, ficr
[26].value
, ficr
[27].value
, ficr
[28].value
,
1241 ficr
[29].value
, ficr
[30].value
, ficr
[31].value
, ficr
[32].value
, ficr
[33].value
,
1242 (uicr
[0].value
== 0xFFFFFFFF) ? 0 : uicr
[0].value
/ 1024,
1243 uicr
[1].value
& 0xFFFF,
1244 uicr
[2].value
& 0xFF,
1245 uicr
[3].value
& 0xFFFF);
1250 static const struct command_registration nrf5_exec_command_handlers
[] = {
1252 .name
= "mass_erase",
1253 .handler
= nrf5_handle_mass_erase_command
,
1254 .mode
= COMMAND_EXEC
,
1255 .help
= "Erase all flash contents of the chip.",
1260 .handler
= nrf5_handle_info_command
,
1261 .mode
= COMMAND_EXEC
,
1262 .help
= "Show FICR and UICR info.",
1265 COMMAND_REGISTRATION_DONE
1268 static const struct command_registration nrf5_command_handlers
[] = {
1271 .mode
= COMMAND_ANY
,
1272 .help
= "nrf5 flash command group",
1274 .chain
= nrf5_exec_command_handlers
,
1278 .mode
= COMMAND_ANY
,
1279 .help
= "nrf51 flash command group",
1281 .chain
= nrf5_exec_command_handlers
,
1283 COMMAND_REGISTRATION_DONE
1286 const struct flash_driver nrf5_flash
= {
1288 .commands
= nrf5_command_handlers
,
1289 .flash_bank_command
= nrf5_flash_bank_command
,
1291 .erase
= nrf5_erase
,
1292 .protect
= nrf5_protect
,
1293 .write
= nrf5_write
,
1294 .read
= default_flash_read
,
1295 .probe
= nrf5_probe
,
1296 .auto_probe
= nrf5_auto_probe
,
1297 .erase_check
= default_flash_blank_check
,
1298 .protect_check
= nrf5_protect_check
,
1299 .free_driver_priv
= nrf5_free_driver_priv
,
1302 /* We need to retain the flash-driver name as well as the commands
1303 * for backwards compatability */
1304 const struct flash_driver nrf51_flash
= {
1306 .commands
= nrf5_command_handlers
,
1307 .flash_bank_command
= nrf5_flash_bank_command
,
1309 .erase
= nrf5_erase
,
1310 .protect
= nrf5_protect
,
1311 .write
= nrf5_write
,
1312 .read
= default_flash_read
,
1313 .probe
= nrf5_probe
,
1314 .auto_probe
= nrf5_auto_probe
,
1315 .erase_check
= default_flash_blank_check
,
1316 .protect_check
= nrf5_protect_check
,
1317 .free_driver_priv
= nrf5_free_driver_priv
,
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)