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

What is the relationship between the BLE address and the various FICR registers?

I am working with SDK15.3.0 and a PCA10040 with S132. I have two questions relating to the BLE addresses as seen by the PCA10040 and by nRF Connect.

Q1 - What is the relationship between the BLE address and the various FICR registers?

I build the ble_app_template exmaple and add this code to print the BLE address, plus various register which I understand are related to the way the address is generated:

    ble_gap_addr_t boardAddress;
    sd_ble_gap_addr_get(&boardAddress);

    NRF_LOG_INFO("   Board address = %02x:%02x:%02x:%02x:%02x:%02x",
            boardAddress.addr[5], boardAddress.addr[4], boardAddress.addr[3],
            boardAddress.addr[2], boardAddress.addr[1], boardAddress.addr[0]);
    NRF_LOG_INFO("    addr_type=%d, addr_id_peer=%d", boardAddress.addr_type, boardAddress.addr_id_peer);
    NRF_LOG_INFO("   DEVICEADDRTYPE: %08X", NRF_FICR->DEVICEADDRTYPE);
    NRF_LOG_INFO("   DEVICEID0: %08X", NRF_FICR->DEVICEID[0]);
    NRF_LOG_INFO("   DEVICEID1: %08X", NRF_FICR->DEVICEID[1]);
    NRF_LOG_INFO("   DEVICEADDR: %08X", NRF_FICR->DEVICEADDR);

The output is as follows:

<info> app:    Board address = E2:2A:8F:50:F5:A3
<info> app:     addr_type=1, addr_id_peer=0
<info> app:    DEVICEADDRTYPE: FFFFFFFF
<info> app:    DEVICEID0: 4BC5E0FB
<info> app:    DEVICEID1: 75CAE81E
<info> app:    DEVICEADDR: 100000A4

nRF Connect sees the board advertising as E2:2A:8F:50:F5:A3, which is the same as the app itself sees. However, other posts suggest that the address is taken directly from the DEVICEID registers - but clearly this is not the case. (I get identical results with the ble_app_hrs as well). What is the relationship between the BLE address and the various FICR registers?

Q2 - why do I get different values for address, addr_type and addr_id_peer?

This is the more interesting question. I am working on a custom app - I think it had origins in this example: https://github.com/bjornspockeli/custom_ble_service_example

In this case the same code gives the same FICR values but different outputs:

After flashing the binary image:

<info> app:    Board address = 00:12:2F:00:00:00
<info> app:     addr_type=0, addr_id_peer=0

then after push-button resets:

<info> app:    Board address = 0D:CE:BC:90:9C:48
<info> app:     addr_type=70, addr_id_peer=1

When powering on after a lengthy period of being powered off:

<info> app:    Board address = 0F:CE:BC:90:9C:48
<info> app:     addr_type=6, addr_id_peer=1

Furthermore, nRF Connect reports the same value as before (E2:2A:8F:50:F5:A3) but this differs from what sd_ble_gap_addr_get() returns. And what about this addr_type 6 & 70, and id_peer? ble_gap.h says this about id_peer: "This bit is set by the SoftDevice to indicate whether the address has been resolved from a Resolvable Private Address (when the peer is using privacy). If set to 1, @ref addr and @ref addr_type refer to the identity address of the resolved address"

