Following up the post (Description of UICR on NRF52 series) https://jimmywongbluetooth.wordpress.com/2019/08/19/manufacturer-storage-data-on-uicr-region/, I would like to describe how to use the UICR to store the custom BLE address, Device Name and Device ID in this blog.

For example, as below table, there are list of the devices to have such configuration.

Device Number # Device ID (8 bytes)
0x10001080 – 0x10001087
NRF_UICR->CUSTOMER[0]
NRF_UICR->CUSTOMER[1]
Address (6 bytes)
0x10001088 – 0x1000108F
NRF_UICR->CUSTOMER[2]
NRF_UICR->CUSTOMER[3]
Device Name (11 bytes)
0x10001090 – 0x1000109B
NRF_UICR->CUSTOMER[4]
NRF_UICR->CUSTOMER[5]
NRF_UICR->CUSTOMER[6]
1 FC000000 00000001 FF00 00000001 DEVICE_00001
2 FC000000 00000002 FF00 00000002 DEVICE_00002
3 FC000000 00000003 FF00 00000003 DEVICE_00003
Device Name “DEVICE_00001”

@REM Erase the UICR region

nrfjprog –family NRF52 –eraseuicr

@REM DEVICE ID

nrfjprog –family NRF52 –memwr 0x10001080 –val 0x00000001

nrfjprog –family NRF52 –memwr 0x10001084 –val 0xFC000000

@REM DEVICE MAC ADDRESS

nrfjprog –family NRF52 –memwr 0x10001088 –val 0x00000001

nrfjprog –family NRF52 –memwr 0x1000108C –val 0x0000FF00

@REM DEVICE NAME

nrfjprog –family NRF52 –memwr 0x10001090 –val 0x30303031

nrfjprog –family NRF52 –memwr 0x10001094 –val 0x43455630

nrfjprog –family NRF52 –memwr 0x10001098 –val 0x44454549

#define MAX_LEN_DEVICE_ID       8
#define MAX_LEN_DEVICE_NAME     12

static void load_device_setting(void)
{
        ret_code_t ret_code;

        // Check if not written
        uint8_t empty_addr[MAX_LEN_DEVICE_NAME];
        memset(empty_addr, 0xff, MAX_LEN_DEVICE_NAME);

        ble_gap_addr_t gap_addr;
        gap_addr.addr_id_peer = 0;
        gap_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;

        /* Read the Device ID (8 bytes) from UICR Memory */
        uint8_t* ptr_device_id = (uint8_t*)&NRF_UICR->CUSTOMER[0];
        if(memcmp(ptr_device_id, empty_addr, MAX_LEN_DEVICE_ID))
        {
                memcpy(m_manufacturer_specific_target_device_id, ptr_device_id, MAX_LEN_DEVICE_ID);
                NRF_LOG_INFO("Device ID");
                NRF_LOG_HEXDUMP_INFO(m_manufacturer_specific_target_device_id, MAX_LEN_DEVICE_ID);
        }

        /* Read the Bluetooth Address from UICR Memory */
        // Get BD address from UICR memory
        uint8_t* ptr = (uint8_t*)&NRF_UICR->CUSTOMER[2];
        if(!memcmp(ptr, empty_addr, BLE_GAP_ADDR_LEN))
        {
                NRF_LOG_WARNING("No BD address in flash, using chip default");
                ret_code = sd_ble_gap_addr_get(&gap_addr);
                APP_ERROR_CHECK(ret_code);
                NRF_LOG_HEXDUMP_INFO(&gap_addr.addr, 6);
        }
        else
        {
                memcpy(&gap_addr.addr, ptr, BLE_GAP_ADDR_LEN);
                NRF_LOG_INFO("GAP Address");
                NRF_LOG_HEXDUMP_INFO(&gap_addr.addr, 6);
        }

        /* Read the Device Name 12 bytes) from UICR Memory */
        uint8_t* ptr_device_name = (uint8_t*)&NRF_UICR->CUSTOMER[4];
        if(memcmp(ptr_device_name, empty_addr, MAX_LEN_DEVICE_NAME))
        {
                memcpy(m_device_name, ptr_device_name, MAX_LEN_DEVICE_NAME);
                NRF_LOG_INFO("Device Name");
                NRF_LOG_HEXDUMP_INFO(m_device_name, MAX_LEN_DEVICE_NAME);
        }

        NRF_LOG_INFO("Setting bd address to: %02X:%02X:%02X:%02X:%02X:%02X",
                     gap_addr.addr[5],
                     gap_addr.addr[4],
                     gap_addr.addr[3],
                     gap_addr.addr[2],
                     gap_addr.addr[1],
                     gap_addr.addr[0]);

        ret_code = sd_ble_gap_addr_set(&gap_addr);
        APP_ERROR_CHECK(ret_code);
}