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

Best method for writing to UICR during production

Please note that I am a new developer.

I am currently testing on a nRF52 DK on Windows.

I want to flash my application (which has a SoftDevice) and also write manufacturing information such as serial number to the UICR (customer reserved) registers.

I have tried using the method described in the UICR Config Example where Keil uVision is modified to write to UICR. This method works, but is not desirable. I want to use a Flasher ATE (JLink flash programmer) to flash each of my devices during production.

I have seen in some threads that it is possible to write to the UICR using nrfjprog as such:

nrfjprog --memwr 0x10001304 --val 0x00000000

Is the best method to use nrfjprog and write to each individual UICR address and then to flash the application and SoftDevice? Or perhaps it is more efficient to produce a single .hex file (using mergehex) where UICR registers are already written.

My question is: what is the most efficient way to write to the UICR registers during production?

Thanks for any help!

Parents
  • Based on new knowledge I`ll try to answer my own question. I will keep this thread here as future reference.

    Writing to UICR via Flasher ATE (during manufacturing):

    When using Flasher ATE during product manufacturing, it is possible to use a command called "#AUTO PATCH". As described in the Flasher ATE User Guide. The Flasher ATE will be connected to a PC using either RS232 or telnet interface. It is then possible to issue commands using J-Link software.

    From the Flasher ATE User Guide: A file called "Patches.txt" can be placed on the ATE module. Each line in the Patches.txt file can hold up to four patches, each being maximum 32 bytes in length. The number in "Serial.txt" refer to which line number in Patches.txt which will be used for the current cycle. Each cycle can refer to a single device which currently is being programmed. Alternatively it is possible to do single patching (no cycling) if there is only one device. The single patch command looks like this:

    #AUTO <module> PATCH <NumPatches>,<Addr>,<NumBytes>:<Data>

    For example:

    #AUTO 0 PATCH 1,10001080,4:12345678

    Here 10001080 refer to the CUSTOMER[0] UICR register address. 4 is the number of bytes in the data, and 12345678 is the data (e.g. the serial number of the device).

    Edit:

    As stated by greenlava below, in order to write to UICR using the ATE Flasher, these memory addresses should be filled with empty dummy data in the .hex file. The ATE Flasher fails to write to addresses which exceeds addresses included in the .hex file. Therefor, the .hex file should be padded with dummy data.

  • Hi there:

        I'm trying to do exactly what you're referring to here, but I'm having trouble pulling it all together and verifying the contents of CUSTOMER[0] after I apply the AUTO PATCH.  I'm having trouble verifying the correct data  is written with a

    #READ <module> 10001080,4

    Did you end up having success with this?

  • Hi,

    I have not tried the '#AUTO PATCH' command myself since I don't have a Flasher ATE available, but I'll still try to help.
    I'm not able to find the '#READ' command in the Flasher ATE User Guide (UM08035).
    You could alternatively try to read the register by using nrfjprog:

    nrfjprog -f NRF52 --memrd 0x10001080 --n 4

    You likely know this already, but I'll write this here just for future reference:
    The UICR should only be written once, and tools such as nrfjprog will not allow you to write to the same flash memory location twice.
    If the UICR has to be re-written, you'll have to erase the flash on the device first.
    This can be done with nrfjprog as well:
    nrfjprog -f NRF52 --eraseall

    Also note that we use Little Endian.

    Example:

    For sake of demonstration, let's compare the nrfjprog method and #AUTO PATCH method.
    Lets say we want to write a decimal value 1337 (0x539) to UICR CUSTOMER[0] register at (register address 0x1001080).
    At the same time we also want to write decimal value 3735928559 (0xDEADBEEF) to UICR CUSTOMER[1] (register address 0x1001084).
    Then we have two patches.

    If we were to use nrfjprog, it would look like this:

    nrfjprog -f NRF52 --memwr 0x10001080 --val 0x00000539
    nrfjprog -f NRF52 --memwr 0x10001084 --val 0xDEADBEEF

    If we instead are using the Flasher ATE '#AUTO PATCH' method, the command would look like this:

    #AUTO PATCH 1 2,10001080,4:00000539,10001084,4:DEADBEEF

    Here 1 is the <module> with TCP port 41, 2 is the number of patches (<NumPatches>) and 4 is the number of bytes in each patch (<NumBytes>). We can write up to four patches at the same time.
    Remember to reset the device to ensure the UICR data has taken effect afterwards.
    I always program the application data before I program the UICR (I don't remember if this is a common rule).


    Hopefully some of this information was useful.
    If this did not do the trick, I'm sorry.
    But still, please let me know if you find out how to do this properly.

Reply
  • Hi,

    I have not tried the '#AUTO PATCH' command myself since I don't have a Flasher ATE available, but I'll still try to help.
    I'm not able to find the '#READ' command in the Flasher ATE User Guide (UM08035).
    You could alternatively try to read the register by using nrfjprog:

    nrfjprog -f NRF52 --memrd 0x10001080 --n 4

    You likely know this already, but I'll write this here just for future reference:
    The UICR should only be written once, and tools such as nrfjprog will not allow you to write to the same flash memory location twice.
    If the UICR has to be re-written, you'll have to erase the flash on the device first.
    This can be done with nrfjprog as well:
    nrfjprog -f NRF52 --eraseall

    Also note that we use Little Endian.

    Example:

    For sake of demonstration, let's compare the nrfjprog method and #AUTO PATCH method.
    Lets say we want to write a decimal value 1337 (0x539) to UICR CUSTOMER[0] register at (register address 0x1001080).
    At the same time we also want to write decimal value 3735928559 (0xDEADBEEF) to UICR CUSTOMER[1] (register address 0x1001084).
    Then we have two patches.

    If we were to use nrfjprog, it would look like this:

    nrfjprog -f NRF52 --memwr 0x10001080 --val 0x00000539
    nrfjprog -f NRF52 --memwr 0x10001084 --val 0xDEADBEEF

    If we instead are using the Flasher ATE '#AUTO PATCH' method, the command would look like this:

    #AUTO PATCH 1 2,10001080,4:00000539,10001084,4:DEADBEEF

    Here 1 is the <module> with TCP port 41, 2 is the number of patches (<NumPatches>) and 4 is the number of bytes in each patch (<NumBytes>). We can write up to four patches at the same time.
    Remember to reset the device to ensure the UICR data has taken effect afterwards.
    I always program the application data before I program the UICR (I don't remember if this is a common rule).


    Hopefully some of this information was useful.
    If this did not do the trick, I'm sorry.
    But still, please let me know if you find out how to do this properly.

Children
Related