Example code to write to UICR

I am trying to store data to the UICR using SDK16, mesh SDK 4.2.0 and the nRF52840 chip.

I want to write to the UICR once on runtime and never again. To avoid messing with the softdevice, I am trying to write to the UICR before calling ble_stack_init() and after __LOG_INIT to get logs working.

This is the code:

NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

uint32_t * consumer0 = (uint32_t *) 0x10001080;
*consumer0 = 0x00000005;

NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%d\n", *consumer0);

NVIC_SystemReset();

So we put the NVMC in Write enable, wait for it to be ready, write to consumer0, put it in Read enable, wait for it to be ready and reset the device. I can see 5 logged to Segger console.

Then I comment what I don't need:

//NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
//while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}

uint32_t * consumer0 = (uint32_t *) 0x10001080;
//*consumer0 = 0x00000005;

//NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
//while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%d\n", *consumer0);

//NVIC_SystemReset();

And I see -1 logged to Segger console, meaning the flash still has the 0xFFFF on that position. I can confirm it on Segger Memory explorer that 10001080 is never filled with the data I wanted. Am I doing something wrong?

Parents
  • Beware that sometimes Flash memory is cached by Segger and does not exactly show what you expect. I refer explicitly to 

    exec SetAllowFlashCache =0   

    Have you tried exiting Segger and starting it again to see if flash isn really set?

    In addition add a check in your coded to see what the value is.

    Finally choose your values wisely since if there PREVIOUS value of customer[0] was FFFFFFFF this will work BUT if the previous value was 05000000 it will not since write to flash can only reset bits. It is necessary to erase flash to set it to FFFFFFF

  • I tried exiting Segger and rechecking the memory, all was the same. I also added a small check for looking for the change in the flash like so:

    //NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    //while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    uint32_t * consumer0 = (uint32_t *) 0x10001080;
    //*consumer0 = 0x00000005;
    if(*consumer0 == 5){
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "*consumer0 = 5\n");
    }
    else {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Flash not correct, *consumer0 = %d\n", *consumer0);
    }
    
    //NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
    //while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    //NVIC_SystemReset();

    As soon as I comment the lines commented in the code I get the second __LOG: Flash not correct, *consumer0 = -1

  • Hi Mohamed,

    What you have found is correct (specifying family is optional). Specifically, nrfjprog never does an erase without "being told so", so that is no problem. To just flash your firmware if there was nothing there before, you can simply use "nrfjprog --program <hexfile>". If you want to overwrite an existing application (the pages you are writing to are not all FFFF), then add --sectorerase like this: "nrfjprog --program <hex> --sectorerase". With this, all pages that will be written to are erased first, but non of the others, and then the hex file is written.

  • Hi Thorsrud,

    I see, I thought I needed to explicitly specify the pages I wanted to erase because 'sectorerase expects arguments. so I don't need to specify the pages number after --sectorerase at the end of the command line. 

    I tried the command 

    nrfjprog -f NRF52 --program merged.hex –-sectorerase

    First I got this error,

    C:\Sandbox\HomeBeacon_dev_sb\build_nrf52833dk_nrf52833_v133_rel\zephyr>nrfjprog -f NRF52 --program merged.hex --sectorerase
    ERROR: The operation attempted is unavailable due to readback protection in
    ERROR: your device. Please use --recover to unlock the device.
    NOTE: For additional output, try running again with logging enabled (--log).
    NOTE: Any generated log error messages will be displayed.

    Then I tried

    C:\Sandbox\HomeBeacon_dev_sb\build_nrf52833dk_nrf52833_v133_rel\zephyr>nrfjprog -f NRF52 --recover --program merged.hex --sectorerase
    ERROR: Two arguments were provided that cannot be combined. Use --help to read
    ERROR: about the valid argument combinations.
    NOTE: For additional output, try running again with logging enabled (--log).
    NOTE: Any generated log error messages will be displayed.

    Finally, I tried

    C:\Sandbox\HomeBeacon_dev_sb\build_nrf52833dk_nrf52833_v133_rel\zephyr>nrfjprog -f NRF52 --recover --program merged.hex
    Recovering device. This operation might take 30s.
    Parsing image file.
    WARNING: A programming operation has been performed without --verify.
    WARNING: Programming can fail without error.

    But I ended up erasing the content of the UICR which I wanted to avoid.

    What am I doing wrong?

    Actually, I think the reason the command nrfjprog -f NRF52 --program merged.hex --sectorerase did not work it is because the device had the release version of the code which has CONFIG_DEBUG_PORT_ACCESS=n.

    So, I flashed the debug version (CONFIG_DEBUG_PORT_ACCESS=y) into the device then I tried the same command nrfjprog -f NRF52 --program merged.hex --sectorerase again and this time the UICR register was not erased. So, we can flash the device without erasing the whole flash including the UICR only if  CONFIG_DEBUG_PORT_ACCESS=y.

    Kind regards
    Mohamed
  • Hi Mohamed,

    This is a special case. Reading the output from nrfjprog you see that readback protection is enabled (APPROTECT). And the only way to disable it is to perform a full chip erase (nrfjprog --recover). Clearly you want to avoid this issue in the future, as you want to be able to program/debug several times after the initial programming:

    • If you are using older revisions, simply do not enable APPROTECT. As long as it is never enabled, you will not have this problem.
    • If you are using the newest revision ICs, you need to recover first with for instance nrfjprog: nrfjprog --recover. This will disable APPROTECT in the UICR and add a small code snippet that unlocks the debug port so that it can be used in the future. However, when you flash your firmware this temporary firmware is deleted, and you must ensure that your firmware does this. For that you must use a MDK version >= 8.40.2, which for instance is included in nRF5 SDK 17.1.0. See IN-142 for more details.
  • Good Morning Thorsrud,
    Thank you for the tips.
    I must admit I get confused with all these different tools versions.
    I know I am using,
    Zephyr  OS build v2.6.99-ncs1
    nRF Connect SDK v1.7.0
    But I am not sure which MDK version I am using. How do I find out?
    See IN-142 for more details
    This document refers to nRF52832 but I am using nrf52833. 
    Does it also apply to nRF52833?
    Kind regards
    Mohamed

  • Hi,

    nRF Connect SDK 1.7.0 OK (that is the oldest nRF Connect SDK with support for the latest revision the nRF52833). nRF Connect SDK 1.7.0 use nrfx 2.5.0 which include MDK 8.40.2. Finding it is a bit tedious, but the easiest is to check the README for nrfx which you find under modules/hal/nordic/nrfx/README, and which tells you which version you are using. Then check the CHANGELOG.md in the same folder, which states which MDK version is used.

    There are separate documents for each device, but the content is virtually the same. For nRF52833 it is IN-149.

  • Reply
    • Hi,

      nRF Connect SDK 1.7.0 OK (that is the oldest nRF Connect SDK with support for the latest revision the nRF52833). nRF Connect SDK 1.7.0 use nrfx 2.5.0 which include MDK 8.40.2. Finding it is a bit tedious, but the easiest is to check the README for nrfx which you find under modules/hal/nordic/nrfx/README, and which tells you which version you are using. Then check the CHANGELOG.md in the same folder, which states which MDK version is used.

      There are separate documents for each device, but the content is virtually the same. For nRF52833 it is IN-149.

    Children
    • Thank you Thorsrud.

      It is all clear now.

      If you are using the newest revision ICs, you need to recover first with for instance nrfjprog: nrfjprog --recover. This will disable APPROTECT in the UICR and add a small

      So, for the newest revision ICs, I must perform the firmware flash operation and setting the device id in three  the steps. Step 1 will erase all user flash memory and disables the readback protection mechanism if enabled. Step 2 will write the device id in the UICR customer[0] location. Finally, step 3 will flash the firmware without erasing the UICR. The firmware will then re-enable the readback protection mechanism at boot-up.

      Step 1: Disable APPROTECT:  nrfjprog --recover 

      Step 2: Flash device id:            nrfjprog --memwr 0x10001080 --val <device id>

      Step 3: Flash firmware:             nrfjprog --program merged.hex –-sectorerase --reset

      Am I right?

      Kind regards
      Mohamed
    • Yes, that looks correct (note that if you want to debug/program after step 3, it is a requirement that the firmware continues to enable debugger access. That is the default behavior with the SDK though, so it should be good).

      I forgot about this post before, but you can read a bit more in Working with the nRF52 Series' improved APPROTECT if you want more details.

    • Thank you for sharing the link.

      note that if you want to debug/program after step 3, it is a requirement that the firmware continues to enable debugger access. That is the default behavior with the SDK though, so it should be good).

      Understood. The three steps mentioned above are for a production environment. We do all development and debugging in Segger Embedded Studio. 

      Kind regards
      Mohamed
    • Hi Thorsrud,

      I have installed nrfjprog v10:15 on another machine running Windows 10 64-bits and I am running into this problem,

      C:\>nrfjprog -v
      ERROR: JLinkARM DLL is invalid. Please reinstall latest JLinkARM DLL.
      NOTE: For additional output, try running again with logging enabled (--log).
      NOTE: Any generated log error messages will be displayed.

      C:\>nrfjprog -v --log
      WARNING: Logging is unavailable. nrfjprog.exe does not have write
      WARNING: permission for the log file
      ERROR: JLinkARM DLL is invalid. Please reinstall latest JLinkARM DLL.
      NOTE: For additional output, try running again with logging enabled (--log).
      NOTE: Any generated log error messages will be displayed.

      He has installed it twice but he is still facing the same problem.

      Thank you for your help.

      Kind regards
      Mohamed
    • Hi,

      I am not immediately able to explain that. Please open a new question/thread for this as it is not directly related to the original topic in this thread.

    Related