This builds on the example Simple BLE and adds support for reading configuration data out of the User Information Configuration Registers. Download the example which contains a readme describing each file in the package.

User Information Configuration Registers

The User Information Configuration Registers (UICR) is an area of flash separate from where the application code is stored within which various configuration data can be stored. In the previous example Simple BLE, the ID of the device (NSD123) was hardcoded into the application code. This is OK for a one off device but if there are multiple devices all using the same application code then it is not really satisfactory to have to recompile the code before flashing each device. Using the UICR registers gets away from this.

On the nRF5 devices that these examples have been built for, the UICR registers start at address 0x10001000. The first 128 bytes are reserved for Nordic (so not really customer registers). The area we can use is 128 bytes long and starts at address 0x10001080.

Flashing Configuration data to the UICR

The RPi SWD Programmer used throughout these examples is capable of reading JSON formatted configuration data files and flashing them to the UICR. This example contains the configuration file UICR.json which contains the following configuration data.


Each item in the configuration file has an address and a typed value to store at that address. In this example there is:

  • A string “QQQ123” at address 0x10001080.
  • A 16 bit unsigned integer (u16) with a value of 200 at address 0x10001088.
  • A 16 bit unsigned integer (u16) with a value of 0x1F4 (500 decimal) at address 0x1000108A

This can be flashed to the microcontroller using the command:

C:\Projects\BLEUICR> "C:\Program Files\NoSMD\SWorD\bin\SWorDProgrammer.exe" -program:UICR.json -probe:rpi4programmer -pagesize:4096

Accessing the UICR from Application Code

It is straightforward to access the UICR data in the application code. Define a structure that matches how the configutation data is stored in flash and then simply memcpy it into the structure.

Numerical data is big endian.

//  Define a structure to hold the configuration items
//  Use pragma pack so the organisation of the structure exactly matches
//  how the data is held in flash

#pragma pack(push,1)
typedef struct
	char m_SerialNumber[SERIAL_NUMBER_FIELD_LEN];
	uint16_t m_LEDOnTimeMS;
	uint16_t m_LEDOffTimeMS;	
} UICRData;
#pragma pack(pop)
bool IsBigEndian();

#define BigEndianToNative32(val) (IsBigEndian() ? val : __REV(val))
#define BigEndianToNative16(val) (IsBigEndian() ? val : __REV16(val))

//  Determines the endianness of the CPU
bool IsBigEndian()
	static bool haveDeterminedEndian = false;
	static bool isBigEndian = false;
        union { uint8_t c[4]; uint32_t i; } data;
        data.i = 0x12345678;
        isBigEndian = (data.c[0] == 0x78) ? false : true;
        haveDeterminedEndian = true;
    return isBigEndian;

// Function to load the config data from the UICR
void LoadUICR(UICRData* pAppConfig)
    const uint32_t UICRBaseAddress = 0x10001000;
    const uint32_t UICRCustomerBase = (UICRBaseAddress + 0x80);
    memcpy(pAppConfig,(uint8_t*)UICRCustomerBase, sizeof(AppConfig));
    pAppConfig->m_SerialNumber[SERIAL_NUMBER_LEN] = '\0';
    pAppConfig->m_LEDOnTimeMS = BigEndianToNative16(pAppConfig->m_LEDOnTimeMS);
    pAppConfig->m_LEDOffTimeMS = BigEndianToNative16(pAppConfig->m_LEDOffTimeMS);

Building and Flashing the Program

Any toolchain/programmer can be used for these steps. All the examples here are built using make and gcc. The binary is flashed using the Raspberry Pi networked programmer. See here for how to set up make, gcc and the Raspberry Pi networked programmer.


From the terminal type:

C:\Projects\BLEUICR> "c:\Program Files (x86)\GnuWin32\bin\make.exe" -f makefile CONFIG=Debug all

If there are no errors then the binary bleuicr.elf should be output to the sub-folder bin\debug

Flashing the Binary to the Microcontroller

Hooking up the Programmer to the Microcontroller

See here for how to connect the programmer to the microcontroller.


From a terminal type to flash both the softdevice (bluetooth stack), the application code and the config to the microcontroller:

C:\Projects\BLEUICR> "C:\Program Files\NoSMD\SWorD\bin\SWorDProgrammer.exe" -program:C:\SDK\NordicSDK\nRF5_SDK_17.0.0_9d13099\components\softdevice\s132\hex\s132_nrf52_7.0.1_softdevice.hex,bin\debug\bleuicr.elf,UICR.json -probe:rpi4programmer -pagesize:4096

Attempting to connect to rpi4programmer on

Connected to rpi4programmer on

Progress 100%
Completed with success



The easiest way to test is to just print out each of the configuration items over SWO.

Initialising saadc...
Loaded configuration from UICR
Device serial number: QQQ123
LED on period: 200
LED off period: 500
Initialise BLE

Change the configuration file UICR.json and only reflash it to see how the operation of the app changes without changing the application code. To just reflash the configuration data.

C:\Projects\BLEUICR> "C:\Program Files\NoSMD\SWorD\bin\SWorDProgrammer.exe" -program:UICR.json -probe:rpi4programmer -pagesize:4096

If you change the serial number field you may have to restart your mobile app in order to see the new name. In some circumstances, the mobile phones bluetooth stack caches the name and you also need to restart bluetooth on the phone to see the new name.


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: