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+ static bool nrf91_ctrl_ap_mass_erase (adiv5_access_port_s * ap )
38+ {
39+ adiv5_ap_write (ap , NRF91_CTRL_AP_ERASEALL , 1 );
40+ platform_timeout_s timeout ;
41+ platform_timeout_set (& timeout , NVMC_TIMEOUT_MS );
42+
43+ bool ret = false;
44+
45+ while (true) {
46+ uint32_t status = adiv5_ap_read (ap , NRF91_CTRL_AP_ERASEALLSTATUS );
47+ if (status == 0 ) {
48+ ret = true;
49+ DEBUG_INFO ("nRF91 mass erase succeeded.\n" );
50+ break ;
51+ }
52+ if (platform_timeout_is_expired (& timeout )) {
53+ DEBUG_INFO ("nRF91 mass erase failed.\n" );
54+ break ;
55+ }
56+ }
57+
58+ platform_delay (10 );
59+
60+ adiv5_ap_write (ap , NRF91_CTRL_AP_RESET , 1 );
61+ adiv5_ap_write (ap , NRF91_CTRL_AP_RESET , 0 );
62+
63+ platform_delay (200 );
64+
65+ return ret ;
66+ }
67+
1868static bool nrf91_wait_ready (target_s * const target , platform_timeout_s * const timeout )
1969{
2070 /* Poll for NVMC_READY */
@@ -27,6 +77,18 @@ static bool nrf91_wait_ready(target_s *const target, platform_timeout_s *const t
2777 return true;
2878}
2979
80+ static bool nrf91_wait_readynext (target_s * const target , platform_timeout_s * const timeout )
81+ {
82+ /* Poll for NVMC_READY */
83+ while (target_mem_read32 (target , NRF91_NVMC_READYNEXT ) == 0 ) {
84+ if (target_check_error (target ))
85+ return false;
86+ if (timeout )
87+ target_print_progress (timeout );
88+ }
89+ return true;
90+ }
91+
3092static bool nrf91_flash_erase (target_flash_s * flash , target_addr_t addr , size_t len )
3193{
3294 target_s * target = flash -> t ;
@@ -49,17 +111,42 @@ static bool nrf91_flash_erase(target_flash_s *flash, target_addr_t addr, size_t
49111 return nrf91_wait_ready (target , NULL );
50112}
51113
52- static bool nrf91_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t len )
114+ static bool nrf91_uicr_flash_erase (target_flash_s * flash , target_addr_t addr , size_t len )
53115{
54116 target_s * target = flash -> t ;
55117
118+ bool erase_needed = false;
119+
120+ for (size_t offset = 0 ; offset < len ; offset += 4 ) {
121+ if (target_mem_read32 (target , addr + offset ) != NRF91_UICR_ERASED_VAL ) {
122+ erase_needed = true;
123+ break ;
124+ }
125+ }
126+
127+ if (erase_needed ) {
128+ gdb_out ("Skipping UICR erase, mass erase might be needed\n" );
129+ }
130+ return true;
131+ }
132+
133+ static bool nrf91_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t len )
134+ {
135+ target_s * target = flash -> t ;
136+ platform_timeout_s timeout ;
56137 /* Enable write */
57138 target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_WEN );
58- if (!nrf91_wait_ready (target , NULL ))
139+
140+ if (!nrf91_wait_ready (target , & timeout ))
59141 return false;
60142 /* Write the data */
61- target_mem_write (target , dest , src , len );
62- if (!nrf91_wait_ready (target , NULL ))
143+ for (size_t offset = 0 ; offset < len ; offset += 4 ) {
144+ target_mem_write32 (target , dest + offset , src + offset );
145+ if (!nrf91_wait_readynext (target , & timeout ))
146+ return false;
147+ }
148+ //target_mem_write(target, dest, src, len);
149+ if (!nrf91_wait_ready (target , & timeout ))
63150 return false;
64151 /* Return to read-only */
65152 target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_REN );
@@ -68,6 +155,7 @@ static bool nrf91_flash_write(target_flash_s *flash, target_addr_t dest, const v
68155
69156static void nrf91_add_flash (target_s * target , uint32_t addr , size_t length , size_t erasesize )
70157{
158+ /* add main flash */
71159 target_flash_s * flash = calloc (1 , sizeof (* flash ));
72160 if (!flash ) { /* calloc failed: heap exhaustion */
73161 DEBUG_WARN ("calloc: failed in %s\n" , __func__ );
@@ -81,25 +169,180 @@ static void nrf91_add_flash(target_s *target, uint32_t addr, size_t length, size
81169 flash -> write = nrf91_flash_write ;
82170 flash -> erased = 0xff ;
83171 target_add_flash (target , flash );
172+
173+ /* add separate UICR flash */
174+ target_flash_s * flash_uicr = calloc (1 , sizeof (* flash_uicr ));
175+ if (!flash_uicr ) { /* calloc failed: heap exhaustion */
176+ DEBUG_WARN ("calloc: failed in %s\n" , __func__ );
177+ return ;
178+ }
179+
180+ flash_uicr -> start = 0xff8000U ;
181+ flash_uicr -> length = 0x1000U ;
182+ flash_uicr -> blocksize = 0x4U ;
183+ flash_uicr -> erase = nrf91_uicr_flash_erase ;
184+ flash_uicr -> write = nrf91_flash_write ;
185+ flash_uicr -> erased = 0xff ;
186+ target_add_flash (target , flash_uicr );
187+ }
188+
189+ static bool nrf91_mass_erase (target_s * target )
190+ {
191+ adiv5_access_port_s * ap = cortex_ap (target );
192+ adiv5_access_port_s ctrl_ap = {
193+ .dp = ap -> dp ,
194+ .apsel = 0x4U ,
195+ };
196+
197+ return nrf91_ctrl_ap_mass_erase (& ctrl_ap );
198+ }
199+
200+ static bool nrf91_exit_flash_mode (target_s * const target )
201+ {
202+ adiv5_access_port_s * ap = cortex_ap (target );
203+ /* Persist AP access if uninitialized (only needed for devices with hardenend APPROTECT) */
204+ if (ap -> dp -> target_revision > 2 ) {
205+ bool approtect_erased = target_mem_read32 (target , NRF91_UICR_APPROTECT ) == NRF91_UICR_ERASED_VAL ;
206+ bool secureapprotect_erased = target_mem_read32 (target , NRF91_UICR_SECUREAPPROTECT ) == NRF91_UICR_ERASED_VAL ;
207+
208+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_WEN );
209+
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+ if (approtect_erased ) {
216+ target_mem_write32 (target , NRF91_UICR_APPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
217+ }
218+ if (secureapprotect_erased ) {
219+ target_mem_write32 (target , NRF91_UICR_SECUREAPPROTECT , NRF91_UICR_APPROTECT_UNPROTECT_VAL );
220+ }
221+
222+ target_mem_write32 (target , NRF91_NVMC_CONFIG , NRF91_NVMC_CONFIG_REN );
223+ }
224+ return true;
84225}
85226
86227bool nrf91_probe (target_s * target )
87228{
88229 adiv5_access_port_s * ap = cortex_ap (target );
89230
90- if (ap -> dp -> version < 2U )
231+ if (ap -> dp -> version < 2U || ap -> dp -> target_partno != NRF91_PARTNO )
91232 return false;
92233
93- switch (ap -> dp -> target_partno ) {
94- case 0x90 :
234+ uint32_t partno = target_mem_read32 (target , 0x00FF0140 );
235+ uint32_t hwrevision = target_mem_read32 (target , 0x00FF0144 );
236+ uint32_t variant = target_mem_read32 (target , 0x00FF0148 );
237+
238+ DEBUG_INFO ("nRF%04" PRIx32 " %4s%4s detected!\n" , partno , (const char * )& variant , (const char * )& hwrevision );
239+
240+ switch (ap -> dp -> target_revision ) {
241+ case 0 :
242+ case 1 :
243+ case 2 :
95244 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 ) ;
245+ break ;
246+ case 3 :
247+ target -> driver = "Nordic nRF91x1" ;
99248 break ;
100249 default :
250+ target -> driver = "Nordic nRF91" ;
251+ }
252+
253+ target -> target_options |= TOPT_INHIBIT_NRST ;
254+ target_add_ram (target , 0x20000000 , 256U * 1024U );
255+ nrf91_add_flash (target , 0 , 4096U * 256U , 4096U );
256+
257+ target -> mass_erase = nrf91_mass_erase ;
258+ target -> exit_flash_mode = nrf91_exit_flash_mode ;
259+
260+ return true;
261+ }
262+
263+ static bool nrf91_rescue_do_recover (target_s * target )
264+ {
265+ adiv5_access_port_s * ap = (adiv5_access_port_s * )target -> priv ;
266+
267+ const bool hardened_approtect = ap -> dp -> target_revision > 2 ;
268+
269+ /* on some revisions, this needs to be repeated */
270+ for (size_t i = 0 ; i < 3 ; ++ i ) {
271+ if (!nrf91_ctrl_ap_mass_erase (ap ))
272+ continue ;
273+ if (!hardened_approtect ) {
274+ /* pin reset is needed on older devices */
275+ platform_nrst_set_val (true);
276+ platform_delay (100 );
277+ platform_nrst_set_val (false);
278+
279+ /* repetition not needed and debug port inactive at this point */
280+ return false;
281+ }
282+
283+ //check if CSW DEVICEEN is set
284+ struct adiv5_access_port ahb_ap = * ap ;
285+ ahb_ap .apsel = 0x0U ;
286+ const uint32_t csw = ap -> dp -> ap_read (& ahb_ap , ADIV5_AP_CSW );
287+ if (csw & ADIV5_AP_CSW_DEVICEEN ) {
288+ DEBUG_INFO ("nRF91 Rescue succeeded.\n" );
289+ break ;
290+ }
291+ }
292+
293+ return false;
294+ }
295+
296+ bool nrf91_rescue_probe (adiv5_access_port_s * ap )
297+ {
298+ target_s * target = target_new ();
299+ if (!target ) {
101300 return false;
102301 }
302+ adiv5_ap_ref (ap );
303+ target -> attach = (void * )nrf91_rescue_do_recover ;
304+ target -> priv = ap ;
305+ target -> priv_free = (void * )adiv5_ap_unref ;
306+ target -> driver = "nRF91 Rescue (Attach, then scan again!)" ;
103307
104308 return true;
105309}
310+
311+ /* check if nRF91 target is in secure state, return false if device is protected */
312+ bool nrf91_dp_prepare (adiv5_debug_port_s * const dp )
313+ {
314+ adiv5_access_port_s ahb_ap = {
315+ .dp = dp ,
316+ .apsel = 0x0U ,
317+ };
318+ adiv5_access_port_s ctrl_ap = {
319+ .dp = dp ,
320+ .apsel = 0x4U ,
321+ };
322+ ahb_ap .idr = adiv5_ap_read (& ahb_ap , ADIV5_AP_IDR );
323+ ahb_ap .csw = adiv5_ap_read (& ahb_ap , ADIV5_AP_CSW );
324+ ctrl_ap .idr = adiv5_ap_read (& ctrl_ap , ADIV5_AP_IDR );
325+
326+ if (ahb_ap .idr != NRF91_AHB_AP_IDR_EXPECTED ) {
327+ DEBUG_ERROR (
328+ "nRF91: AHB-AP IDR is 0x%08" PRIx32 ", expected 0x%08" PRIx32 "\n" , ahb_ap .idr , NRF91_AHB_AP_IDR_EXPECTED );
329+ }
330+
331+ if (ctrl_ap .idr != NRF91_CTRL_IDR_EXPECTED ) {
332+ DEBUG_ERROR (
333+ "nRF91: CTRL-AP IDR is 0x%08" PRIx32 ", expected 0x%08" PRIx32 "\n" , ctrl_ap .idr , NRF91_CTRL_IDR_EXPECTED );
334+ }
335+
336+ if (!(ahb_ap .csw & ADIV5_AP_CSW_DEVICEEN )) {
337+ DEBUG_INFO ("nRF91 is in secure state, creating rescue target\n" );
338+ adiv5_access_port_s * ap = calloc (1 , sizeof (* ap ));
339+ if (!ap ) { /* calloc failed: heap exhaustion */
340+ DEBUG_ERROR ("calloc: failed in %s\n" , __func__ );
341+ return false;
342+ }
343+ memcpy (ap , & ctrl_ap , sizeof (* ap ));
344+ nrf91_rescue_probe (ap );
345+ return false;
346+ }
347+ return true;
348+ }
0 commit comments