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 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.

  • Good Morning Einar,
    We managed to solve the problem by just installing nRF Connect for Desktop on the new machine.
    Thank you for your support.
    Kind regards
    Mohamed
  • Hi Einar,

    Learner said:
    Can I use the same code snippet with other Soc version e.g. QDAAA0?

    If you refer to the code snippet to write to flash, then yes. Writing to flash (including the UICR) is the same for all revisions. (As mentioned deleting the UICR page is special though, as it can only be done with a full chip erase).

    I am finding that I cannot debug code on an older version QDAAA0. The code boots up and stops at the point where NRF_UICR->APPROTECT is checked, see code below.

    void system_SetDebugPortAccess(void)
    {
    #if (CONFIG_DEBUG_PORT_ACCESS)
    
        /* Prevent chip from locking itself in hardware (if not already set) */
        if (NRF_UICR->APPROTECT != UICR_APPROTECT_PALL_HwDisabled)
        {
            LOG_ERR("Device debug prevented on next POR (0x%08X), resetting to disable this.", NRF_UICR->APPROTECT);
            system_WriteDebugPortAccess(UICR_APPROTECT_PALL_HwDisabled);
        }
    
        /* Prevent chip from locking itself in software */
        NRF_APPROTECT->DISABLE = APPROTECT_DISABLE_DISABLE_SwDisable;
    
    #else
        /* Enforce HW protection (if not already set) */
        if (NRF_UICR->APPROTECT != UICR_APPROTECT_PALL_Enabled)
        {
            LOG_ERR("Device debug allowed on next POR (0x%08X), resetting to disable this.", NRF_UICR->APPROTECT);
            system_WriteDebugPortAccess(UICR_APPROTECT_PALL_Enabled);
        }
    
        /* Belts and braces, enforce SW protection */
        NRF_APPROTECT->FORCEPROTECT = APPROTECT_FORCEPROTECT_FORCEPROTECT_Force;
    
    #endif //CONFIG_DEBUG_PORT_ACCESS
    }
    

    This is what I see in Segger Embedded Studio (SES-Nordic Edition) Debug Terminal:

    *** Booting Zephyr OS build v2.6.99-ncs1 ***
    [00:00:00.025,848] <err> system: Device debug prevented on next POR (0xFFFFFFFF), resetting to disable this.

    So, basically NRF_UICR->APPROTECT != UICR_APPROTECT_PALL_HwDisabled

    I can debug the same code on a newer version of the chip QDAAB0.

    QDAAA0: content of APPROTECT: 10120000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE

    QDAAB0: content of APPROTECT: 1012000012000000120000005A000000FEFFFFFF65

    So, I wrote to APPROTECT of the QDAAA0 chip 0x0000005A  to disable the protection mechanism.

    C:\WINDOWS\system32>nrfjprog --recover
    Recovering device. This operation might take 30s.
    Erasing user code and UICR flash areas.

    C:\WINDOWS\system32>nrfjprog --memwr 0x10001208 --val 0x0000005A --verify
    Parsing parameters.
    Writing.
    Verified OK.

    I then read UICR back to check the value of APPROTECT

    C:\WINDOWS\system32>nrfjprog --readuicr hb-700078-3.ihex
    Storing data in 'hb-700078-3.ihex'.

    QDAAA0: new content of APPROTECT: 10120000FFFFFFFFFFFFFFFF5A000000FFFFFFFFEE

    But when I flash the firmware in SES and start a debug session I still cannot debug it. I get the same error, <err> system: Device debug prevented on next POR (0xFFFFFFFF), resetting to disable this.

    I then tried to read back UICR to check if APPROTECT is still disabled but the read command failed

    C:\WINDOWS\system32>nrfjprog --readuicr hb-700078-4.ihex
    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.

    Why?
    It looks as if the APPROTECT enable/disable does not work for older chip version such as QDFAAA0.
    Kind regards
    Mohamed

  • Hi Mohamed,

    The code in this snippet will not work for older revisions., which has a different APPROTECT mechanism. You need to handle the revisions separately, as is done in the MDK. Referring to nRF Connect SDK 1.9.1 you have modules/hal/nordic/nrfx/mdk/system_nrf52_approtect.h which handles APPROTECT. There you can see that the nrf52_configuration_249() is checked and this returns true for devices with the new APPROTECT mechanism and false for the older.

    As you want to disable APPROTECT, and older devices has APPROTECT disabled by default (, you can simply check which revision you have and avoid running any APPROTECT related code on the older devices.

    PS: To understand the difference between the old (Access port protection controlled by hardware) and new (Access port protection controlled by hardware and software) scheme, I suggest you refer to the Debug and trace chapter in the product specification.

Reply
  • Hi Mohamed,

    The code in this snippet will not work for older revisions., which has a different APPROTECT mechanism. You need to handle the revisions separately, as is done in the MDK. Referring to nRF Connect SDK 1.9.1 you have modules/hal/nordic/nrfx/mdk/system_nrf52_approtect.h which handles APPROTECT. There you can see that the nrf52_configuration_249() is checked and this returns true for devices with the new APPROTECT mechanism and false for the older.

    As you want to disable APPROTECT, and older devices has APPROTECT disabled by default (, you can simply check which revision you have and avoid running any APPROTECT related code on the older devices.

    PS: To understand the difference between the old (Access port protection controlled by hardware) and new (Access port protection controlled by hardware and software) scheme, I suggest you refer to the Debug and trace chapter in the product specification.

Children
No Data
Related