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

Writing to UICR from application code

Hello,

I am truing to store data in the UICR register "customer area" from application code. The procedure is invoked only once when the registers are still empty. The code is as follows:

void write_to_uicr()
{
        uint32_t data_to_write;

        uint32_t err_code = sd_softdevice_disable();
        APP_ERROR_CHECK(err_code);

        interrupts_disable();
        //...

        data_to_write = get_data();

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;	
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        *(uint32_t *)0x10001080 = data_to_write ;
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;	
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

}

Unfortunately the only data written to the registers is 0x00000000 even though I can verify with the debugger that the value of the "data_to_write" variable is different than zero and it is as expected. Optimizations are switched off. I would be more than glad to get any input on this problem. Thank you in advance!

  • I am adding more details related to the problem in this post. In general the code that I am debugging is in two files. The first file contains a variable which is retrieved and stored in the UICR from the second file.

    Data provider (provider.c):

     ...
    static uint32_t data;
    ...
    
    uint32_t get_data(void)
    {
        return data;
    }
    

    UICR write (write.c)

    ...
    extern uint32_t get_data(void);
    ...
    static void update_uicr_customer_data()
    {
        data = get_data();
    
        if(data != 0){
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
            *(uint32_t *)0x10001080 = data;
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        }else
        {
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
            *(uint32_t *)0x10001080 = 0x22222222;
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
        }
    }
    

    With the debugger I can verify that the content of the "data" variable is "1234" after the function returns and this is what I expect to get as a result. Then the if statement is executed. The else is there just to prove that data != 0.

    The content of the 0x10001080 at this point is:

    0x10001080: 00001234 FFFFFFFF FFFFFFFF FFFFFFFF
    

    However, after a power-cycle of the chip the content of the memory location reads back as:

    0x10001080: 00000220 FFFFFFFF FFFFFFFF FFFFFFFF
    

    Furthermore, if i replace the call to the external function with a call to function in the same file (write.c) the writing procedure goes as expected and the value is preserved after power-cycle.

    It looks like I am doing something wrong, but I was blaming the UICR write... Do you have comments on this? Thank you in advance.

  • Down to guesswork at this point. If the value is correct after the write, then the next logical guess is that you're writing it again somewhere else, either before the chip power cycles or straight afterwards, and putting in a different value. 0x0000220 is what you would get if you wrote 0x00001234 followed by 0x22222222, sure you're not doing that?

    Can you set a memory write breakpoint at that address, segger supports those, which should tell you if you or something else writes there again.

  • Thanks for the help RK! You were right my code was righting to the same memory location twice.

Related