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

Writing data to UICR region and flashing device

I'm trying to accomplish two things:

1. Write 2 values to the UICR (2 arrays actually - a serial number and encryption keys).
2. Flash the device in such a way that the information in UICR is preserved.

My questions:

1. Whats the UICR address range? (Based on the  NRF SDK, the UICR base address is 0x10001000UL). The reason I ask is because I can see in the fstorage example that you can specify the start and end addresses of the flash region to reserve for your purposes. In my case I would like to reserve memory starting from  the UICR address base. What's the recommended address range to use?

2. Using nrfjprog, I can specify which areas of flash to erase and keep UICR, by specifying the start and end address of the regions I want to erase. Would it make sense to simply specify the address range as 00000000 - 000ffffff (this is the entire flash) memory range. If I specify this range, would the programmer wipe everything except UICR data (if i specify the --sectorerase option)? I can see from my current application that it lies in the address range 00000000 - 00012b07.
Any reccommendations on what address range to specify to erase?

For now I'm trying to accomplish this without SoftDevice enabled.


Thanks (I'm a bit new to memory management) :)

Parents Reply Children
  • Hi,

    1. UICR contains registers that are reserved for other uses as well, UICR.PSELRESET[] that enables the reset pin for instance. But you can use the "CUSTOMER" registers. A description of the different registers can be found in the PS here: https://infocenter.nordicsemi.com/topic/ps_nrf52840/uicr.html?cp=3_0_0_3_4 

    2.  When writing to flash you need to specify the exact address you want to write to. E.g., if you want to write to UICR.CUSTOMER[0]:

    nrfjprog --memwr 0x10001080 --val <32-bit value>

  • Okay. Would it therefore make sense to reserve the UICR customer adresses? The fstorage driver instance requires you to reserve an area of flash that you want to use. So, would this make sense:

    NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage_instance) =
    {
        .evt_handler = fstorage_evt_handler,
    
        .start_addr = 0x10001080UL, //CUSTOMER[0]
        .end_addr   = 0x100010FCUL, //CUSTOMER[31]
    };

  • fstorage is not suitable for writing data to the UICR. I'd recommend you to copy the approach used to enable the reset pin in system_nrf52840 if you need the app to set the serial number and encryption keys at runtime. 

            if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
                ((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))){
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; //<-- Enable flash write
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
                NRF_UICR->PSELRESET[0] = 21; //<-- write value to UICR register
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} <-- wait until write is complete
                NRF_UICR->PSELRESET[1] = 21; //<-- write value to UICR register
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; // <-- disable write access
                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
                NVIC_SystemReset(); // <-- Pinreset functionality is enabled after reset
            }

    Note that it's not possible to erase UICR from the app, so you cannot update an existing value in UICR. Also, it's not possible to write to UICR while the softdevice is enabled. 

  • Thanks so much for the reply.

    1. Why is fstorage not suitable?
    2. Using a similar approach like you described above, how would you read from the UICR?
  • Hi,

    1. The module is intended for managing NV memory storage in the FLASH region (0x0 - 0x80000). You can probably use fstorage to write data to the UICR if you don't use the softdevice backend (ie. can only be used while the softdevice is disabled). Since the UICR is intended for one-time configurations like serial numbers,etc., I don't think fstorage is worth the overhead. 

    2. UICR can be read it like any other register. E.g.,

    uint32_t serial_number;

    serial_number = NRF_UICR->CUSTOMER[x];

Related