This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to enable/disable UICR custom registers writes through APPROTECT?

Hello Devzone:

Would I be correct if I assume enabling APPROTECT should prevent writes into UICR? - for other readers, NO, IT CANNOT PROTECT AGAINST SOFTWARE READS/WRITES, ONLY DEBUGGER

Based on this assumption I wrote the following code to enable APPROTECT:

NRF_NVMC->CONFIG = 0x1;//NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; 
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
NRF_UICR->APPROTECT = 0x00;
NRF_NVMC->CONFIG = 0x0; //NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; 
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

And I indeed observed my writes into UICR are invalid because I can't read back the same values I wrote, read values are only 0xFFFFFFFFs.

The problem is now I can't re-enable UICR writes.

I thought replacing 2nd line in the above code with

NRF_UICR->APPROTECT = 0xFF;

would re-enable UICR writes, but in experiment my UICR writes are still invalid.

How do i disable APPROTECT and re-enable UICR writes?

Thanks!

Best regards.

Parents
  • Just to be very clear:

    The UICR locations are not just arbitrarily writable. Initially the UICR locations are in the erased state (shows 0xFF when read). Individual locations can be written to set their values. But once written, a location can't be modified again _unless_ you issue the ERASEUICR command to return the entire UICR to the erased state and then program it all over again.

    Enabling the APPPROTECT feature requires writing a 0x00 to NRF_UICR->APPROTECT. So once you do that, the only way to change it back to 0xFF is to erase the UICR.

    Note that the reset pin selection is also stored in the UICR, so if you erase it, you should remember to restore it, otherwise the external reset button will stop working.

    Here's an example of the code I wrote once for the nRF52840 to erase and reprogram the UICR:

    https://github.com/netik/dc27_badge/blob/master/software/firmware/badge/main.c#L352

    Also, enabling the APPROTECT feature does not "prevent writes to the UICR." What it does is disable the CPU's debug access port (DAP) so that you can no longer issue commands via the SWD pins to debug the CPU. This blocks the debugger from accessing anything on the CPU, not just the UICR fields.

    In order to recover a device which has been setThis this way (and where the firmware loaded into the device has no option to do it for you), you have to issue an ERASEALL command via the CTRL-AP port (which is a vendor-specific access port separate from the debug AP). The ERASEALL command will blank both the flash and the UICR (i.e. returns the chip back to its "fresh off the assembly line" state). You can issue an ERASEALL command via the NVMC registers too, but if the APPROTECT feature is turned on, the NVMC registers will also be inaccessible via the debug port. The CTRL-AP access mechanism provides an alternate way to reset the chip. The difference is that while this lets you recover a locked device, it doesn't allow you to download the contents of the flash first (i.e. software in a locked device is still protected from unauthorized access).

    Most of the time if you ask how to do this, you will be told to use the nrfjprog utility. However there are other ways to issue this command with a debugger. Here's an example of how to do it with OpenOCD and an arbitrary JTAG/SWD debugger:

    https://github.com/netik/dc27_badge/blob/master/hardware/programming/debug.txt#L41

    -Bill

Reply
  • Just to be very clear:

    The UICR locations are not just arbitrarily writable. Initially the UICR locations are in the erased state (shows 0xFF when read). Individual locations can be written to set their values. But once written, a location can't be modified again _unless_ you issue the ERASEUICR command to return the entire UICR to the erased state and then program it all over again.

    Enabling the APPPROTECT feature requires writing a 0x00 to NRF_UICR->APPROTECT. So once you do that, the only way to change it back to 0xFF is to erase the UICR.

    Note that the reset pin selection is also stored in the UICR, so if you erase it, you should remember to restore it, otherwise the external reset button will stop working.

    Here's an example of the code I wrote once for the nRF52840 to erase and reprogram the UICR:

    https://github.com/netik/dc27_badge/blob/master/software/firmware/badge/main.c#L352

    Also, enabling the APPROTECT feature does not "prevent writes to the UICR." What it does is disable the CPU's debug access port (DAP) so that you can no longer issue commands via the SWD pins to debug the CPU. This blocks the debugger from accessing anything on the CPU, not just the UICR fields.

    In order to recover a device which has been setThis this way (and where the firmware loaded into the device has no option to do it for you), you have to issue an ERASEALL command via the CTRL-AP port (which is a vendor-specific access port separate from the debug AP). The ERASEALL command will blank both the flash and the UICR (i.e. returns the chip back to its "fresh off the assembly line" state). You can issue an ERASEALL command via the NVMC registers too, but if the APPROTECT feature is turned on, the NVMC registers will also be inaccessible via the debug port. The CTRL-AP access mechanism provides an alternate way to reset the chip. The difference is that while this lets you recover a locked device, it doesn't allow you to download the contents of the flash first (i.e. software in a locked device is still protected from unauthorized access).

    Most of the time if you ask how to do this, you will be told to use the nrfjprog utility. However there are other ways to issue this command with a debugger. Here's an example of how to do it with OpenOCD and an arbitrary JTAG/SWD debugger:

    https://github.com/netik/dc27_badge/blob/master/hardware/programming/debug.txt#L41

    -Bill

Children
No Data
Related