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
  • Hi,

    Yes, you can program the UICR from firmware. However, this is flash and not RAM, so you need to do it in a different way. If you do it without/before the SoftDevice is enabled, you can do it in the same way as shown in this code snippet from boards.c (just replace the destination address with another part of the UICR):

            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
            NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
                                (UICR_REGOUT0_VOUT_3V0 << UICR_REGOUT0_VOUT_Pos);
    
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

    If you need to do this while the SoftDevice is enabled you should use sd_flash_write() instead.

  • Thanks for your reply.

    Just to clarify, during initialisation the firmware retrieves the serial number from address 0x10001080. Then during normal runtime, the new serial is sent over BLE and I need to write that to the same location, so after a reboot the serial is updated. If I understand correctly, then the softdevice is already running so I need to use the sd_flash_write() method?

  • 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 (;; )
    

Reply Children
No Data
Related