How to write data to UICR CUSTOMER registers?

I have some keyword, want to save to UICR CUSTOMER registers. Then, when I start he board, I can get the data from UICR CUSTOMER registers. but, I donot know how to ?

Functional description The User Information Configuration Registers (UICRs) are NVM registers for configuring user specific settings. Code readback protection of the whole code area, or a part of the code area can be configured and enabled in the UICR. The UICR can only be erased by using ERASEALL. The code area can be divided into two regions, code region 0 (CR0) and code region 1 (CR1). Code region 0 starts at address 0x00000000 and stretches into the code area as specified in the CLENR0 register. The area above CLENR0 will then be defined as code region 1. If CLENR0 is not configured, that is, has the value 0xFFFFFFFF, the whole code area will be defined as code region 1 (CR1). Code running from code region 1 will not be able to write to code region 0. Additionally, the content of code region 0 cannot be read from code running in code region 1 or through the SWD interface if code region 0 is readback protected, see PR0 in RBPCONF. The main readback protection mechanism that will protect the whole code, that is, both code region 0 and code region 1, is also configured through the UICR. The PAGEERASE command in NVMC will only work for code region 1. See NVMC chapter for information on how to erase and program the code area and the UICR.

I follow it as above, I can not do it well.

  • Hi, the approach for setting these registers depends on when you want to do it. I.e., at compile time or at runtime.

    You can for instance use the attribute keyword to declare a variable in one of the customer registers so that it gets included in the FW image (Keil)

    uint32_t  user_data  __attribute__((at(NRF_UICR->CUSTOMER[x])) = VALUE; 
    

    Or if you wish to write to set the register during program execution (should be done prior to initialization of SD):

        if (NRF_UICR->CUSTOMER[x] == 0xFFFFFFFF) 
        {
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
            NRF_UICR->CUSTOMER[x] = VALUE;
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        }
    
  • unsigned long dataflash[32];

    void write32data(void) { NRF_NVMC->CONFIG=2;//FOR DEL NRF_NVMC->ERASEUICR=1; //while(NRF_NVMC->READY==0);

    NRF_NVMC->CONFIG=1;//FOR write
    for(int tmpi=0;tmpi<32;tmpi++)
    {
    	NRF_UICR->CUSTOMER[tmpi]=dataflash[tmpi];
    }
    NRF_NVMC->ERASEUICR=0;
    NRF_NVMC->CONFIG=0;//FOR READ
    

    }

    void read32data(void) { NRF_NVMC->CONFIG=0;//FOR READ for(int tmpi=0;tmpi<32;tmpi++) { dataflash[tmpi]=NRF_UICR->CUSTOMER[tmpi]; } }

    I write a some code to operate the UICR. but run in s130 with BLE will error.

  • Is this compile-time approach supported by GCC?

  • the AT keyword is not supported, but you can do something like this:

    volatile uint32_t user_data  __attribute__ ((section(".uicr_customer"))) = VALUE;
    

    then add and configure the placement of this section in the linker script:

    MEMORY
    {
       ...
       UICR (r) : ORIGIN = 0x10001080, LENGTH = 0x4
    }
    
    SECTIONS
    { 
      ...
      .uicr_customer : 
      {
        KEEP(*(.uicr_customer))
      } > UICR
    
    }
    
Related