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

nRF52832 UICR serial number programming

In firmware I can read the programmed UICR serial number as follows: -

uint32_t serial;

memcpy(&serial, (uint32_t*)0x10001080, 4);

Is it possible to program the UICR from within the firmware during runtime?

Using the reverse  - memcpy( (uint32_t*)0x10001080, 4) doesn't work.

I would like to send a command to the nRF52 containing the serial number and write it to the UICR register.

  • Thanks for your answer. I'm getting closer now. With the following code: -

     err_code = sd_softdevice_disable();

     if( err_code == NRF_SUCCESS )
     {
     // Enable write mode.
     NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een<<NVMC_CONFIG_WEN_Pos;
     while(NRF_NVMC->READY == NVMC_READY_READY_Busy){}

     // write value to the register
     NRF_UICR->CUSTOMER[0] = serial;

     // Disable flash writing
     NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren<<NVMC_CONFIG_WEN_Pos;
     while(NRF_NVMC->READY == NVMC_READY_READY_Busy){}

     }
     
     // now reboot the nRF52 - there is no return from this command!
     NVIC_SystemReset();

    All steps work, and the device reboots successfully, but the register value has not changed. I have read in other threads that after writing to the UICR and before restarting the softDevice needs to be re-enabled using sd_softdevice_enable(). Is this the case?

  • Hi,

    You need to adjust the code like this (how you enable and disable flash writing):

    // Enable write mode.
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    // write value to the register
    NRF_UICR->CUSTOMER[0] = serial;
    
    // Disable flash writing
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

    This works for me when modifying the beacon example in SDK 17.0.2 to test, as shown by this diff:

    diff --git a/examples/ble_peripheral/ble_app_beacon/main.c b/examples/ble_peripheral/ble_app_beacon/main.c
    index eebe67a..bebdf8b 100644
    --- a/examples/ble_peripheral/ble_app_beacon/main.c
    +++ b/examples/ble_peripheral/ble_app_beacon/main.c
    @@ -57,6 +57,8 @@
     #include "ble_advdata.h"
     #include "app_timer.h"
     #include "nrf_pwr_mgmt.h"
    +#include "nrf_sdm.h"
    +#include "nrf_delay.h"
     
     #include "nrf_log.h"
     #include "nrf_log_ctrl.h"
    @@ -285,6 +287,54 @@ static void idle_state_handle(void)
         }
     }
     
    +static void check_write_uicr_serial(void)
    +{
    +    static const uint32_t serial = 123456;
    +    ret_code_t err_code;
    +
    +    if (NRF_UICR->CUSTOMER[0] == serial)
    +    {
    +        NRF_LOG_INFO("Serial allready set.");
    +    }
    +    else
    +    {
    +        if (NRF_UICR->CUSTOMER[0] == ~0)
    +        {
    +            // Word is erased (all '1'), so ready to write serial number
    +            err_code = sd_softdevice_disable();
    +
    +            if( err_code == NRF_SUCCESS )
    +            {
    +                NRF_LOG_INFO("Write to UICR.");
    +
    +                // Enable write mode.
    +                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    +                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    +
    +                // write value to the register
    +                NRF_UICR->CUSTOMER[0] = serial;
    +
    +                 // Disable flash writing
    +                NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
    +                while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    +
    +                // now reboot the nRF52 - there is no return from this command!
    +                NVIC_SystemReset();
    +            }
    +            else
    +            {
    +                NRF_LOG_INFO("Failed to disable SoftDevice.");
    +            }
    +        }
    +        else
    +        {
    +            NRF_LOG_INFO("UICR register contains invalid data (not serial, but not all '1')");
    +        }
    +    }
    +}
    +
    +
    +
     
     /**
      * @brief Function for application main entry.
    @@ -297,11 +347,11 @@ int main(void)
         leds_init();
         power_management_init();
         ble_stack_init();
    -    advertising_init();
     
         // Start execution.
         NRF_LOG_INFO("Beacon example started.");
    -    advertising_start();
    +    nrf_delay_ms(100);
    +    check_write_uicr_serial();
     
         // Enter main loop.
         for (;; )
    

Related