3
3
#include "target_internal.h"
4
4
#include "cortexm.h"
5
5
#include "adiv5.h"
6
+ #include "gdb_packet.h"
6
7
7
8
/* Non-Volatile Memory Controller (NVMC) Registers */
8
- #define NRF91_NVMC 0x50039000U
9
- #define NRF91_NVMC_READY (NRF91_NVMC + 0x400U)
10
- #define NRF91_NVMC_CONFIG (NRF91_NVMC + 0x504U)
11
- #define NRF91_NVMC_ERASEALL (NRF91_NVMC + 0x50cU)
9
+ #define NRF91_NVMC 0x50039000U
10
+ #define NRF91_NVMC_READY (NRF91_NVMC + 0x400U)
11
+ #define NRF91_NVMC_READYNEXT (NRF91_NVMC + 0x408U)
12
+ #define NRF91_NVMC_CONFIG (NRF91_NVMC + 0x504U)
13
+ #define NRF91_NVMC_ERASEALL (NRF91_NVMC + 0x50cU)
14
+
15
+ #define NVMC_TIMEOUT_MS 300U
12
16
13
17
#define NRF91_NVMC_CONFIG_REN 0x0U // Read only access
14
18
#define NRF91_NVMC_CONFIG_WEN 0x1U // Write enable
15
19
#define NRF91_NVMC_CONFIG_EEN 0x2U // Erase enable
16
20
#define NRF91_NVMC_CONFIG_PEEN 0x3U // Partial erase enable
17
21
22
+ /* https://infocenter.nordicsemi.com/topic/ps_nrf9160/dif.html */
23
+ #define NRF91_PARTNO 0x90U
24
+
25
+ #define NRF91_CTRL_AP_RESET ADIV5_AP_REG(0x000)
26
+ #define NRF91_CTRL_AP_ERASEALL ADIV5_AP_REG(0x004)
27
+ #define NRF91_CTRL_IDR_EXPECTED 0x12880000
28
+ #define NRF91_AHB_AP_IDR_EXPECTED 0x84770001
29
+ #define NRF91_CTRL_AP_ERASEALLSTATUS ADIV5_AP_REG(0x008)
30
+
31
+ /* https://infocenter.nordicsemi.com/topic/ps_nrf9161/uicr.html */
32
+ #define NRF91_UICR_APPROTECT 0x00FF8000U
33
+ #define NRF91_UICR_SECUREAPPROTECT 0x00FF802CU
34
+ #define NRF91_UICR_APPROTECT_UNPROTECT_VAL 0x50FA50FAU
35
+ #define NRF91_UICR_ERASED_VAL 0xFFFFFFFFU
36
+
37
+ unsigned char empty_app [] = {
38
+ 0x00 , 0x10 , 0x00 , 0x20 , 0x09 , 0x00 , 0x00 , 0x00 , 0x05 , 0x4b , 0x4f , 0xf0 ,
39
+ 0x5a , 0x02 , 0xc3 , 0xf8 , 0x10 , 0x2e , 0x03 , 0x4b , 0x4f , 0xf0 , 0x5a , 0x02 ,
40
+ 0xc3 , 0xf8 , 0x00 , 0x2e , 0xfe , 0xe7 , 0x00 , 0x00 , 0x00 , 0x90 , 0x03 , 0x50
41
+ };
42
+ unsigned int empty_app_len = 36 ;
43
+
44
+ static bool nrf91_ctrl_ap_mass_erase (adiv5_access_port_s * ap )
45
+ {
46
+ adiv5_ap_write (ap , NRF91_CTRL_AP_ERASEALL , 1 );
47
+ platform_timeout_s timeout ;
48
+ platform_timeout_set (& timeout , NVMC_TIMEOUT_MS );
49
+
50
+ bool ret = false;
51
+
52
+ while (true) {
53
+ uint32_t status = adiv5_ap_read (ap , NRF91_CTRL_AP_ERASEALLSTATUS );
54
+ if (status == 0 ) {
55
+ ret = true;
56
+ DEBUG_INFO ("nRF91 mass erase succeeded.\n" );
57
+ break ;
58
+ }
59
+ if (platform_timeout_is_expired (& timeout )) {
60
+ DEBUG_INFO ("nRF91 mass erase failed.\n" );
61
+ break ;
62
+ }
63
+ }
64
+
65
+ platform_delay (10 );
66
+
67
+ adiv5_ap_write (ap , NRF91_CTRL_AP_RESET , 1 );
68
+ adiv5_ap_write (ap , NRF91_CTRL_AP_RESET , 0 );
69
+
70
+ platform_delay (200 );
71
+
72
+ return ret ;
73
+ }
74
+
18
75
static bool nrf91_wait_ready (target_s * const target , platform_timeout_s * const timeout )
19
76
{
20
77
/* Poll for NVMC_READY */
@@ -49,6 +106,25 @@ static bool nrf91_flash_erase(target_flash_s *flash, target_addr_t addr, size_t
49
106
return nrf91_wait_ready (target , NULL );
50
107
}
51
108
109
+ static bool nrf91_uicr_flash_erase (target_flash_s * flash , target_addr_t addr , size_t len )
110
+ {
111
+ target_s * target = flash -> t ;
112
+
113
+ bool erase_needed = false;
114
+
115
+ for (size_t offset = 0 ; offset < len ; offset += 4 ) {
116
+ if (target_mem_read32 (target , addr + offset ) != NRF91_UICR_ERASED_VAL ) {
117
+ erase_needed = true;
118
+ break ;
119
+ }
120
+ }
121
+
122
+ if (erase_needed ) {
123
+ gdb_out ("Skipping UICR erase, mass erase might be needed\n" );
124
+ }
125
+ return true;
126
+ }
127
+
52
128
static bool nrf91_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t len )
53
129
{
54
130
target_s * target = flash -> t ;
@@ -68,6 +144,7 @@ static bool nrf91_flash_write(target_flash_s *flash, target_addr_t dest, const v
68
144
69
145
static void nrf91_add_flash (target_s * target , uint32_t addr , size_t length , size_t erasesize )
70
146
{
147
+ /* add main flash */
71
148
target_flash_s * flash = calloc (1 , sizeof (* flash ));
72
149
if (!flash ) { /* calloc failed: heap exhaustion */
73
150
DEBUG_WARN ("calloc: failed in %s\n" , __func__ );
@@ -81,25 +158,208 @@ static void nrf91_add_flash(target_s *target, uint32_t addr, size_t length, size
81
158
flash -> write = nrf91_flash_write ;
82
159
flash -> erased = 0xff ;
83
160
target_add_flash (target , flash );
161
+
162
+ /* add separate UICR flash */
163
+ target_flash_s * flash_uicr = calloc (1 , sizeof (* flash_uicr ));
164
+ if (!flash_uicr ) { /* calloc failed: heap exhaustion */
165
+ DEBUG_WARN ("calloc: failed in %s\n" , __func__ );
166
+ return ;
167
+ }
168
+
169
+ flash_uicr -> start = 0xff8000U ;
170
+ flash_uicr -> length = 0x1000U ;
171
+ flash_uicr -> blocksize = 0x4U ;
172
+ flash_uicr -> erase = nrf91_uicr_flash_erase ;
173
+ flash_uicr -> write = nrf91_flash_write ;
174
+ flash_uicr -> erased = 0xff ;
175
+ target_add_flash (target , flash_uicr );
176
+ }
177
+
178
+ static bool nrf91_mass_erase (target_s * target )
179
+ {
180
+ adiv5_access_port_s * ap = cortex_ap (target );
181
+ adiv5_access_port_s ctrl_ap = {
182
+ .dp = ap -> dp ,
183
+ .apsel = 0x4U ,
184
+ };
185
+
186
+ if (!nrf91_ctrl_ap_mass_erase (& ctrl_ap )) {
187
+ return false;
188
+ }
189
+
190
+ if (ap -> dp -> target_revision > 2 ) {
191
+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_WEN );
192
+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
193
+ platform_delay (1 );
194
+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
195
+ }
196
+
197
+ target_mem_write (target , 0 , empty_app , empty_app_len );
198
+ target_mem_write32 (target , NRF91_UICR_APPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
199
+ target_mem_write32 (target , NRF91_UICR_SECUREAPPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
200
+
201
+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
202
+ platform_delay (1 );
203
+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
204
+ }
205
+
206
+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_REN );
207
+ }
208
+
209
+ return true;
210
+ }
211
+
212
+ static bool nrf91_exit_flash_mode (target_s * const target )
213
+ {
214
+ adiv5_access_port_s * ap = cortex_ap (target );
215
+ /* Persist AP access if uninitialized (only needed for devices with hardenend APPROTECT) */
216
+ if (ap -> dp -> target_revision > 2 ) {
217
+ bool approtect_erased = target_mem_read32 (target , NRF91_UICR_APPROTECT ) == NRF91_UICR_ERASED_VAL ;
218
+ bool secureapprotect_erased = target_mem_read32 (target , NRF91_UICR_SECUREAPPROTECT ) == NRF91_UICR_ERASED_VAL ;
219
+
220
+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_WEN );
221
+
222
+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
223
+ platform_delay (1 );
224
+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
225
+ }
226
+
227
+ if (approtect_erased ) {
228
+ target_mem_write32 (target , NRF91_UICR_APPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
229
+ }
230
+ if (secureapprotect_erased ) {
231
+ target_mem_write32 (target , NRF91_UICR_SECUREAPPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
232
+ }
233
+
234
+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
235
+ platform_delay (1 );
236
+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
237
+ }
238
+
239
+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_REN );
240
+ }
241
+ return true;
84
242
}
85
243
86
244
bool nrf91_probe (target_s * target )
87
245
{
88
246
adiv5_access_port_s * ap = cortex_ap (target );
89
247
90
- if (ap -> dp -> version < 2U )
248
+ if (ap -> dp -> version < 2U || ap -> dp -> target_partno != NRF91_PARTNO )
91
249
return false;
92
250
93
- switch (ap -> dp -> target_partno ) {
94
- case 0x90 :
251
+ #ifndef ENABLE_DEBUG
252
+ uint32_t partno = target_mem_read32 (target , 0x00FF0140 );
253
+ uint32_t hwrevision = target_mem_read32 (target , 0x00FF0144 );
254
+ uint32_t variant = target_mem_read32 (target , 0x00FF0148 );
255
+ DEBUG_INFO ("nRF%04" PRIx32 " %4s%4s detected!\n" , partno , (const char * )& variant , (const char * )& hwrevision );
256
+ #endif
257
+ switch (ap -> dp -> target_revision ) {
258
+ case 0 :
259
+ case 1 :
260
+ case 2 :
95
261
target -> driver = "Nordic nRF9160" ;
96
- target -> target_options |= TOPT_INHIBIT_NRST ;
97
- target_add_ram ( target , 0x20000000 , 256U * 1024U );
98
- nrf91_add_flash ( target , 0 , 4096U * 256U , 4096U ) ;
262
+ break ;
263
+ case 3 :
264
+ target -> driver = "Nordic nRF91x1" ;
99
265
break ;
100
266
default :
267
+ target -> driver = "Nordic nRF91" ;
268
+ }
269
+
270
+ target -> target_options |= TOPT_INHIBIT_NRST ;
271
+ target_add_ram (target , 0x20000000 , 256U * 1024U );
272
+ nrf91_add_flash (target , 0 , 4096U * 256U , 4096U );
273
+
274
+ target -> mass_erase = nrf91_mass_erase ;
275
+ target -> exit_flash_mode = nrf91_exit_flash_mode ;
276
+
277
+ return true;
278
+ }
279
+
280
+ static bool nrf91_rescue_do_recover (target_s * target )
281
+ {
282
+ adiv5_access_port_s * ap = (adiv5_access_port_s * )target -> priv ;
283
+
284
+ const bool hardened_approtect = ap -> dp -> target_revision > 2 ;
285
+
286
+ /* on some revisions, this needs to be repeated */
287
+ for (size_t i = 0 ; i < 3 ; ++ i ) {
288
+ if (!nrf91_ctrl_ap_mass_erase (ap ))
289
+ continue ;
290
+ if (!hardened_approtect ) {
291
+ /* pin reset is needed on older devices */
292
+ platform_nrst_set_val (true);
293
+ platform_delay (100 );
294
+ platform_nrst_set_val (false);
295
+
296
+ /* repetition not needed and debug port inactive at this point */
297
+ return false;
298
+ }
299
+
300
+ //check if CSW DEVICEEN is set
301
+ struct adiv5_access_port ahb_ap = * ap ;
302
+ ahb_ap .apsel = 0x0U ;
303
+ const uint32_t csw = ap -> dp -> ap_read (& ahb_ap , ADIV5_AP_CSW );
304
+ if (csw & ADIV5_AP_CSW_DEVICEEN ) {
305
+ DEBUG_INFO ("nRF91 Rescue succeeded.\n" );
306
+ break ;
307
+ }
308
+ }
309
+
310
+ return false;
311
+ }
312
+
313
+ bool nrf91_rescue_probe (adiv5_access_port_s * ap )
314
+ {
315
+ target_s * target = target_new ();
316
+ if (!target ) {
101
317
return false;
102
318
}
319
+ adiv5_ap_ref (ap );
320
+ target -> attach = (void * )nrf91_rescue_do_recover ;
321
+ target -> priv = ap ;
322
+ target -> priv_free = (void * )adiv5_ap_unref ;
323
+ target -> driver = "nRF91 Rescue (Attach, then scan again!)" ;
103
324
104
325
return true;
105
326
}
327
+
328
+ /* check if nRF91 target is in secure state, return false if device is protected */
329
+ bool nrf91_dp_prepare (adiv5_debug_port_s * const dp )
330
+ {
331
+ adiv5_access_port_s ahb_ap = {
332
+ .dp = dp ,
333
+ .apsel = 0x0U ,
334
+ };
335
+ adiv5_access_port_s ctrl_ap = {
336
+ .dp = dp ,
337
+ .apsel = 0x4U ,
338
+ };
339
+ ahb_ap .idr = adiv5_ap_read (& ahb_ap , ADIV5_AP_IDR );
340
+ ahb_ap .csw = adiv5_ap_read (& ahb_ap , ADIV5_AP_CSW );
341
+ ctrl_ap .idr = adiv5_ap_read (& ctrl_ap , ADIV5_AP_IDR );
342
+
343
+ if (ahb_ap .idr != NRF91_AHB_AP_IDR_EXPECTED ) {
344
+ DEBUG_ERROR (
345
+ "nRF91: AHB-AP IDR is 0x%08" PRIx32 ", expected 0x%08" PRIx32 "\n" , ahb_ap .idr , NRF91_AHB_AP_IDR_EXPECTED );
346
+ }
347
+
348
+ if (ctrl_ap .idr != NRF91_CTRL_IDR_EXPECTED ) {
349
+ DEBUG_ERROR (
350
+ "nRF91: CTRL-AP IDR is 0x%08" PRIx32 ", expected 0x%08" PRIx32 "\n" , ctrl_ap .idr , NRF91_CTRL_IDR_EXPECTED );
351
+ }
352
+
353
+ if (!(ahb_ap .csw & ADIV5_AP_CSW_DEVICEEN )) {
354
+ DEBUG_INFO ("nRF91 is in secure state, creating rescue target\n" );
355
+ adiv5_access_port_s * ap = calloc (1 , sizeof (* ap ));
356
+ if (!ap ) { /* calloc failed: heap exhaustion */
357
+ DEBUG_ERROR ("calloc: failed in %s\n" , __func__ );
358
+ return false;
359
+ }
360
+ memcpy (ap , & ctrl_ap , sizeof (* ap ));
361
+ nrf91_rescue_probe (ap );
362
+ return false;
363
+ }
364
+ return true;
365
+ }
0 commit comments