APPROTECT and verify with nrfjprog

Hi

On the nRF52840-QIAA-R there should be implemented the APPROTECT according to this guide:

https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/working-with-the-nrf52-series-improved-approtect

Informational Notice (IN) - Vulnerability of the nRF52 series.

I implemented now the suggested code on top of main:

void AppProtection(void)
{
#ifdef ENABLE_APPROTECT
	if ((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) !=
		(UICR_APPROTECT_PALL_Enabled << 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_Enabled << UICR_APPROTECT_PALL_Pos));

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        NVIC_SystemReset();
   	}
#else
	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();
	}
#endif
}

This is working, but the problem is that the verify in production programming is not working anymore. Is there an option to verify the chip before? Because after a program the chip is getting restarted and read out protection is active which makes verify impossible. Is there a solution to verify with nrfjprog or use nrfjprog to program without starting the code on the nRF52?

nrfjprog --program %HEX_FILE% --verify --log

  • Ok, now I managed to enable ReadProtect only the second time after reset because of the Verify issue.
    To manage this, I use a command line before program / verify and check this value in the App:

    nrfjprog --memwr 0x000F5000 --val 0x12345678

    if I read the address before enabling the ReadBackProtection I read 0xDEADC0DE

    nrfjprog --memrd 0x000F5000 0x000F5000: DEADC0DE 

    my bootloader is starting at 0xF6000 and has 32kB, so in the memory map the part lower than 0xF6000 should be empty, but what this 0xDEADC0DE is meaning?

    Is it safe to use this region below (grey) or should I avoid this? Is there any other way to do the ReadBackProtection in the App only after the second Reset without this Falsh? UICR is not working, I guess the internal falsh is ok only the 0xDEADC0DE is confusing me...

  • I think it's possible to use NRF_UICR->CUSTOMER[x] flag to enable the NRF_UICR->APPROTECT only after the second Reset/Boot, and with nrfjprog --eraseall the flags in uicr will be reset to default before flashing.I will try

  • Hi Dominik,

    That does sound like a good way. And you are also right that --eraseall resets UICR, including protection flags.

    -Priyanka

  • Hi Priyanaka

    With the UIR flags its possible and working like expected.

    The logic is the following: Bootloader has its own UICR (index 1), application has its own UICR (index 0).

    If the index is empty, the bootloader and app is writing the predefined value to this index. Next restart (Reset, Power Reset) the code is checking this value and is writing the AppProtection Flag following by a reset. This logic is needed to ensure that the fisrt time the AppProtect is not activated, second time yes. 

    The if is preventing that this is happening at every reset, it will happen only once:

    void AppProtection(void)
    {
    #ifdef ENABLE_APPROTECT
        if (!is_customer_magic_set())
        {
            NRF_LOG_DEBUG("Customer Magic is not active");
            uicr_write_customer_magic();
        }
        else
        {
            NRF_LOG_DEBUG("Enable AppProtection");
            if ((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) !=
        		(UICR_APPROTECT_PALL_Enabled << 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_Enabled << UICR_APPROTECT_PALL_Pos));
    
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
    
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
                NVIC_SystemReset();
            }
    #else
        	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));
    
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
    
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
                NVIC_SystemReset();
        	}
    #endif
        }
    }

    Thank you for your help and if there is any issue or problem in the code please let me know

  • Hi,

    This looks like a good approach and the code snippet also looks nice. Slight smile

    Regards,

    Priyanka

Related