I cannot see anything in my code which causes this different behaviour. Where should I look? is sdk_config.h involved?

  • Hello,

    A1:

     

        NRF_LOG_INFO("   Board address = %02x:%02x:%02x:%02x:%02x:%02x",
                boardAddress.addr[5], boardAddress.addr[4], boardAddress.addr[3],
                boardAddress.addr[2], boardAddress.addr[1], boardAddress.addr[0]);
        NRF_LOG_INFO("    addr_type=%d, addr_id_peer=%d", boardAddress.addr_type, boardAddress.addr_id_peer);
        NRF_LOG_INFO("   DEVICEADDRTYPE: %08X", NRF_FICR->DEVICEADDRTYPE);
        NRF_LOG_INFO("   DEVICEID0: %08X", NRF_FICR->DEVICEID[0]);
        NRF_LOG_INFO("   DEVICEID1: %08X", NRF_FICR->DEVICEID[1]);
        NRF_LOG_INFO("   DEVICEADDR: %08X", NRF_FICR->DEVICEADDR);

    The output is as follows:

    <info> app:    Board address = E2:2A:8F:50:F5:A3
    <info> app:     addr_type=1, addr_id_peer=0
    <info> app:    DEVICEADDRTYPE: FFFFFFFF
    <info> app:    DEVICEID0: 4BC5E0FB
    <info> app:    DEVICEID1: 75CAE81E
    <info> app:    DEVICEADDR: 100000A4

     It is actually the DEVICEADDR that is the BLE address, not the DEVICEID. I see that you missed one thing when printing the DEVICEADDR. Like the DEVICEID registers the DEVICEADDR is two registers. Try to print:

    NRF_LOG_INFO("    DEVICEADDR0 %08x", NRF_FICR->DEVICEADDR[0]);
    NRF_LOG_INFO("    DEVICEADDR1 %08x", NRF_FICR->DEVICEADDR[1]);

    Right now it only prints the address where the DEVICEADDR register is located, 0x1000000A4, which you can see here. (baseaddress: 0x10000000, offset 0x0A4)

    It says in the description of DEVICEADDR (from the link):

    48 bit device address
    DEVICEADDR[0] contains the least significant bits of the device address. DEVICEADDR[1] contains the most significant bits of the device address. Only bits [15:0] of DEVICEADDR[1] are used.

    So only 2 bytes of DEVICEADDR are used. Also, the 2 MSBits of the BLE address has to be '11' according to the BLE spec. 

    You may notice (but it may not be the case on your device) that some bits of DEVICEADDR are "wrong" compared to the board address that you check with sd_ble_gap_addr_get(); This is because the some address bits are tied to the address type. So if your deviceaddr says 0x65, the address will be 0xE5, given that you use a random static address.

    A2:

    These values look semi-random. Do you fetch them the same way as you did in Q1? Where in the project do you do it? Before or after the softdevice is initialized? Does sd_ble_gap_addr_get() return 0? Try:

    ble_gap_addr_t boardAddress;
    ret_code_t err_code;
    err_code = sd_ble_gap_addr_get(&boardAddress);
    if (err_code == NRF_SUCCESS)
    {
        NRF_LOG_INFO("   Board address = %02x:%02x:%02x:%02x:%02x:%02x",
                boardAddress.addr[5], boardAddress.addr[4], boardAddress.addr[3],
                boardAddress.addr[2], boardAddress.addr[1], boardAddress.addr[0]);
        NRF_LOG_INFO("    addr_type=%d, addr_id_peer=%d", boardAddress.addr_type, boardAddress.addr_id_peer);
        NRF_LOG_INFO("   DEVICEADDRTYPE: %08X", NRF_FICR->DEVICEADDRTYPE);
        NRF_LOG_INFO("   DEVICEID0: %08X", NRF_FICR->DEVICEID[0]);
        NRF_LOG_INFO("   DEVICEID1: %08X", NRF_FICR->DEVICEID[1]);
        NRF_LOG_INFO("   DEVICEADDR: %08X", NRF_FICR->DEVICEADDR);
    }
    else
    {
        NRF_LOG_INFO("sd_ble_gap_addr_get() failed with err_code 0x%x", err_code);
    }

    What does it say?

    Best regards,

    Edvin

  • Hi Edvin

    First, thanks for pointing out my coding error (DEVICEADDR[0] etc). When I read NRF_FICR->DEVICEADDR[0] and NRF_FICR->DEVICEADDR[1] I now get this result, with the board address shown as originating from DEVICEADDR:

    <info> app:    Board address = E2:2A:8F:50:F5:A3
    <info> app:     addr_type=1, addr_id_peer=0
    <info> app:    DEVICEADDRTYPE: FFFFFFFF
    <info> app:    DEVICEID[0]: 4BC5E0FB
    <info> app:    DEVICEID[1]: 75CAE81E
    <info> app:    DEVICEADDR[0]: 8F50F5A3
    <info> app:    DEVICEADDR[1]: 7483622A

    In the case of my own app, you guessed correctly: I was calling sd_ble_gap_addr_get() too soon (error code was 02). When I move this call after the softdevice is initialised it works the same as above.

    My apologies for my simple errors and thank you for your quick response!

  • No worries. Happy to help Slight smile Maybe someone else who has the same questions in the future will find this post helpful, so no need to apologize.

    Best regards,

    Edvin

Related