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.

Parents Reply Children
  • Am I also correct in thinking that the soft device needs to be disabled first using sd_softdevice_disable()?

    If so, is that the correct function? I keep getting an 'undefined reference to sd_softdevice_disable()' error.

  • Hi,

    I thought I would put together an example that demonstrated this, but unfortunately it turns out that writing to the UICR with the SoftDevice enabled is not allowed, which I had forgotten. This has been requested before but it does not look like it will be implemented. So then your only option is to write to UICR with the SoftDevice disabled, or to store your serial number elsewhere in flash. I am sorry for the confusion.

    You use sd_softdevice_disable() to do that, but then you need to include nrf_sdm.h where it is declared. Note that wile disabling the SoftDEvice itself is no problem, most SDK libraries that interface the SoftDevice are not designed to handle the SoftDevice being disabled, so it is not as straight forward as you would think.

  • 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