33#include "target_internal.h"
44#include "cortexm.h"
55#include "adiv5.h"
6+ #include "gdb_packet.h"
67
78/* 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
1216
1317#define NRF91_NVMC_CONFIG_REN 0x0U // Read only access
1418#define NRF91_NVMC_CONFIG_WEN 0x1U // Write enable
1519#define NRF91_NVMC_CONFIG_EEN 0x2U // Erase enable
1620#define NRF91_NVMC_CONFIG_PEEN 0x3U // Partial erase enable
1721
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+
1875static bool nrf91_wait_ready (target_s * const target , platform_timeout_s * const timeout )
1976{
2077 /* Poll for NVMC_READY */
@@ -27,6 +84,18 @@ static bool nrf91_wait_ready(target_s *const target, platform_timeout_s *const t
2784 return true;
2885}
2986
87+ static bool nrf91_wait_readynext (target_s * const target , platform_timeout_s * const timeout )
88+ {
89+ /* Poll for NVMC_READY */
90+ while (target_mem_read32 (target , NRF91_NVMC_READYNEXT ) == 0 ) {
91+ if (target_check_error (target ))
92+ return false;
93+ if (timeout )
94+ target_print_progress (timeout );
95+ }
96+ return true;
97+ }
98+
3099static bool nrf91_flash_erase (target_flash_s * flash , target_addr_t addr , size_t len )
31100{
32101 target_s * target = flash -> t ;
@@ -49,17 +118,42 @@ static bool nrf91_flash_erase(target_flash_s *flash, target_addr_t addr, size_t
49118 return nrf91_wait_ready (target , NULL );
50119}
51120
52- static bool nrf91_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t len )
121+ static bool nrf91_uicr_flash_erase (target_flash_s * flash , target_addr_t addr , size_t len )
53122{
54123 target_s * target = flash -> t ;
55124
125+ bool erase_needed = false;
126+
127+ for (size_t offset = 0 ; offset < len ; offset += 4 ) {
128+ if (target_mem_read32 (target , addr + offset ) != NRF91_UICR_ERASED_VAL ) {
129+ erase_needed = true;
130+ break ;
131+ }
132+ }
133+
134+ if (erase_needed ) {
135+ gdb_out ("Skipping UICR erase, mass erase might be needed\n" );
136+ }
137+ return true;
138+ }
139+
140+ static bool nrf91_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t len )
141+ {
142+ target_s * target = flash -> t ;
143+ platform_timeout_s timeout ;
56144 /* Enable write */
57145 target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_WEN );
58- if (!nrf91_wait_ready (target , NULL ))
146+
147+ if (!nrf91_wait_ready (target , & timeout ))
59148 return false;
60149 /* Write the data */
61- target_mem_write (target , dest , src , len );
62- if (!nrf91_wait_ready (target , NULL ))
150+ for (size_t offset = 0 ; offset < len ; offset += 4 ) {
151+ target_mem_write32 (target , dest + offset , src + offset );
152+ if (!nrf91_wait_readynext (target , & timeout ))
153+ return false;
154+ }
155+ //target_mem_write(target, dest, src, len);
156+ if (!nrf91_wait_ready (target , & timeout ))
63157 return false;
64158 /* Return to read-only */
65159 target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_REN );
@@ -68,6 +162,7 @@ static bool nrf91_flash_write(target_flash_s *flash, target_addr_t dest, const v
68162
69163static void nrf91_add_flash (target_s * target , uint32_t addr , size_t length , size_t erasesize )
70164{
165+ /* add main flash */
71166 target_flash_s * flash = calloc (1 , sizeof (* flash ));
72167 if (!flash ) { /* calloc failed: heap exhaustion */
73168 DEBUG_WARN ("calloc: failed in %s\n" , __func__ );
@@ -81,25 +176,208 @@ static void nrf91_add_flash(target_s *target, uint32_t addr, size_t length, size
81176 flash -> write = nrf91_flash_write ;
82177 flash -> erased = 0xff ;
83178 target_add_flash (target , flash );
179+
180+ /* add separate UICR flash */
181+ target_flash_s * flash_uicr = calloc (1 , sizeof (* flash_uicr ));
182+ if (!flash_uicr ) { /* calloc failed: heap exhaustion */
183+ DEBUG_WARN ("calloc: failed in %s\n" , __func__ );
184+ return ;
185+ }
186+
187+ flash_uicr -> start = 0xff8000U ;
188+ flash_uicr -> length = 0x1000U ;
189+ flash_uicr -> blocksize = 0x4U ;
190+ flash_uicr -> erase = nrf91_uicr_flash_erase ;
191+ flash_uicr -> write = nrf91_flash_write ;
192+ flash_uicr -> erased = 0xff ;
193+ target_add_flash (target , flash_uicr );
194+ }
195+
196+ static bool nrf91_mass_erase (target_s * target )
197+ {
198+ adiv5_access_port_s * ap = cortex_ap (target );
199+ adiv5_access_port_s ctrl_ap = {
200+ .dp = ap -> dp ,
201+ .apsel = 0x4U ,
202+ };
203+
204+ if (!nrf91_ctrl_ap_mass_erase (& ctrl_ap )) {
205+ return false;
206+ }
207+
208+ if (ap -> dp -> target_revision > 2 ) {
209+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_WEN );
210+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
211+ platform_delay (1 );
212+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
213+ }
214+
215+ target_mem_write (target , 0 , empty_app , empty_app_len );
216+ target_mem_write32 (target , NRF91_UICR_APPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
217+ target_mem_write32 (target , NRF91_UICR_SECUREAPPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
218+
219+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
220+ platform_delay (1 );
221+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
222+ }
223+
224+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_REN );
225+ }
226+
227+ return true;
228+ }
229+
230+ static bool nrf91_exit_flash_mode (target_s * const target )
231+ {
232+ adiv5_access_port_s * ap = cortex_ap (target );
233+ /* Persist AP access if uninitialized (only needed for devices with hardenend APPROTECT) */
234+ if (ap -> dp -> target_revision > 2 ) {
235+ bool approtect_erased = target_mem_read32 (target , NRF91_UICR_APPROTECT ) == NRF91_UICR_ERASED_VAL ;
236+ bool secureapprotect_erased = target_mem_read32 (target , NRF91_UICR_SECUREAPPROTECT ) == NRF91_UICR_ERASED_VAL ;
237+
238+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_WEN );
239+
240+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
241+ platform_delay (1 );
242+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
243+ }
244+
245+ if (approtect_erased ) {
246+ target_mem_write32 (target , NRF91_UICR_APPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
247+ }
248+ if (secureapprotect_erased ) {
249+ target_mem_write32 (target , NRF91_UICR_SECUREAPPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
250+ }
251+
252+ while (target_mem_read32 (target , NRF91_NVMC_READY ) == 0 ) {
253+ platform_delay (1 );
254+ DEBUG_INFO ("Waiting for NVMC to become ready\n" );
255+ }
256+
257+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_REN );
258+ }
259+ return true;
84260}
85261
86262bool nrf91_probe (target_s * target )
87263{
88264 adiv5_access_port_s * ap = cortex_ap (target );
89265
90- if (ap -> dp -> version < 2U )
266+ if (ap -> dp -> version < 2U || ap -> dp -> target_partno != NRF91_PARTNO )
91267 return false;
92268
93- switch (ap -> dp -> target_partno ) {
94- case 0x90 :
269+ uint32_t partno = target_mem_read32 (target , 0x00FF0140 );
270+ uint32_t hwrevision = target_mem_read32 (target , 0x00FF0144 );
271+ uint32_t variant = target_mem_read32 (target , 0x00FF0148 );
272+
273+ DEBUG_INFO ("nRF%04" PRIx32 " %4s%4s detected!\n" , partno , (const char * )& variant , (const char * )& hwrevision );
274+
275+ switch (ap -> dp -> target_revision ) {
276+ case 0 :
277+ case 1 :
278+ case 2 :
95279 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 ) ;
280+ break ;
281+ case 3 :
282+ target -> driver = "Nordic nRF91x1" ;
99283 break ;
100284 default :
285+ target -> driver = "Nordic nRF91" ;
286+ }
287+
288+ target -> target_options |= TOPT_INHIBIT_NRST ;
289+ target_add_ram (target , 0x20000000 , 256U * 1024U );
290+ nrf91_add_flash (target , 0 , 4096U * 256U , 4096U );
291+
292+ target -> mass_erase = nrf91_mass_erase ;
293+ target -> exit_flash_mode = nrf91_exit_flash_mode ;
294+
295+ return true;
296+ }
297+
298+ static bool nrf91_rescue_do_recover (target_s * target )
299+ {
300+ adiv5_access_port_s * ap = (adiv5_access_port_s * )target -> priv ;
301+
302+ const bool hardened_approtect = ap -> dp -> target_revision > 2 ;
303+
304+ /* on some revisions, this needs to be repeated */
305+ for (size_t i = 0 ; i < 3 ; ++ i ) {
306+ if (!nrf91_ctrl_ap_mass_erase (ap ))
307+ continue ;
308+ if (!hardened_approtect ) {
309+ /* pin reset is needed on older devices */
310+ platform_nrst_set_val (true);
311+ platform_delay (100 );
312+ platform_nrst_set_val (false);
313+
314+ /* repetition not needed and debug port inactive at this point */
315+ return false;
316+ }
317+
318+ //check if CSW DEVICEEN is set
319+ struct adiv5_access_port ahb_ap = * ap ;
320+ ahb_ap .apsel = 0x0U ;
321+ const uint32_t csw = ap -> dp -> ap_read (& ahb_ap , ADIV5_AP_CSW );
322+ if (csw & ADIV5_AP_CSW_DEVICEEN ) {
323+ DEBUG_INFO ("nRF91 Rescue succeeded.\n" );
324+ break ;
325+ }
326+ }
327+
328+ return false;
329+ }
330+
331+ bool nrf91_rescue_probe (adiv5_access_port_s * ap )
332+ {
333+ target_s * target = target_new ();
334+ if (!target ) {
101335 return false;
102336 }
337+ adiv5_ap_ref (ap );
338+ target -> attach = (void * )nrf91_rescue_do_recover ;
339+ target -> priv = ap ;
340+ target -> priv_free = (void * )adiv5_ap_unref ;
341+ target -> driver = "nRF91 Rescue (Attach, then scan again!)" ;
342+
343+ return true;
344+ }
103345
346+ /* check if nRF91 target is in secure state, return false if device is protected */
347+ bool nrf91_dp_prepare (adiv5_debug_port_s * const dp )
348+ {
349+ adiv5_access_port_s ahb_ap = {
350+ .dp = dp ,
351+ .apsel = 0x0U ,
352+ };
353+ adiv5_access_port_s ctrl_ap = {
354+ .dp = dp ,
355+ .apsel = 0x4U ,
356+ };
357+ ahb_ap .idr = adiv5_ap_read (& ahb_ap , ADIV5_AP_IDR );
358+ ahb_ap .csw = adiv5_ap_read (& ahb_ap , ADIV5_AP_CSW );
359+ ctrl_ap .idr = adiv5_ap_read (& ctrl_ap , ADIV5_AP_IDR );
360+
361+ if (ahb_ap .idr != NRF91_AHB_AP_IDR_EXPECTED ) {
362+ DEBUG_ERROR (
363+ "nRF91: AHB-AP IDR is 0x%08" PRIx32 ", expected 0x%08" PRIx32 "\n" , ahb_ap .idr , NRF91_AHB_AP_IDR_EXPECTED );
364+ }
365+
366+ if (ctrl_ap .idr != NRF91_CTRL_IDR_EXPECTED ) {
367+ DEBUG_ERROR (
368+ "nRF91: CTRL-AP IDR is 0x%08" PRIx32 ", expected 0x%08" PRIx32 "\n" , ctrl_ap .idr , NRF91_CTRL_IDR_EXPECTED );
369+ }
370+
371+ if (!(ahb_ap .csw & ADIV5_AP_CSW_DEVICEEN )) {
372+ DEBUG_INFO ("nRF91 is in secure state, creating rescue target\n" );
373+ adiv5_access_port_s * ap = calloc (1 , sizeof (* ap ));
374+ if (!ap ) { /* calloc failed: heap exhaustion */
375+ DEBUG_ERROR ("calloc: failed in %s\n" , __func__ );
376+ return false;
377+ }
378+ memcpy (ap , & ctrl_ap , sizeof (* ap ));
379+ nrf91_rescue_probe (ap );
380+ return false;
381+ }
104382 return true;
105383}
0 commit comments