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),
42 NRF5_FICR_CLENR0
= NRF5_FICR_REG(0x028),
43 NRF5_FICR_PPFC
= NRF5_FICR_REG(0x02C),
44 NRF5_FICR_NUMRAMBLOCK
= NRF5_FICR_REG(0x034),
45 NRF5_FICR_SIZERAMBLOCK0
= NRF5_FICR_REG(0x038),
46 NRF5_FICR_SIZERAMBLOCK1
= NRF5_FICR_REG(0x03C),
47 NRF5_FICR_SIZERAMBLOCK2
= NRF5_FICR_REG(0x040),
48 NRF5_FICR_SIZERAMBLOCK3
= NRF5_FICR_REG(0x044),
49 NRF5_FICR_CONFIGID
= NRF5_FICR_REG(0x05C),
50 NRF5_FICR_DEVICEID0
= NRF5_FICR_REG(0x060),
51 NRF5_FICR_DEVICEID1
= NRF5_FICR_REG(0x064),
52 NRF5_FICR_ER0
= NRF5_FICR_REG(0x080),
53 NRF5_FICR_ER1
= NRF5_FICR_REG(0x084),
54 NRF5_FICR_ER2
= NRF5_FICR_REG(0x088),
55 NRF5_FICR_ER3
= NRF5_FICR_REG(0x08C),
56 NRF5_FICR_IR0
= NRF5_FICR_REG(0x090),
57 NRF5_FICR_IR1
= NRF5_FICR_REG(0x094),
58 NRF5_FICR_IR2
= NRF5_FICR_REG(0x098),
59 NRF5_FICR_IR3
= NRF5_FICR_REG(0x09C),
60 NRF5_FICR_DEVICEADDRTYPE
= NRF5_FICR_REG(0x0A0),
61 NRF5_FICR_DEVICEADDR0
= NRF5_FICR_REG(0x0A4),
62 NRF5_FICR_DEVICEADDR1
= NRF5_FICR_REG(0x0A8),
63 NRF5_FICR_OVERRIDEN
= NRF5_FICR_REG(0x0AC),
64 NRF5_FICR_NRF_1MBIT0
= NRF5_FICR_REG(0x0B0),
65 NRF5_FICR_NRF_1MBIT1
= NRF5_FICR_REG(0x0B4),
66 NRF5_FICR_NRF_1MBIT2
= NRF5_FICR_REG(0x0B8),
67 NRF5_FICR_NRF_1MBIT3
= NRF5_FICR_REG(0x0BC),
68 NRF5_FICR_NRF_1MBIT4
= NRF5_FICR_REG(0x0C0),
69 NRF5_FICR_BLE_1MBIT0
= NRF5_FICR_REG(0x0EC),
70 NRF5_FICR_BLE_1MBIT1
= NRF5_FICR_REG(0x0F0),
71 NRF5_FICR_BLE_1MBIT2
= NRF5_FICR_REG(0x0F4),
72 NRF5_FICR_BLE_1MBIT3
= NRF5_FICR_REG(0x0F8),
73 NRF5_FICR_BLE_1MBIT4
= NRF5_FICR_REG(0x0FC),
75 /* Following registers are available on nRF52 and on nRF51 since rev 3 */
76 NRF5_FICR_INFO_PART
= NRF5_FICR_REG(0x100),
77 NRF5_FICR_INFO_VARIANT
= NRF5_FICR_REG(0x104),
78 NRF5_FICR_INFO_PACKAGE
= NRF5_FICR_REG(0x108),
79 NRF5_FICR_INFO_RAM
= NRF5_FICR_REG(0x10C),
80 NRF5_FICR_INFO_FLASH
= NRF5_FICR_REG(0x110),
83 enum nrf5_uicr_registers
{
84 NRF5_UICR_BASE
= 0x10001000, /* User Information
85 * Configuration Regsters */
87 #define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset)
89 NRF5_UICR_CLENR0
= NRF5_UICR_REG(0x000),
90 NRF5_UICR_RBPCONF
= NRF5_UICR_REG(0x004),
91 NRF5_UICR_XTALFREQ
= NRF5_UICR_REG(0x008),
92 NRF5_UICR_FWID
= NRF5_UICR_REG(0x010),
95 enum nrf5_nvmc_registers
{
96 NRF5_NVMC_BASE
= 0x4001E000, /* Non-Volatile Memory
97 * Controller Registers */
99 #define NRF5_NVMC_REG(offset) (NRF5_NVMC_BASE + offset)
101 NRF5_NVMC_READY
= NRF5_NVMC_REG(0x400),
102 NRF5_NVMC_CONFIG
= NRF5_NVMC_REG(0x504),
103 NRF5_NVMC_ERASEPAGE
= NRF5_NVMC_REG(0x508),
104 NRF5_NVMC_ERASEALL
= NRF5_NVMC_REG(0x50C),
105 NRF5_NVMC_ERASEUICR
= NRF5_NVMC_REG(0x514),
107 NRF5_BPROT_BASE
= 0x40000000,
110 enum nrf5_nvmc_config_bits
{
111 NRF5_NVMC_CONFIG_REN
= 0x00,
112 NRF5_NVMC_CONFIG_WEN
= 0x01,
113 NRF5_NVMC_CONFIG_EEN
= 0x02,
117 struct nrf52_ficr_info
{
126 NRF5_FEATURE_SERIES_51
= 1 << 0,
127 NRF5_FEATURE_SERIES_52
= 1 << 1,
128 NRF5_FEATURE_BPROT
= 1 << 2,
129 NRF5_FEATURE_ACL_PROT
= 1 << 3,
132 struct nrf5_device_spec
{
136 const char *build_code
;
137 unsigned int flash_size_kb
;
138 enum nrf5_features features
;
145 struct nrf5_info
*chip
;
148 struct target
*target
;
150 /* chip identification stored in nrf5_probe() for use in nrf5_info() */
151 bool ficr_info_valid
;
152 struct nrf52_ficr_info ficr_info
;
153 const struct nrf5_device_spec
*spec
;
155 enum nrf5_features features
;
156 unsigned int flash_size_kb
;
159 #define NRF51_DEVICE_DEF(id, pt, var, bcode, fsize) \
164 .build_code = bcode, \
165 .flash_size_kb = (fsize), \
166 .features = NRF5_FEATURE_SERIES_51, \
169 #define NRF5_DEVICE_DEF(id, pt, var, bcode, fsize, features) \
174 .build_code = bcode, \
175 .flash_size_kb = (fsize), \
176 .features = features, \
179 /* The known devices table below is derived from the "nRF5x series
180 * compatibility matrix" documents, which can be found in the "DocLib" of
183 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51422_ic_revision_overview
184 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51822_ic_revision_overview
185 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51824_ic_revision_overview
186 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52810/latest/COMP/nrf52810/nRF52810_ic_revision_overview
187 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52832/latest/COMP/nrf52832/ic_revision_overview
188 * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52840/latest/COMP/nrf52840/nRF52840_ic_revision_overview
190 * Up to date with Matrix v2.0, plus some additional HWIDs.
192 * The additional HWIDs apply where the build code in the matrix is
193 * shown as Gx0, Bx0, etc. In these cases the HWID in the matrix is
194 * for x==0, x!=0 means different (unspecified) HWIDs.
196 static const struct nrf5_device_spec nrf5_known_devices_table
[] = {
197 /* nRF51822 Devices (IC rev 1). */
198 NRF51_DEVICE_DEF(0x001D, "51822", "QFAA", "CA/C0", 256),
199 NRF51_DEVICE_DEF(0x0026, "51822", "QFAB", "AA", 128),
200 NRF51_DEVICE_DEF(0x0027, "51822", "QFAB", "A0", 128),
201 NRF51_DEVICE_DEF(0x0020, "51822", "CEAA", "BA", 256),
202 NRF51_DEVICE_DEF(0x002F, "51822", "CEAA", "B0", 256),
204 /* Some early nRF51-DK (PCA10028) & nRF51-Dongle (PCA10031) boards
205 with built-in jlink seem to use engineering samples not listed
206 in the nRF51 Series Compatibility Matrix V1.0. */
207 NRF51_DEVICE_DEF(0x0071, "51822", "QFAC", "AB", 256),
209 /* nRF51822 Devices (IC rev 2). */
210 NRF51_DEVICE_DEF(0x002A, "51822", "QFAA", "FA0", 256),
211 NRF51_DEVICE_DEF(0x0044, "51822", "QFAA", "GC0", 256),
212 NRF51_DEVICE_DEF(0x003C, "51822", "QFAA", "G0", 256),
213 NRF51_DEVICE_DEF(0x0057, "51822", "QFAA", "G2", 256),
214 NRF51_DEVICE_DEF(0x0058, "51822", "QFAA", "G3", 256),
215 NRF51_DEVICE_DEF(0x004C, "51822", "QFAB", "B0", 128),
216 NRF51_DEVICE_DEF(0x0040, "51822", "CEAA", "CA0", 256),
217 NRF51_DEVICE_DEF(0x0047, "51822", "CEAA", "DA0", 256),
218 NRF51_DEVICE_DEF(0x004D, "51822", "CEAA", "D00", 256),
220 /* nRF51822 Devices (IC rev 3). */
221 NRF51_DEVICE_DEF(0x0072, "51822", "QFAA", "H0", 256),
222 NRF51_DEVICE_DEF(0x00D1, "51822", "QFAA", "H2", 256),
223 NRF51_DEVICE_DEF(0x007B, "51822", "QFAB", "C0", 128),
224 NRF51_DEVICE_DEF(0x0083, "51822", "QFAC", "A0", 256),
225 NRF51_DEVICE_DEF(0x0084, "51822", "QFAC", "A1", 256),
226 NRF51_DEVICE_DEF(0x007D, "51822", "CDAB", "A0", 128),
227 NRF51_DEVICE_DEF(0x0079, "51822", "CEAA", "E0", 256),
228 NRF51_DEVICE_DEF(0x0087, "51822", "CFAC", "A0", 256),
229 NRF51_DEVICE_DEF(0x008F, "51822", "QFAA", "H1", 256),
231 /* nRF51422 Devices (IC rev 1). */
232 NRF51_DEVICE_DEF(0x001E, "51422", "QFAA", "CA", 256),
233 NRF51_DEVICE_DEF(0x0024, "51422", "QFAA", "C0", 256),
234 NRF51_DEVICE_DEF(0x0031, "51422", "CEAA", "A0A", 256),
236 /* nRF51422 Devices (IC rev 2). */
237 NRF51_DEVICE_DEF(0x002D, "51422", "QFAA", "DAA", 256),
238 NRF51_DEVICE_DEF(0x002E, "51422", "QFAA", "E0", 256),
239 NRF51_DEVICE_DEF(0x0061, "51422", "QFAB", "A00", 128),
240 NRF51_DEVICE_DEF(0x0050, "51422", "CEAA", "B0", 256),
242 /* nRF51422 Devices (IC rev 3). */
243 NRF51_DEVICE_DEF(0x0073, "51422", "QFAA", "F0", 256),
244 NRF51_DEVICE_DEF(0x007C, "51422", "QFAB", "B0", 128),
245 NRF51_DEVICE_DEF(0x0085, "51422", "QFAC", "A0", 256),
246 NRF51_DEVICE_DEF(0x0086, "51422", "QFAC", "A1", 256),
247 NRF51_DEVICE_DEF(0x007E, "51422", "CDAB", "A0", 128),
248 NRF51_DEVICE_DEF(0x007A, "51422", "CEAA", "C0", 256),
249 NRF51_DEVICE_DEF(0x0088, "51422", "CFAC", "A0", 256),
251 /* The driver fully autodects nRF52 series devices by FICR INFO,
252 * no need for nRF52xxx HWIDs in this table */
254 /* nRF52810 Devices */
255 NRF5_DEVICE_DEF(0x0142, "52810", "QFAA", "B0", 192, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
256 NRF5_DEVICE_DEF(0x0143, "52810", "QCAA", "C0", 192, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
258 /* nRF52832 Devices */
259 NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0", 512, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
260 NRF5_DEVICE_DEF(0x0139, "52832", "QFAA", "E0", 512, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
261 NRF5_DEVICE_DEF(0x00E3, "52832", "CIAA", "B0", 512, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_BPROT
),
263 /* nRF52840 Devices */
264 NRF5_DEVICE_DEF(0x0150, "52840", "QIAA", "C0", 1024, NRF5_FEATURE_SERIES_52
| NRF5_FEATURE_ACL_PROT
),
268 struct nrf5_device_package
{
273 /* Newer devices have FICR INFO.PACKAGE.
274 * This table converts its value to two character code */
275 static const struct nrf5_device_package nrf5_packages_table
[] = {
282 static int nrf5_bank_is_probed(struct flash_bank
*bank
)
284 struct nrf5_bank
*nbank
= bank
->driver_priv
;
286 assert(nbank
!= NULL
);
288 return nbank
->probed
;
290 static int nrf5_probe(struct flash_bank
*bank
);
292 static int nrf5_get_probed_chip_if_halted(struct flash_bank
*bank
, struct nrf5_info
**chip
)
294 if (bank
->target
->state
!= TARGET_HALTED
) {
295 LOG_ERROR("Target not halted");
296 return ERROR_TARGET_NOT_HALTED
;
299 struct nrf5_bank
*nbank
= bank
->driver_priv
;
302 int probed
= nrf5_bank_is_probed(bank
);
306 return nrf5_probe(bank
);
311 static int nrf5_wait_for_nvmc(struct nrf5_info
*chip
)
315 int timeout_ms
= 340;
316 int64_t ts_start
= timeval_ms();
319 res
= target_read_u32(chip
->target
, NRF5_NVMC_READY
, &ready
);
320 if (res
!= ERROR_OK
) {
321 LOG_ERROR("Couldn't read NVMC_READY register");
325 if (ready
== 0x00000001)
330 } while ((timeval_ms()-ts_start
) < timeout_ms
);
332 LOG_DEBUG("Timed out waiting for NVMC_READY");
333 return ERROR_FLASH_BUSY
;
336 static int nrf5_nvmc_erase_enable(struct nrf5_info
*chip
)
339 res
= target_write_u32(chip
->target
,
341 NRF5_NVMC_CONFIG_EEN
);
343 if (res
!= ERROR_OK
) {
344 LOG_ERROR("Failed to enable erase operation");
349 According to NVMC examples in Nordic SDK busy status must be
350 checked after writing to NVMC_CONFIG
352 res
= nrf5_wait_for_nvmc(chip
);
354 LOG_ERROR("Erase enable did not complete");
359 static int nrf5_nvmc_write_enable(struct nrf5_info
*chip
)
362 res
= target_write_u32(chip
->target
,
364 NRF5_NVMC_CONFIG_WEN
);
366 if (res
!= ERROR_OK
) {
367 LOG_ERROR("Failed to enable write operation");
372 According to NVMC examples in Nordic SDK busy status must be
373 checked after writing to NVMC_CONFIG
375 res
= nrf5_wait_for_nvmc(chip
);
377 LOG_ERROR("Write enable did not complete");
382 static int nrf5_nvmc_read_only(struct nrf5_info
*chip
)
385 res
= target_write_u32(chip
->target
,
387 NRF5_NVMC_CONFIG_REN
);
389 if (res
!= ERROR_OK
) {
390 LOG_ERROR("Failed to enable read-only operation");
394 According to NVMC examples in Nordic SDK busy status must be
395 checked after writing to NVMC_CONFIG
397 res
= nrf5_wait_for_nvmc(chip
);
399 LOG_ERROR("Read only enable did not complete");
404 static int nrf5_nvmc_generic_erase(struct nrf5_info
*chip
,
405 uint32_t erase_register
, uint32_t erase_value
)
409 res
= nrf5_nvmc_erase_enable(chip
);
413 res
= target_write_u32(chip
->target
,
419 res
= nrf5_wait_for_nvmc(chip
);
423 return nrf5_nvmc_read_only(chip
);
426 nrf5_nvmc_read_only(chip
);
428 LOG_ERROR("Failed to erase reg: 0x%08"PRIx32
" val: 0x%08"PRIx32
,
429 erase_register
, erase_value
);
433 static int nrf5_protect_check_bprot(struct flash_bank
*bank
)
435 struct nrf5_bank
*nbank
= bank
->driver_priv
;
436 struct nrf5_info
*chip
= nbank
->chip
;
438 assert(chip
!= NULL
);
440 static uint32_t nrf5_bprot_offsets
[4] = { 0x600, 0x604, 0x610, 0x614 };
441 uint32_t bprot_reg
= 0;
444 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
445 unsigned int bit
= i
% 32;
447 unsigned int n_reg
= i
/ 32;
448 if (n_reg
>= ARRAY_SIZE(nrf5_bprot_offsets
))
451 res
= target_read_u32(chip
->target
, NRF5_BPROT_BASE
+ nrf5_bprot_offsets
[n_reg
], &bprot_reg
);
455 bank
->sectors
[i
].is_protected
= (bprot_reg
& (1 << bit
)) ? 1 : 0;
460 static int nrf5_protect_check(struct flash_bank
*bank
)
465 /* UICR cannot be write protected so just return early */
466 if (bank
->base
== NRF5_UICR_BASE
)
469 struct nrf5_bank
*nbank
= bank
->driver_priv
;
470 struct nrf5_info
*chip
= nbank
->chip
;
472 assert(chip
!= NULL
);
474 if (chip
->features
& NRF5_FEATURE_BPROT
)
475 return nrf5_protect_check_bprot(bank
);
477 if (!(chip
->features
& NRF5_FEATURE_SERIES_51
)) {
478 LOG_WARNING("Flash protection of this nRF device is not supported");
479 return ERROR_FLASH_OPER_UNSUPPORTED
;
482 res
= target_read_u32(chip
->target
, NRF5_FICR_CLENR0
,
484 if (res
!= ERROR_OK
) {
485 LOG_ERROR("Couldn't read code region 0 size[FICR]");
489 if (clenr0
== 0xFFFFFFFF) {
490 res
= target_read_u32(chip
->target
, NRF5_UICR_CLENR0
,
492 if (res
!= ERROR_OK
) {
493 LOG_ERROR("Couldn't read code region 0 size[UICR]");
498 for (int i
= 0; i
< bank
->num_sectors
; i
++)
499 bank
->sectors
[i
].is_protected
=
500 clenr0
!= 0xFFFFFFFF && bank
->sectors
[i
].offset
< clenr0
;
505 static int nrf5_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
508 uint32_t clenr0
, ppfc
;
509 struct nrf5_info
*chip
;
511 /* UICR cannot be write protected so just bail out early */
512 if (bank
->base
== NRF5_UICR_BASE
)
515 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
519 if (!(chip
->features
& NRF5_FEATURE_SERIES_51
)) {
520 LOG_ERROR("Flash protection setting of this nRF device is not supported");
521 return ERROR_FLASH_OPER_UNSUPPORTED
;
525 LOG_ERROR("Code region 0 must start at the begining of the bank");
529 res
= target_read_u32(chip
->target
, NRF5_FICR_PPFC
,
531 if (res
!= ERROR_OK
) {
532 LOG_ERROR("Couldn't read PPFC register");
536 if ((ppfc
& 0xFF) == 0x00) {
537 LOG_ERROR("Code region 0 size was pre-programmed at the factory, can't change flash protection settings");
541 res
= target_read_u32(chip
->target
, NRF5_UICR_CLENR0
,
543 if (res
!= ERROR_OK
) {
544 LOG_ERROR("Couldn't read code region 0 size[UICR]");
548 if (clenr0
== 0xFFFFFFFF) {
549 res
= target_write_u32(chip
->target
, NRF5_UICR_CLENR0
,
551 if (res
!= ERROR_OK
) {
552 LOG_ERROR("Couldn't write code region 0 size[UICR]");
557 LOG_ERROR("You need to perform chip erase before changing the protection settings");
560 nrf5_protect_check(bank
);
565 static bool nrf5_info_variant_to_str(uint32_t variant
, char *bf
)
567 h_u32_to_be((uint8_t *)bf
, variant
);
569 if (isalnum(bf
[0]) && isalnum(bf
[1]) && isalnum(bf
[2]) && isalnum(bf
[3]))
576 static const char *nrf5_decode_info_package(uint32_t package
)
578 for (size_t i
= 0; i
< ARRAY_SIZE(nrf5_packages_table
); i
++) {
579 if (nrf5_packages_table
[i
].package
== package
)
580 return nrf5_packages_table
[i
].code
;
585 static int nrf5_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
587 struct nrf5_bank
*nbank
= bank
->driver_priv
;
588 struct nrf5_info
*chip
= nbank
->chip
;
591 snprintf(buf
, buf_size
,
592 "nRF%s-%s(build code: %s) %ukB Flash",
593 chip
->spec
->part
, chip
->spec
->variant
, chip
->spec
->build_code
,
594 chip
->flash_size_kb
);
596 } else if (chip
->ficr_info_valid
) {
598 nrf5_info_variant_to_str(chip
->ficr_info
.variant
, variant
);
599 snprintf(buf
, buf_size
,
600 "nRF%" PRIx32
"-%s%.2s(build code: %s) %" PRIu32
601 "kB Flash, %" PRIu32
"kB RAM",
602 chip
->ficr_info
.part
,
603 nrf5_decode_info_package(chip
->ficr_info
.package
),
604 variant
, &variant
[2],
606 chip
->ficr_info
.ram
);
609 snprintf(buf
, buf_size
, "nRF51xxx (HWID 0x%04" PRIx16
") %ukB Flash",
610 chip
->hwid
, chip
->flash_size_kb
);
615 static int nrf5_read_ficr_info(struct nrf5_info
*chip
)
618 struct target
*target
= chip
->target
;
620 chip
->ficr_info_valid
= false;
622 res
= target_read_u32(target
, NRF5_FICR_INFO_PART
, &chip
->ficr_info
.part
);
623 if (res
!= ERROR_OK
) {
624 LOG_DEBUG("Couldn't read FICR INFO.PART register");
628 uint32_t series
= chip
->ficr_info
.part
& 0xfffff000;
631 chip
->features
= NRF5_FEATURE_SERIES_51
;
635 chip
->features
= NRF5_FEATURE_SERIES_52
;
637 switch (chip
->ficr_info
.part
) {
640 chip
->features
|= NRF5_FEATURE_BPROT
;
644 chip
->features
|= NRF5_FEATURE_ACL_PROT
;
650 LOG_DEBUG("FICR INFO likely not implemented. Invalid PART value 0x%08"
651 PRIx32
, chip
->ficr_info
.part
);
652 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
655 /* Now we know the device has FICR INFO filled by something relevant:
656 * Although it is not documented, the tested nRF51 rev 3 devices
657 * have FICR INFO.PART, RAM and FLASH of the same format as nRF52.
658 * VARIANT and PACKAGE coding is unknown for a nRF51 device.
659 * nRF52 devices have FICR INFO documented and always filled. */
661 res
= target_read_u32(target
, NRF5_FICR_INFO_VARIANT
, &chip
->ficr_info
.variant
);
665 res
= target_read_u32(target
, NRF5_FICR_INFO_PACKAGE
, &chip
->ficr_info
.package
);
669 res
= target_read_u32(target
, NRF5_FICR_INFO_RAM
, &chip
->ficr_info
.ram
);
673 res
= target_read_u32(target
, NRF5_FICR_INFO_FLASH
, &chip
->ficr_info
.flash
);
677 chip
->ficr_info_valid
= true;
681 static int nrf5_probe(struct flash_bank
*bank
)
684 struct nrf5_bank
*nbank
= bank
->driver_priv
;
685 struct nrf5_info
*chip
= nbank
->chip
;
686 struct target
*target
= chip
->target
;
688 res
= target_read_u32(target
, NRF5_FICR_CONFIGID
, &chip
->hwid
);
689 if (res
!= ERROR_OK
) {
690 LOG_ERROR("Couldn't read CONFIGID register");
694 chip
->hwid
&= 0xFFFF; /* HWID is stored in the lower two
695 * bytes of the CONFIGID register */
697 /* guess a nRF51 series if the device has no FICR INFO and we don't know HWID */
698 chip
->features
= NRF5_FEATURE_SERIES_51
;
700 /* Don't bail out on error for the case that some old engineering
701 * sample has FICR INFO registers unreadable. We can proceed anyway. */
702 (void)nrf5_read_ficr_info(chip
);
705 for (size_t i
= 0; i
< ARRAY_SIZE(nrf5_known_devices_table
); i
++) {
706 if (chip
->hwid
== nrf5_known_devices_table
[i
].hwid
) {
707 chip
->spec
= &nrf5_known_devices_table
[i
];
708 chip
->features
= chip
->spec
->features
;
713 if (chip
->spec
&& chip
->ficr_info_valid
) {
714 /* check if HWID table gives the same part as FICR INFO */
715 if (chip
->ficr_info
.part
!= strtoul(chip
->spec
->part
, NULL
, 16))
716 LOG_WARNING("HWID 0x%04" PRIx32
" mismatch: FICR INFO.PART %"
717 PRIx32
, chip
->hwid
, chip
->ficr_info
.part
);
720 /* The value stored in NRF5_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */
721 uint32_t flash_page_size
;
722 res
= target_read_u32(chip
->target
, NRF5_FICR_CODEPAGESIZE
,
724 if (res
!= ERROR_OK
) {
725 LOG_ERROR("Couldn't read code page size");
729 /* Note the register name is misleading,
730 * NRF5_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */
731 uint32_t num_sectors
;
732 res
= target_read_u32(chip
->target
, NRF5_FICR_CODESIZE
, &num_sectors
);
733 if (res
!= ERROR_OK
) {
734 LOG_ERROR("Couldn't read code memory size");
738 chip
->flash_size_kb
= num_sectors
* flash_page_size
/ 1024;
740 if (!chip
->bank
[0].probed
&& !chip
->bank
[1].probed
) {
742 nrf5_info(bank
, buf
, sizeof(buf
));
743 if (!chip
->spec
&& !chip
->ficr_info_valid
) {
744 LOG_INFO("Unknown device: %s", buf
);
750 if (bank
->base
== NRF5_FLASH_BASE
) {
752 if (chip
->spec
&& chip
->flash_size_kb
!= chip
->spec
->flash_size_kb
)
753 LOG_WARNING("Chip's reported Flash capacity does not match expected one");
754 if (chip
->ficr_info_valid
&& chip
->flash_size_kb
!= chip
->ficr_info
.flash
)
755 LOG_WARNING("Chip's reported Flash capacity does not match FICR INFO.FLASH");
757 bank
->num_sectors
= num_sectors
;
758 bank
->size
= num_sectors
* flash_page_size
;
760 bank
->sectors
= alloc_block_array(0, flash_page_size
, num_sectors
);
764 nrf5_protect_check(bank
);
766 chip
->bank
[0].probed
= true;
769 bank
->num_sectors
= 1;
770 bank
->size
= flash_page_size
;
772 bank
->sectors
= alloc_block_array(0, flash_page_size
, num_sectors
);
776 bank
->sectors
[0].is_protected
= 0;
778 chip
->bank
[1].probed
= true;
784 static int nrf5_auto_probe(struct flash_bank
*bank
)
786 int probed
= nrf5_bank_is_probed(bank
);
793 return nrf5_probe(bank
);
796 static int nrf5_erase_all(struct nrf5_info
*chip
)
798 LOG_DEBUG("Erasing all non-volatile memory");
799 return nrf5_nvmc_generic_erase(chip
,
804 static int nrf5_erase_page(struct flash_bank
*bank
,
805 struct nrf5_info
*chip
,
806 struct flash_sector
*sector
)
810 LOG_DEBUG("Erasing page at 0x%"PRIx32
, sector
->offset
);
811 if (sector
->is_protected
) {
812 LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32
, sector
->offset
);
816 if (bank
->base
== NRF5_UICR_BASE
) {
818 res
= target_read_u32(chip
->target
, NRF5_FICR_PPFC
,
820 if (res
!= ERROR_OK
) {
821 LOG_ERROR("Couldn't read PPFC register");
825 if ((ppfc
& 0xFF) == 0xFF) {
826 /* We can't erase the UICR. Double-check to
827 see if it's already erased before complaining. */
828 default_flash_blank_check(bank
);
829 if (sector
->is_erased
== 1)
832 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");
836 res
= nrf5_nvmc_generic_erase(chip
,
842 res
= nrf5_nvmc_generic_erase(chip
,
850 static const uint8_t nrf5_flash_write_code
[] = {
851 /* See contrib/loaders/flash/cortex-m0.S */
853 0x0d, 0x68, /* ldr r5, [r1, #0] */
854 0x00, 0x2d, /* cmp r5, #0 */
855 0x0b, 0xd0, /* beq.n 1e <exit> */
856 0x4c, 0x68, /* ldr r4, [r1, #4] */
857 0xac, 0x42, /* cmp r4, r5 */
858 0xf9, 0xd0, /* beq.n 0 <wait_fifo> */
859 0x20, 0xcc, /* ldmia r4!, {r5} */
860 0x20, 0xc3, /* stmia r3!, {r5} */
861 0x94, 0x42, /* cmp r4, r2 */
862 0x01, 0xd3, /* bcc.n 18 <no_wrap> */
863 0x0c, 0x46, /* mov r4, r1 */
864 0x08, 0x34, /* adds r4, #8 */
866 0x4c, 0x60, /* str r4, [r1, #4] */
867 0x04, 0x38, /* subs r0, #4 */
868 0xf0, 0xd1, /* bne.n 0 <wait_fifo> */
870 0x00, 0xbe /* bkpt 0x0000 */
874 /* Start a low level flash write for the specified region */
875 static int nrf5_ll_flash_write(struct nrf5_info
*chip
, uint32_t address
, const uint8_t *buffer
, uint32_t bytes
)
877 struct target
*target
= chip
->target
;
878 uint32_t buffer_size
= 8192;
879 struct working_area
*write_algorithm
;
880 struct working_area
*source
;
881 struct reg_param reg_params
[4];
882 struct armv7m_algorithm armv7m_info
;
883 int retval
= ERROR_OK
;
885 LOG_DEBUG("Writing buffer to flash address=0x%"PRIx32
" bytes=0x%"PRIx32
, address
, bytes
);
886 assert(bytes
% 4 == 0);
888 /* allocate working area with flash programming code */
889 if (target_alloc_working_area(target
, sizeof(nrf5_flash_write_code
),
890 &write_algorithm
) != ERROR_OK
) {
891 LOG_WARNING("no working area available, falling back to slow memory writes");
893 for (; bytes
> 0; bytes
-= 4) {
894 retval
= target_write_memory(target
, address
, 4, 1, buffer
);
895 if (retval
!= ERROR_OK
)
898 retval
= nrf5_wait_for_nvmc(chip
);
899 if (retval
!= ERROR_OK
)
909 retval
= target_write_buffer(target
, write_algorithm
->address
,
910 sizeof(nrf5_flash_write_code
),
911 nrf5_flash_write_code
);
912 if (retval
!= ERROR_OK
)
916 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
) {
918 buffer_size
&= ~3UL; /* Make sure it's 4 byte aligned */
919 if (buffer_size
<= 256) {
920 /* free working area, write algorithm already allocated */
921 target_free_working_area(target
, write_algorithm
);
923 LOG_WARNING("No large enough working area available, can't do block memory writes");
924 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
928 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
929 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
931 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
); /* byte count */
932 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
); /* buffer start */
933 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
); /* buffer end */
934 init_reg_param(®_params
[3], "r3", 32, PARAM_IN_OUT
); /* target address */
936 buf_set_u32(reg_params
[0].value
, 0, 32, bytes
);
937 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
);
938 buf_set_u32(reg_params
[2].value
, 0, 32, source
->address
+ source
->size
);
939 buf_set_u32(reg_params
[3].value
, 0, 32, address
);
941 retval
= target_run_flash_async_algorithm(target
, buffer
, bytes
/4, 4,
944 source
->address
, source
->size
,
945 write_algorithm
->address
, 0,
948 target_free_working_area(target
, source
);
949 target_free_working_area(target
, write_algorithm
);
951 destroy_reg_param(®_params
[0]);
952 destroy_reg_param(®_params
[1]);
953 destroy_reg_param(®_params
[2]);
954 destroy_reg_param(®_params
[3]);
959 static int nrf5_write(struct flash_bank
*bank
, const uint8_t *buffer
,
960 uint32_t offset
, uint32_t count
)
962 struct nrf5_info
*chip
;
964 int res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
968 assert(offset
% 4 == 0);
969 assert(count
% 4 == 0);
971 res
= nrf5_nvmc_write_enable(chip
);
975 res
= nrf5_ll_flash_write(chip
, bank
->base
+ offset
, buffer
, count
);
979 return nrf5_nvmc_read_only(chip
);
982 nrf5_nvmc_read_only(chip
);
983 LOG_ERROR("Failed to write to nrf5 flash");
987 static int nrf5_erase(struct flash_bank
*bank
, int first
, int last
)
990 struct nrf5_info
*chip
;
992 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
996 /* For each sector to be erased */
997 for (int s
= first
; s
<= last
&& res
== ERROR_OK
; s
++)
998 res
= nrf5_erase_page(bank
, chip
, &bank
->sectors
[s
]);
1003 static void nrf5_free_driver_priv(struct flash_bank
*bank
)
1005 struct nrf5_bank
*nbank
= bank
->driver_priv
;
1006 struct nrf5_info
*chip
= nbank
->chip
;
1011 if (chip
->refcount
== 0) {
1013 bank
->driver_priv
= NULL
;
1017 FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command
)
1019 static struct nrf5_info
*chip
;
1020 struct nrf5_bank
*nbank
= NULL
;
1022 switch (bank
->base
) {
1023 case NRF5_FLASH_BASE
:
1024 case NRF5_UICR_BASE
:
1027 LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT
, bank
->base
);
1032 /* Create a new chip */
1033 chip
= calloc(1, sizeof(*chip
));
1037 chip
->target
= bank
->target
;
1040 switch (bank
->base
) {
1041 case NRF5_FLASH_BASE
:
1042 nbank
= &chip
->bank
[0];
1044 case NRF5_UICR_BASE
:
1045 nbank
= &chip
->bank
[1];
1048 assert(nbank
!= NULL
);
1052 nbank
->probed
= false;
1053 bank
->driver_priv
= nbank
;
1054 bank
->write_start_alignment
= bank
->write_end_alignment
= 4;
1059 COMMAND_HANDLER(nrf5_handle_mass_erase_command
)
1062 struct flash_bank
*bank
= NULL
;
1063 struct target
*target
= get_current_target(CMD_CTX
);
1065 res
= get_flash_bank_by_addr(target
, NRF5_FLASH_BASE
, true, &bank
);
1066 if (res
!= ERROR_OK
)
1069 assert(bank
!= NULL
);
1071 struct nrf5_info
*chip
;
1073 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
1074 if (res
!= ERROR_OK
)
1079 res
= target_read_u32(target
, NRF5_FICR_PPFC
,
1081 if (res
!= ERROR_OK
) {
1082 LOG_ERROR("Couldn't read PPFC register");
1086 if ((ppfc
& 0xFF) == 0x00) {
1087 LOG_ERROR("Code region 0 size was pre-programmed at the factory, "
1088 "mass erase command won't work.");
1092 res
= nrf5_erase_all(chip
);
1093 if (res
!= ERROR_OK
) {
1094 LOG_ERROR("Failed to erase the chip");
1095 nrf5_protect_check(bank
);
1099 res
= nrf5_protect_check(bank
);
1100 if (res
!= ERROR_OK
) {
1101 LOG_ERROR("Failed to check chip's write protection");
1105 res
= get_flash_bank_by_addr(target
, NRF5_UICR_BASE
, true, &bank
);
1106 if (res
!= ERROR_OK
)
1112 COMMAND_HANDLER(nrf5_handle_info_command
)
1115 struct flash_bank
*bank
= NULL
;
1116 struct target
*target
= get_current_target(CMD_CTX
);
1118 res
= get_flash_bank_by_addr(target
, NRF5_FLASH_BASE
, true, &bank
);
1119 if (res
!= ERROR_OK
)
1122 assert(bank
!= NULL
);
1124 struct nrf5_info
*chip
;
1126 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
1127 if (res
!= ERROR_OK
)
1131 const uint32_t address
;
1134 { .address
= NRF5_FICR_CODEPAGESIZE
},
1135 { .address
= NRF5_FICR_CODESIZE
},
1136 { .address
= NRF5_FICR_CLENR0
},
1137 { .address
= NRF5_FICR_PPFC
},
1138 { .address
= NRF5_FICR_NUMRAMBLOCK
},
1139 { .address
= NRF5_FICR_SIZERAMBLOCK0
},
1140 { .address
= NRF5_FICR_SIZERAMBLOCK1
},
1141 { .address
= NRF5_FICR_SIZERAMBLOCK2
},
1142 { .address
= NRF5_FICR_SIZERAMBLOCK3
},
1143 { .address
= NRF5_FICR_CONFIGID
},
1144 { .address
= NRF5_FICR_DEVICEID0
},
1145 { .address
= NRF5_FICR_DEVICEID1
},
1146 { .address
= NRF5_FICR_ER0
},
1147 { .address
= NRF5_FICR_ER1
},
1148 { .address
= NRF5_FICR_ER2
},
1149 { .address
= NRF5_FICR_ER3
},
1150 { .address
= NRF5_FICR_IR0
},
1151 { .address
= NRF5_FICR_IR1
},
1152 { .address
= NRF5_FICR_IR2
},
1153 { .address
= NRF5_FICR_IR3
},
1154 { .address
= NRF5_FICR_DEVICEADDRTYPE
},
1155 { .address
= NRF5_FICR_DEVICEADDR0
},
1156 { .address
= NRF5_FICR_DEVICEADDR1
},
1157 { .address
= NRF5_FICR_OVERRIDEN
},
1158 { .address
= NRF5_FICR_NRF_1MBIT0
},
1159 { .address
= NRF5_FICR_NRF_1MBIT1
},
1160 { .address
= NRF5_FICR_NRF_1MBIT2
},
1161 { .address
= NRF5_FICR_NRF_1MBIT3
},
1162 { .address
= NRF5_FICR_NRF_1MBIT4
},
1163 { .address
= NRF5_FICR_BLE_1MBIT0
},
1164 { .address
= NRF5_FICR_BLE_1MBIT1
},
1165 { .address
= NRF5_FICR_BLE_1MBIT2
},
1166 { .address
= NRF5_FICR_BLE_1MBIT3
},
1167 { .address
= NRF5_FICR_BLE_1MBIT4
},
1169 { .address
= NRF5_UICR_CLENR0
, },
1170 { .address
= NRF5_UICR_RBPCONF
},
1171 { .address
= NRF5_UICR_XTALFREQ
},
1172 { .address
= NRF5_UICR_FWID
},
1175 for (size_t i
= 0; i
< ARRAY_SIZE(ficr
); i
++) {
1176 res
= target_read_u32(chip
->target
, ficr
[i
].address
,
1178 if (res
!= ERROR_OK
) {
1179 LOG_ERROR("Couldn't read %" PRIx32
, ficr
[i
].address
);
1184 for (size_t i
= 0; i
< ARRAY_SIZE(uicr
); i
++) {
1185 res
= target_read_u32(chip
->target
, uicr
[i
].address
,
1187 if (res
!= ERROR_OK
) {
1188 LOG_ERROR("Couldn't read %" PRIx32
, uicr
[i
].address
);
1194 "\n[factory information control block]\n\n"
1195 "code page size: %"PRIu32
"B\n"
1196 "code memory size: %"PRIu32
"kB\n"
1197 "code region 0 size: %"PRIu32
"kB\n"
1198 "pre-programmed code: %s\n"
1199 "number of ram blocks: %"PRIu32
"\n"
1200 "ram block 0 size: %"PRIu32
"B\n"
1201 "ram block 1 size: %"PRIu32
"B\n"
1202 "ram block 2 size: %"PRIu32
"B\n"
1203 "ram block 3 size: %"PRIu32
"B\n"
1204 "config id: %" PRIx32
"\n"
1205 "device id: 0x%"PRIx32
"%08"PRIx32
"\n"
1206 "encryption root: 0x%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"\n"
1207 "identity root: 0x%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"\n"
1208 "device address type: 0x%"PRIx32
"\n"
1209 "device address: 0x%"PRIx32
"%08"PRIx32
"\n"
1210 "override enable: %"PRIx32
"\n"
1211 "NRF_1MBIT values: %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
"\n"
1212 "BLE_1MBIT values: %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
"\n"
1213 "\n[user information control block]\n\n"
1214 "code region 0 size: %"PRIu32
"kB\n"
1215 "read back protection configuration: %"PRIx32
"\n"
1216 "reset value for XTALFREQ: %"PRIx32
"\n"
1217 "firmware id: 0x%04"PRIx32
,
1219 (ficr
[1].value
* ficr
[0].value
) / 1024,
1220 (ficr
[2].value
== 0xFFFFFFFF) ? 0 : ficr
[2].value
/ 1024,
1221 ((ficr
[3].value
& 0xFF) == 0x00) ? "present" : "not present",
1224 (ficr
[6].value
== 0xFFFFFFFF) ? 0 : ficr
[6].value
,
1225 (ficr
[7].value
== 0xFFFFFFFF) ? 0 : ficr
[7].value
,
1226 (ficr
[8].value
== 0xFFFFFFFF) ? 0 : ficr
[8].value
,
1228 ficr
[10].value
, ficr
[11].value
,
1229 ficr
[12].value
, ficr
[13].value
, ficr
[14].value
, ficr
[15].value
,
1230 ficr
[16].value
, ficr
[17].value
, ficr
[18].value
, ficr
[19].value
,
1232 ficr
[21].value
, ficr
[22].value
,
1234 ficr
[24].value
, ficr
[25].value
, ficr
[26].value
, ficr
[27].value
, ficr
[28].value
,
1235 ficr
[29].value
, ficr
[30].value
, ficr
[31].value
, ficr
[32].value
, ficr
[33].value
,
1236 (uicr
[0].value
== 0xFFFFFFFF) ? 0 : uicr
[0].value
/ 1024,
1237 uicr
[1].value
& 0xFFFF,
1238 uicr
[2].value
& 0xFF,
1239 uicr
[3].value
& 0xFFFF);
1244 static const struct command_registration nrf5_exec_command_handlers
[] = {
1246 .name
= "mass_erase",
1247 .handler
= nrf5_handle_mass_erase_command
,
1248 .mode
= COMMAND_EXEC
,
1249 .help
= "Erase all flash contents of the chip.",
1254 .handler
= nrf5_handle_info_command
,
1255 .mode
= COMMAND_EXEC
,
1256 .help
= "Show FICR and UICR info.",
1259 COMMAND_REGISTRATION_DONE
1262 static const struct command_registration nrf5_command_handlers
[] = {
1265 .mode
= COMMAND_ANY
,
1266 .help
= "nrf5 flash command group",
1268 .chain
= nrf5_exec_command_handlers
,
1272 .mode
= COMMAND_ANY
,
1273 .help
= "nrf51 flash command group",
1275 .chain
= nrf5_exec_command_handlers
,
1277 COMMAND_REGISTRATION_DONE
1280 const struct flash_driver nrf5_flash
= {
1282 .commands
= nrf5_command_handlers
,
1283 .flash_bank_command
= nrf5_flash_bank_command
,
1285 .erase
= nrf5_erase
,
1286 .protect
= nrf5_protect
,
1287 .write
= nrf5_write
,
1288 .read
= default_flash_read
,
1289 .probe
= nrf5_probe
,
1290 .auto_probe
= nrf5_auto_probe
,
1291 .erase_check
= default_flash_blank_check
,
1292 .protect_check
= nrf5_protect_check
,
1293 .free_driver_priv
= nrf5_free_driver_priv
,
1296 /* We need to retain the flash-driver name as well as the commands
1297 * for backwards compatability */
1298 const struct flash_driver nrf51_flash
= {
1300 .commands
= nrf5_command_handlers
,
1301 .flash_bank_command
= nrf5_flash_bank_command
,
1303 .erase
= nrf5_erase
,
1304 .protect
= nrf5_protect
,
1305 .write
= nrf5_write
,
1306 .read
= default_flash_read
,
1307 .probe
= nrf5_probe
,
1308 .auto_probe
= nrf5_auto_probe
,
1309 .erase_check
= default_flash_blank_check
,
1310 .protect_check
= nrf5_protect_check
,
1311 .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)