Example code to write to UICR

I am trying to store data to the UICR using SDK16, mesh SDK 4.2.0 and the nRF52840 chip.

I want to write to the UICR once on runtime and never again. To avoid messing with the softdevice, I am trying to write to the UICR before calling ble_stack_init() and after __LOG_INIT to get logs working.

This is the code:

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

uint32_t * consumer0 = (uint32_t *) 0x10001080;
*consumer0 = 0x00000005;

NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%d\n", *consumer0);

NVIC_SystemReset();

So we put the NVMC in Write enable, wait for it to be ready, write to consumer0, put it in Read enable, wait for it to be ready and reset the device. I can see 5 logged to Segger console.

Then I comment what I don't need:

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

uint32_t * consumer0 = (uint32_t *) 0x10001080;
//*consumer0 = 0x00000005;

//NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
//while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%d\n", *consumer0);

//NVIC_SystemReset();

And I see -1 logged to Segger console, meaning the flash still has the 0xFFFF on that position. I can confirm it on Segger Memory explorer that 10001080 is never filled with the data I wanted. Am I doing something wrong?

  • Although this does not answer the original question,
    In the code provided by Einar,
    I believe the line

    if (*addr != 0xFFFFFFFF)

    should actually be

    if ( (*addr & word) != word )

              { /* UICR has bits cleared that word needs set. Erase is required */

         ....

              }
                   

    This is a problem with nrfjprog as reported in

    nrfjprog --memwr-0x10001080 --val 0x01010101 shouldn't fail second-time

    As a test, to assist with diagnosing,  you tried using nrfjprog?

    Is it necessary to restore NVM to read state using 

    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);

  • Hi All,

    I am experiencing the same problem, meaning I write to the UICR but when I flash the firmware again using SES or nRF Programmer the content of the UICR is also erased. Can you please help?

    If rmarques has resolved his problem it would be good if the solution is shared on this platform.

    Thank you.

    Kind regards
    Mohamed
  • Hi Mohamed,

    The UICR page is only erased when you do a full chip erase (eraseall) / recover. Do you by any chance use access port protection (APPROTECT) / readback protection? If so, a recover is needed, and the programmer will do it for you (it should ask by default, though). Is that what is happening here here?

  • Hi Thorsrud,

    Yes, you hit the nail on the head!

    That is exactly what I am doing at every boot-up to check if I am running a release or a debug version of the code.

    void system_SetDebugPortAccess(void)
    {
    #if (CONFIG_DEBUG_PORT_ACCESS)
    
        /* Prevent chip from locking itself in hardware (if not already set) */
        if (NRF_UICR->APPROTECT != UICR_APPROTECT_PALL_HwDisabled)
        {
            LOG_ERR("Device debug prevented on next POR (0x%08X), resetting to disable this.", NRF_UICR->APPROTECT);
            system_WriteDebugPortAccess(UICR_APPROTECT_PALL_HwDisabled);
        }
    
        /* Prevent chip from locking itself in software */
        NRF_APPROTECT->DISABLE = APPROTECT_DISABLE_DISABLE_SwDisable;
    
    #else
        /* Enforce HW protection (if not already set) */
        if (NRF_UICR->APPROTECT != UICR_APPROTECT_PALL_Enabled)
        {
            LOG_ERR("Device debug allowed on next POR (0x%08X), resetting to disable this.", NRF_UICR->APPROTECT);
            system_WriteDebugPortAccess(UICR_APPROTECT_PALL_Enabled);
        }
    
        /* Belts and braces, enforce SW protection */
        NRF_APPROTECT->FORCEPROTECT = APPROTECT_FORCEPROTECT_FORCEPROTECT_Force;
    
    #endif //CONFIG_DEBUG_PORT_ACCESS
    }
    

    Any suggestion how to avoid UICR register being erased?

    Kind regards
    Mohamed
  • My original problem was not resolved, every time I programmed a device the UICR was reset to its original values, could be a nrfjprog or segger issue. My team just stopped trying to store config data on the UICR and just stored it in mesh config entry...

    Also, we could not erase the UICR on runtime, could be our mistake or not, but if your project already uses the MeshSDK, just use mesh config entry to store your data, it's a no-brainer, all of these issues disappeared and mesh config entry is not that difficult to learn, setup and use.

Related