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
) {
821 res
= target_read_u32(chip
->target
, NRF51_FICR_PPFC
,
823 if (res
!= ERROR_OK
) {
824 LOG_ERROR("Couldn't read PPFC register");
828 if ((ppfc
& 0xFF) == 0xFF) {
829 /* We can't erase the UICR. Double-check to
830 see if it's already erased before complaining. */
831 default_flash_blank_check(bank
);
832 if (sector
->is_erased
== 1)
835 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");
839 res
= nrf5_nvmc_generic_erase(chip
,
845 res
= nrf5_nvmc_generic_erase(chip
,
853 static const uint8_t nrf5_flash_write_code
[] = {
854 /* See contrib/loaders/flash/cortex-m0.S */
856 0x0d, 0x68, /* ldr r5, [r1, #0] */
857 0x00, 0x2d, /* cmp r5, #0 */
858 0x0b, 0xd0, /* beq.n 1e <exit> */
859 0x4c, 0x68, /* ldr r4, [r1, #4] */
860 0xac, 0x42, /* cmp r4, r5 */
861 0xf9, 0xd0, /* beq.n 0 <wait_fifo> */
862 0x20, 0xcc, /* ldmia r4!, {r5} */
863 0x20, 0xc3, /* stmia r3!, {r5} */
864 0x94, 0x42, /* cmp r4, r2 */
865 0x01, 0xd3, /* bcc.n 18 <no_wrap> */
866 0x0c, 0x46, /* mov r4, r1 */
867 0x08, 0x34, /* adds r4, #8 */
869 0x4c, 0x60, /* str r4, [r1, #4] */
870 0x04, 0x38, /* subs r0, #4 */
871 0xf0, 0xd1, /* bne.n 0 <wait_fifo> */
873 0x00, 0xbe /* bkpt 0x0000 */
877 /* Start a low level flash write for the specified region */
878 static int nrf5_ll_flash_write(struct nrf5_info
*chip
, uint32_t address
, const uint8_t *buffer
, uint32_t bytes
)
880 struct target
*target
= chip
->target
;
881 uint32_t buffer_size
= 8192;
882 struct working_area
*write_algorithm
;
883 struct working_area
*source
;
884 struct reg_param reg_params
[4];
885 struct armv7m_algorithm armv7m_info
;
886 int retval
= ERROR_OK
;
888 LOG_DEBUG("Writing buffer to flash address=0x%"PRIx32
" bytes=0x%"PRIx32
, address
, bytes
);
889 assert(bytes
% 4 == 0);
891 /* allocate working area with flash programming code */
892 if (target_alloc_working_area(target
, sizeof(nrf5_flash_write_code
),
893 &write_algorithm
) != ERROR_OK
) {
894 LOG_WARNING("no working area available, falling back to slow memory writes");
896 for (; bytes
> 0; bytes
-= 4) {
897 retval
= target_write_memory(target
, address
, 4, 1, buffer
);
898 if (retval
!= ERROR_OK
)
901 retval
= nrf5_wait_for_nvmc(chip
);
902 if (retval
!= ERROR_OK
)
912 retval
= target_write_buffer(target
, write_algorithm
->address
,
913 sizeof(nrf5_flash_write_code
),
914 nrf5_flash_write_code
);
915 if (retval
!= ERROR_OK
)
919 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
) {
921 buffer_size
&= ~3UL; /* Make sure it's 4 byte aligned */
922 if (buffer_size
<= 256) {
923 /* free working area, write algorithm already allocated */
924 target_free_working_area(target
, write_algorithm
);
926 LOG_WARNING("No large enough working area available, can't do block memory writes");
927 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
931 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
932 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
934 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
); /* byte count */
935 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
); /* buffer start */
936 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
); /* buffer end */
937 init_reg_param(®_params
[3], "r3", 32, PARAM_IN_OUT
); /* target address */
939 buf_set_u32(reg_params
[0].value
, 0, 32, bytes
);
940 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
);
941 buf_set_u32(reg_params
[2].value
, 0, 32, source
->address
+ source
->size
);
942 buf_set_u32(reg_params
[3].value
, 0, 32, address
);
944 retval
= target_run_flash_async_algorithm(target
, buffer
, bytes
/4, 4,
947 source
->address
, source
->size
,
948 write_algorithm
->address
, 0,
951 target_free_working_area(target
, source
);
952 target_free_working_area(target
, write_algorithm
);
954 destroy_reg_param(®_params
[0]);
955 destroy_reg_param(®_params
[1]);
956 destroy_reg_param(®_params
[2]);
957 destroy_reg_param(®_params
[3]);
962 static int nrf5_write(struct flash_bank
*bank
, const uint8_t *buffer
,
963 uint32_t offset
, uint32_t count
)
965 struct nrf5_info
*chip
;
967 int res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
971 assert(offset
% 4 == 0);
972 assert(count
% 4 == 0);
974 res
= nrf5_nvmc_write_enable(chip
);
978 res
= nrf5_ll_flash_write(chip
, bank
->base
+ offset
, buffer
, count
);
982 return nrf5_nvmc_read_only(chip
);
985 nrf5_nvmc_read_only(chip
);
986 LOG_ERROR("Failed to write to nrf5 flash");
990 static int nrf5_erase(struct flash_bank
*bank
, int first
, int last
)
993 struct nrf5_info
*chip
;
995 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
999 /* For each sector to be erased */
1000 for (int s
= first
; s
<= last
&& res
== ERROR_OK
; s
++)
1001 res
= nrf5_erase_page(bank
, chip
, &bank
->sectors
[s
]);
1006 static void nrf5_free_driver_priv(struct flash_bank
*bank
)
1008 struct nrf5_bank
*nbank
= bank
->driver_priv
;
1009 struct nrf5_info
*chip
= nbank
->chip
;
1014 if (chip
->refcount
== 0) {
1016 bank
->driver_priv
= NULL
;
1020 FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command
)
1022 static struct nrf5_info
*chip
;
1023 struct nrf5_bank
*nbank
= NULL
;
1025 switch (bank
->base
) {
1026 case NRF5_FLASH_BASE
:
1027 case NRF5_UICR_BASE
:
1030 LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT
, bank
->base
);
1035 /* Create a new chip */
1036 chip
= calloc(1, sizeof(*chip
));
1040 chip
->target
= bank
->target
;
1043 switch (bank
->base
) {
1044 case NRF5_FLASH_BASE
:
1045 nbank
= &chip
->bank
[0];
1047 case NRF5_UICR_BASE
:
1048 nbank
= &chip
->bank
[1];
1051 assert(nbank
!= NULL
);
1055 nbank
->probed
= false;
1056 bank
->driver_priv
= nbank
;
1057 bank
->write_start_alignment
= bank
->write_end_alignment
= 4;
1062 COMMAND_HANDLER(nrf5_handle_mass_erase_command
)
1065 struct flash_bank
*bank
= NULL
;
1066 struct target
*target
= get_current_target(CMD_CTX
);
1068 res
= get_flash_bank_by_addr(target
, NRF5_FLASH_BASE
, true, &bank
);
1069 if (res
!= ERROR_OK
)
1072 assert(bank
!= NULL
);
1074 struct nrf5_info
*chip
;
1076 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
1077 if (res
!= ERROR_OK
)
1082 res
= target_read_u32(target
, NRF51_FICR_PPFC
,
1084 if (res
!= ERROR_OK
) {
1085 LOG_ERROR("Couldn't read PPFC register");
1089 if ((ppfc
& 0xFF) == 0x00) {
1090 LOG_ERROR("Code region 0 size was pre-programmed at the factory, "
1091 "mass erase command won't work.");
1095 res
= nrf5_erase_all(chip
);
1096 if (res
!= ERROR_OK
) {
1097 LOG_ERROR("Failed to erase the chip");
1098 nrf5_protect_check(bank
);
1102 res
= nrf5_protect_check(bank
);
1103 if (res
!= ERROR_OK
) {
1104 LOG_ERROR("Failed to check chip's write protection");
1108 res
= get_flash_bank_by_addr(target
, NRF5_UICR_BASE
, true, &bank
);
1109 if (res
!= ERROR_OK
)
1115 COMMAND_HANDLER(nrf5_handle_info_command
)
1118 struct flash_bank
*bank
= NULL
;
1119 struct target
*target
= get_current_target(CMD_CTX
);
1121 res
= get_flash_bank_by_addr(target
, NRF5_FLASH_BASE
, true, &bank
);
1122 if (res
!= ERROR_OK
)
1125 assert(bank
!= NULL
);
1127 struct nrf5_info
*chip
;
1129 res
= nrf5_get_probed_chip_if_halted(bank
, &chip
);
1130 if (res
!= ERROR_OK
)
1134 const uint32_t address
;
1137 { .address
= NRF5_FICR_CODEPAGESIZE
},
1138 { .address
= NRF5_FICR_CODESIZE
},
1139 { .address
= NRF51_FICR_CLENR0
},
1140 { .address
= NRF51_FICR_PPFC
},
1141 { .address
= NRF51_FICR_NUMRAMBLOCK
},
1142 { .address
= NRF51_FICR_SIZERAMBLOCK0
},
1143 { .address
= NRF51_FICR_SIZERAMBLOCK1
},
1144 { .address
= NRF51_FICR_SIZERAMBLOCK2
},
1145 { .address
= NRF51_FICR_SIZERAMBLOCK3
},
1146 { .address
= NRF5_FICR_CONFIGID
},
1147 { .address
= NRF5_FICR_DEVICEID0
},
1148 { .address
= NRF5_FICR_DEVICEID1
},
1149 { .address
= NRF5_FICR_ER0
},
1150 { .address
= NRF5_FICR_ER1
},
1151 { .address
= NRF5_FICR_ER2
},
1152 { .address
= NRF5_FICR_ER3
},
1153 { .address
= NRF5_FICR_IR0
},
1154 { .address
= NRF5_FICR_IR1
},
1155 { .address
= NRF5_FICR_IR2
},
1156 { .address
= NRF5_FICR_IR3
},
1157 { .address
= NRF5_FICR_DEVICEADDRTYPE
},
1158 { .address
= NRF5_FICR_DEVICEADDR0
},
1159 { .address
= NRF5_FICR_DEVICEADDR1
},
1160 { .address
= NRF51_FICR_OVERRIDEN
},
1161 { .address
= NRF51_FICR_NRF_1MBIT0
},
1162 { .address
= NRF51_FICR_NRF_1MBIT1
},
1163 { .address
= NRF51_FICR_NRF_1MBIT2
},
1164 { .address
= NRF51_FICR_NRF_1MBIT3
},
1165 { .address
= NRF51_FICR_NRF_1MBIT4
},
1166 { .address
= NRF51_FICR_BLE_1MBIT0
},
1167 { .address
= NRF51_FICR_BLE_1MBIT1
},
1168 { .address
= NRF51_FICR_BLE_1MBIT2
},
1169 { .address
= NRF51_FICR_BLE_1MBIT3
},
1170 { .address
= NRF51_FICR_BLE_1MBIT4
},
1172 { .address
= NRF51_UICR_CLENR0
, },
1173 { .address
= NRF51_UICR_RBPCONF
},
1174 { .address
= NRF51_UICR_XTALFREQ
},
1175 { .address
= NRF51_UICR_FWID
},
1178 for (size_t i
= 0; i
< ARRAY_SIZE(ficr
); i
++) {
1179 res
= target_read_u32(chip
->target
, ficr
[i
].address
,
1181 if (res
!= ERROR_OK
) {
1182 LOG_ERROR("Couldn't read %" PRIx32
, ficr
[i
].address
);
1187 for (size_t i
= 0; i
< ARRAY_SIZE(uicr
); i
++) {
1188 res
= target_read_u32(chip
->target
, uicr
[i
].address
,
1190 if (res
!= ERROR_OK
) {
1191 LOG_ERROR("Couldn't read %" PRIx32
, uicr
[i
].address
);
1197 "\n[factory information control block]\n\n"
1198 "code page size: %"PRIu32
"B\n"
1199 "code memory size: %"PRIu32
"kB\n"
1200 "code region 0 size: %"PRIu32
"kB\n"
1201 "pre-programmed code: %s\n"
1202 "number of ram blocks: %"PRIu32
"\n"
1203 "ram block 0 size: %"PRIu32
"B\n"
1204 "ram block 1 size: %"PRIu32
"B\n"
1205 "ram block 2 size: %"PRIu32
"B\n"
1206 "ram block 3 size: %"PRIu32
"B\n"
1207 "config id: %" PRIx32
"\n"
1208 "device id: 0x%"PRIx32
"%08"PRIx32
"\n"
1209 "encryption root: 0x%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"\n"
1210 "identity root: 0x%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"%08"PRIx32
"\n"
1211 "device address type: 0x%"PRIx32
"\n"
1212 "device address: 0x%"PRIx32
"%08"PRIx32
"\n"
1213 "override enable: %"PRIx32
"\n"
1214 "NRF_1MBIT values: %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
"\n"
1215 "BLE_1MBIT values: %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
" %"PRIx32
"\n"
1216 "\n[user information control block]\n\n"
1217 "code region 0 size: %"PRIu32
"kB\n"
1218 "read back protection configuration: %"PRIx32
"\n"
1219 "reset value for XTALFREQ: %"PRIx32
"\n"
1220 "firmware id: 0x%04"PRIx32
,
1222 (ficr
[1].value
* ficr
[0].value
) / 1024,
1223 (ficr
[2].value
== 0xFFFFFFFF) ? 0 : ficr
[2].value
/ 1024,
1224 ((ficr
[3].value
& 0xFF) == 0x00) ? "present" : "not present",
1227 (ficr
[6].value
== 0xFFFFFFFF) ? 0 : ficr
[6].value
,
1228 (ficr
[7].value
== 0xFFFFFFFF) ? 0 : ficr
[7].value
,
1229 (ficr
[8].value
== 0xFFFFFFFF) ? 0 : ficr
[8].value
,
1231 ficr
[10].value
, ficr
[11].value
,
1232 ficr
[12].value
, ficr
[13].value
, ficr
[14].value
, ficr
[15].value
,
1233 ficr
[16].value
, ficr
[17].value
, ficr
[18].value
, ficr
[19].value
,
1235 ficr
[21].value
, ficr
[22].value
,
1237 ficr
[24].value
, ficr
[25].value
, ficr
[26].value
, ficr
[27].value
, ficr
[28].value
,
1238 ficr
[29].value
, ficr
[30].value
, ficr
[31].value
, ficr
[32].value
, ficr
[33].value
,
1239 (uicr
[0].value
== 0xFFFFFFFF) ? 0 : uicr
[0].value
/ 1024,
1240 uicr
[1].value
& 0xFFFF,
1241 uicr
[2].value
& 0xFF,
1242 uicr
[3].value
& 0xFFFF);
1247 static const struct command_registration nrf5_exec_command_handlers
[] = {
1249 .name
= "mass_erase",
1250 .handler
= nrf5_handle_mass_erase_command
,
1251 .mode
= COMMAND_EXEC
,
1252 .help
= "Erase all flash contents of the chip.",
1257 .handler
= nrf5_handle_info_command
,
1258 .mode
= COMMAND_EXEC
,
1259 .help
= "Show FICR and UICR info.",
1262 COMMAND_REGISTRATION_DONE
1265 static const struct command_registration nrf5_command_handlers
[] = {
1268 .mode
= COMMAND_ANY
,
1269 .help
= "nrf5 flash command group",
1271 .chain
= nrf5_exec_command_handlers
,
1275 .mode
= COMMAND_ANY
,
1276 .help
= "nrf51 flash command group",
1278 .chain
= nrf5_exec_command_handlers
,
1280 COMMAND_REGISTRATION_DONE
1283 const struct flash_driver nrf5_flash
= {
1285 .commands
= nrf5_command_handlers
,
1286 .flash_bank_command
= nrf5_flash_bank_command
,
1288 .erase
= nrf5_erase
,
1289 .protect
= nrf5_protect
,
1290 .write
= nrf5_write
,
1291 .read
= default_flash_read
,
1292 .probe
= nrf5_probe
,
1293 .auto_probe
= nrf5_auto_probe
,
1294 .erase_check
= default_flash_blank_check
,
1295 .protect_check
= nrf5_protect_check
,
1296 .free_driver_priv
= nrf5_free_driver_priv
,
1299 /* We need to retain the flash-driver name as well as the commands
1300 * for backwards compatability */
1301 const struct flash_driver nrf51_flash
= {
1303 .commands
= nrf5_command_handlers
,
1304 .flash_bank_command
= nrf5_flash_bank_command
,
1306 .erase
= nrf5_erase
,
1307 .protect
= nrf5_protect
,
1308 .write
= nrf5_write
,
1309 .read
= default_flash_read
,
1310 .probe
= nrf5_probe
,
1311 .auto_probe
= nrf5_auto_probe
,
1312 .erase_check
= default_flash_blank_check
,
1313 .protect_check
= nrf5_protect_check
,
1314 .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)