Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Unresponsive device when flashing after disabling APPPROTECT

Hi,

I'm developing on the current setup:

  • nRF52840
  • Soft Device 140 version 7.2.0
  • SDK 17.1.0 
  • MDK: 8.51
  • Segger v4.52c
  • Secure bootloader (DFU)

I don't define ENABLE_APPROTECT in the preprocessor and I've followed this guide: Working with the nRF52 Series' improved APPROTECT - Blogs - Nordic Blog - Nordic DevZone, which led me to included this code as the first thing main executes:

void approtect_disable( void )
{
	if ( ( NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk ) != ( UICR_APPROTECT_PALL_HwDisabled << UICR_APPROTECT_PALL_Pos ) ) {

		NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
		while ( NRF_NVMC->READY == NVMC_READY_READY_Busy ) {}

		NRF_UICR->APPROTECT = ( ( NRF_UICR->APPROTECT & ~( ( uint32_t )UICR_APPROTECT_PALL_Msk ) ) |
		                        ( UICR_APPROTECT_PALL_HwDisabled << UICR_APPROTECT_PALL_Pos ) );

		NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
		while ( NRF_NVMC->READY == NVMC_READY_READY_Busy ) {}
		NVIC_SystemReset();
	}
	NRF_APPROTECT->DISABLE = APPROTECT_DISABLE_DISABLE_SwDisable;
}

However, it only works partially. Before including this code, each time I tried to download & debug with Segger, I would get the usual message "CTRL-AP indicates that the device is secured. For debugger connection the device needs to be unsecured. Note: unsecuring will trigger a mass erase of the internal flash" from the JLink driver. After accepting, the application would download correctly but as soon as the nRF reset itself (part of the application sequence), I lost all trace information, which was extremely inconvenient.

After including this code, I no longer get the message and traces keep working even after a reset. However, if I try to download & debug again, the code doesn't run and the uC seems to be stuck at a random location:

When in this state, I can do an "Erase all" from Segger or --eraseall from nrfjprog, but it doesn't fix the issue. I can only fix it after I send a "nrfjprog --recover" from the command line. After that, the next Segger download & debug works fine.

What could be the issue?

Thank you!

Parents
  • Hi,

    The nrfjprog --recover procedure differs from the JLink unsecuring procedure in that it will also write 0x5A to the UICR.APPROTECT register and load a small FW image that will unlock approtect in SW (i.e. write 0x5A to the NV NRF_APPROTECT->DISABLE register) after the ERASEALL. 

    The problem is that the bootloader includes data in the UICR region (@0x10001014 and 10001018) which causes the UICR section to be erased when you program the bootloader image. This means the UICR.APPROTECT will be set to '0xff' again, causing 0xFF to be written to NRF_APPROTECT->DISABLE in your startup code before reaching main().

    https://docs.nordicsemi.com/bundle/ps_nrf52840/page/dif.html 

    After including this code, I no longer get the message and traces keep working even after a reset. However, if I try to download & debug again, the code doesn't run and the uC seems to be stuck at a random location:

    Are you able to read out the UICR.APPROTECT register at this point? 

    Best regards,

    Vidar

  • Hi Vidar, thanks for the answer.

    At that point, the register window in Segger shows this:

    I didn't fully understand your logic regarding the bootloader overwriting the NRF_APPROTECT->DISABLE. Wouldn't it happen too in this sequence?:

    • nrfjprog --recover
    • download & debug from segger
      • Load soft device
      • load dfu settings
      • load bootloader
      • load app

    If the bootloader overwritting NRF_APPROTECT->DISABLE is the issue, can I modify the bootloader project to have the 0x5A be part of the hex file that is being burned? I see the hex file includes contents for 0x10001014 and 10001018, but I couldn't find in the code where this is defined.

  • Hi,

    The problem is the UICR.APPROTECT register @ 0x10001208. The programmer will erase the UICR section before writing to 0x10001014 and  0x10001018 when loading the bootloader image. However, the code snippet you posted should take care of this. Can you check if the UICR.APPROTECT is 0x5a?

Reply Children
  • Hi,


    Sorry I posted the wrong register. Here's the right one, I hope. 0x10001208 is set to 0xFF. What does this mean?

  • Hi,

    It should be set to 0x5a after the approtect_disable() function has been executed. Can you place a breakpoint after this function call to confirm?

  • The short answer is that it only reaches that point after a recover, and the value is actually 0x5A. If I try to flash again, it will not even reach main, it gets stuck somewhere else. 

    I think I haven't explained myself clearly. I'll try to put a detailed sequence here: 

    • nrfjprog --recover
    • Download & debug from segger. Segger is configured to "Additional Load" other hex files, which are the soft device, Bootloader and dfu settings, in that order.
    • This reaches main and executes without issues.
    • Goes through the approtect_disable function and leaves NRF_APPROTECT->DISABLE in 0x5A and NRF_UICR->APPROTECT in 0xFF.
    • Debugger works too, even through device resets.
    • Stop debugging session
    • Download & Debug again (no prompt to recover)
    • Now the execution never reaches main, it's stuck somewhere that appears invalid code, as I showed in the original post.
    • FORCEPROTECT shows as 1 (0x40000550)
    • NRF_APPROTECT->DISABLE shows as 1 (0x40000558)
    • NRF_UICR->APPROTECT shows as 0xFF (0x10001208)
    • Stop debugging session
    • Download and Debug again. This prompts for a recovery, press OK and now it works.

    So, it seems to be working every other time. I was under the impression that I could only make it work again with "nrfjprog --recover", but now Segger is prompting me for recovery so it seems to work. Not sure what changed.

    Thanks!

  • Thanks for the summary. The UICR will be cleared every time the bootloader FW is loaded. As a result the, the APPROTECT mechansim will not become unlocked until the program reaches the approtect_disable() call in app main(). To confirm this, you can remove the bootloader hex from the "Additional Load" field.

  • Hi Vidar, yes I can confirm that by disabling the "bootloader.hex" Additional Load, it works fine. But we do need to load it.Based on what you said, I modified the bootloader project to run approtect_disable in main and now the issue seems to be gone.

    This would suggest that the bootloader.hex code is running before flashing the app.hex file? Like in-between Additional Loads. Does that make sense? I'm still not sure I understood everything.

Related