Error when loading whitelist on a central + peripheral when connected peripheral shutdowns

Hello,

I have a 52832 using SDK16.0.0, that acts as an advertising peripheral (anyone can connect to it), and as a central, connected with 1-1 bond to a peripheral (a 52811).

I have implemented this 1-1 bond using whitelist and peer_managers on both sides (central 52832 and peripheral 52811). This is based on HRS / HRS_C examples.

Everythings works fine when bonding and keeping connection.

Here is the scenario that doesn't work : when peripheral shutdowns. Then the central starts scanning again, a whitelist request is received, but when loading whitelist I get a 12804 error (BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE) on pm_device_identities_list_set.

If I restart the central with the peripheral still down, I get the same error.
I I restart the central with the peripheral up and avertising, it successfully connects. 

Here are the logs of succcessful initial pairing :

00> <debug> ble_scan: Scanning parameters have been changed successfully
00> <info> app: Whitelist request
00> <debug> ble_scan: Scanning parameters have been changed successfully
00> <debug> ble_scan: Scanning
00> <debug> ble_scan: Connecting
00> <debug> ble_scan: Connection status: 0
00> <info> app: Scan filter match.
00> <info> app: Central connected to Scale (mac address E3:30:0F:54:9A:DC)
00> <info> app: Attempt to find scale peripheral on conn_handle 0x0
00> <debug> nrf_ble_gq: Registering connection handle: 0x0000
00> <debug> ble_db_disc: Starting discovery of service with UUID 0x1 on connection handle 0x0.
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Primary Services Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (2) succeeded on connection handle: 0.
00> <debug> ble_db_disc: Found service UUID 0x1.
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Discovery Request
00> <debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Characteristic Descriptor Request
00> <debug> nrf_ble_gq: SD GATT procedure (4) succeeded on connection handle: 0.
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> ble_db_disc: Discovery of service with UUID 0x1 completed with success on connection handle 0x0.
00> <debug> app: Scale service discovered.
00> <info> app: Assigning scale ble handles
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_PARAMS_REQ
00> <debug> peer_manager_handler: Security parameter request
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_START
00> <debug> peer_manager_handler: Connection security procedure started: role: Central, conn_handle: 0, procedure: Bonding
00> <debug> nrf_ble_gq: Adding item to the request queue
00> <debug> nrf_ble_gq: GATTC Write Request
00> <debug> nrf_ble_gq: SD GATT procedure (1) succeeded on connection handle: 0.
00> <debug> app: Scale service notifications enabled
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_PARAMS_REQ
00> <debug> peer_manager_handler: Security parameter request
00> <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_SUCCEEDED
00> <info> peer_manager_handler: Connection secured: role: Central, conn_handle: 0, procedure: Bonding
00> <info> app: Bonding with previous scale succeded
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
00> <debug> app: Received data from BLE BOKS
00> <debug> app:  52                     |R       
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> nrf_ble_gq: Processing the request queue...
00> <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Central address resolution, action: Update

Here are the logs after shuting down the connected peripheral :

00> <debug> ble_scan: Scanning parameters have been changed successfully
00> <info> app: Whitelist request
00> <error> app: ERROR 12804 [Unknown error code] at ble_scale.c:280
00> PC at: 0x00037529
00> <error> app: End of error report


Here is the relevant code:

static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
    ret_code_t err_code;
    switch(p_scan_evt->scan_evt_id)
    {
        case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
        {
            NRF_LOG_INFO("Whitelist request");
            on_whitelist_req();
        } break;

        (....)
    }
}

static void on_whitelist_req(void)
{
    // Whitelist buffers.
    ble_gap_addr_t whitelist_addrs[8];
    ble_gap_irk_t  whitelist_irks[8];

    memset(whitelist_addrs, 0x00, sizeof(whitelist_addrs));
    memset(whitelist_irks,  0x00, sizeof(whitelist_irks));

    uint32_t addr_cnt = (sizeof(whitelist_addrs) / sizeof(ble_gap_addr_t));
    uint32_t irk_cnt  = (sizeof(whitelist_irks)  / sizeof(ble_gap_irk_t));

    // Reload the whitelist and whitelist all peers.
    whitelist_load();

    ret_code_t ret;

    // Get the whitelist previously set with pm_whitelist_set().
    ret = pm_whitelist_get(whitelist_addrs, &addr_cnt,
                           whitelist_irks,  &irk_cnt);

    if (((addr_cnt == 0) && (irk_cnt == 0)))
    {
        m_scan_param.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL;

        ret = nrf_ble_scan_params_set(&m_scan, &m_scan_param);
        APP_ERROR_CHECK(ret);
    }
}

static void whitelist_load()
{
    ret_code_t   ret;
    pm_peer_id_t peers[8];
    uint32_t     peer_cnt;

    memset(peers, PM_PEER_ID_INVALID, sizeof(peers));
    peer_cnt = (sizeof(peers) / sizeof(pm_peer_id_t));

    // Load all peers from the flash and whitelist them.
    peer_list_get(peers, &peer_cnt);

    ret = pm_whitelist_set(peers, peer_cnt);
    APP_ERROR_CHECK(ret);

    // Setup the list of device identities.
    // Some SoftDevices do not support this feature.
    ret = pm_device_identities_list_set(peers, peer_cnt);
    if (ret != NRF_ERROR_NOT_SUPPORTED)
    {
        APP_ERROR_CHECK(ret);
    }
}

I do not reproduce with HRS / HRS_C examples.

Thanks !

Parents
  • Hi Quentin, 

    Could you post your full code in your main.c ? 
    The error you received could be related to that whitelist_load () (which calls pm_device_identities_list_set() ) has been called more than once with the same list. 

    I noticed that in  your log you have "Scanning parameters have been changed successfully" could you check how you get this log ? Usually it's the call nrf_ble_scan_params_set() that should not be called when whitelist is used. (at least in the hrs_c it's not called if there is something in the whitelist)

  • I have also taken inspiration in example rscs_c, where you can find :

    m_scan_param.filter_policy = BLE_GAP_SCAN_FP_WHITELIST;
    err_code = nrf_ble_scan_params_set(&m_scan, &m_scan_param);



    Here is additional code from my project :

    /**< Scan parameters requested for scanning and connection. */
    static ble_gap_scan_params_t m_scan_param =
    {
        .active        = 0x01,
        .interval      = NRF_BLE_SCAN_SCAN_INTERVAL,
        .window        = NRF_BLE_SCAN_SCAN_WINDOW,
        .filter_policy  = BLE_GAP_SCAN_FP_WHITELIST,
        .timeout       = SCAN_DURATION,
        .scan_phys     = BLE_GAP_PHY_1MBPS
        //.extended      = 1 // should it be set ? 
    };
    
    static void scan_start(void)
    {
        ret_code_t err_code;
    
        // If there is any pending write to flash, defer scanning until it completes.
        if (nrf_fstorage_is_busy(NULL))
        {
            m_memory_access_in_progress = true;
            return;
        }
    
        scale_scan_blink_start();
    
        m_scan_param.filter_policy = BLE_GAP_SCAN_FP_WHITELIST;
    
        err_code = nrf_ble_scan_params_set(&m_scan, &m_scan_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_scan_start(&m_scan);
        APP_ERROR_CHECK(err_code);
    }

  • Hi again Quentin, 

    - You can switch between. 

    - "extended" mode is only for extended advertising (Bluetooth 5.0 feature where you can advertise longer, or advertise only the header and the content will be transmitted in data channel. If you don't use extended advertising, you don't need to turn this on)

    - I did a quick search and found some cases:

    https://devzone.nordicsemi.com/f/nordic-q-a/32674/simultaneous-central-peripheral-with-whitelist-only-used-in-one-role


    https://devzone.nordicsemi.com/f/nordic-q-a/46268/error-12804-multipheripheral-bonding-whitelist/182613#182613

    So if you already doing advertising (or scanning) you would need to stop that before you start scanning (or advertising). Here a quote from my answer in the other case: 

    Sorry for the late response. I got the information from our staff. Quoted here: 

    You can not call sd_ble_gap_device_identities_set if the scanner is running. Even though you set use_whitelist=0 when stating the scanner, it will still use the identity list to resolve addresses.

     

    It seems that you would need to do the trick to start advertising first before you start scanning. Or stop scanning, start advertising and start scanning again. In my opinion,  scanning with whitelist = 0 shouldn't use identity list. 

  • I had already read these issues and tried some of those solutions (like stopping advertising before on_whitelist_request), without success.
    Besides, if I'm not wrong, hrs_c calls sd_ble_gap_device_identities_set without stopping advertising nor scanning.

    This is not clear to me what is the expected behaviour of the framework. Could you get some more definitive answers on what is working and what is not ?

    Why is the advertising in conflict with this whitelist at all ?

    So if you already doing advertising (or scanning) you would need to stop that before you start scanning (or advertising)
    Sorry, this is really not clear

    start advertising first before you start scanning
    This is not the case when I restart both peripheral and central, and it works fine. And it's not the case of HRS_C

    Or stop scanning, start advertising and start scanning again
    You mean stop advertising, then stop scanning, then start advertising, then start scanning again ?
    It looks very complicated 

  • Hi Quentin, 

    The key difference between the hrs_c and your application is that you do advertising and scanning at the same time. 
    When advertising there can be a whitelist used and when scanning whitelisting can also be used for scanning. 
    Only one whitelist can be used in the hardware, we don't have 2 different whitelist system for advertising and scanning.

    It could be the reason why you receive BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE when you start scanning ,it's because your advertising may already use a whitelist (?). You can find in both of the cases that I pointed to , the application does advertising + scanning at the same time. 

    It's hard for us to give you definite answer without knowing your application. We don't get a full picture from your code snippets.  My suggestion is to test scanning with whitelist without advertising just to check if you see the same error. 

    A good way to narrow down the issue is to get your application as close as possible to a working example. You then can trace back on which feature that you disable may cause the issue. 

  • My suggestion is to test scanning with whitelist without advertising just to check if you see the same error. 
    I did try, by calling :

    case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
        {
            NRF_LOG_INFO("Whitelist request");
            sd_ble_gap_adv_stop(m_advertising.adv_handle);
            on_whitelist_req();
            ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
        } break;

    Same error.


  • Well, I retried, and in fact it's not the same error.

    The first time NRF_BLE_SCAN_EVT_WHITELIST_REQUEST is called, ble_advertising_start throws with NRF_ERROR_CONN_COUNT, as if it didn't succeed stopping advertising (even though sd_ble_gap_adv_stop did not throw, checked by APP_ERROR_CHECK).

    If I ignore errors on ble_advertising_start (like the avove snippet) everythong works fine ! When the peripheral shutdowns, central starts scanning with whitelist, and advertises correctly.

    Do you know why I get the NRF_ERROR_CONN_COUNT the first time ?

Reply
  • Well, I retried, and in fact it's not the same error.

    The first time NRF_BLE_SCAN_EVT_WHITELIST_REQUEST is called, ble_advertising_start throws with NRF_ERROR_CONN_COUNT, as if it didn't succeed stopping advertising (even though sd_ble_gap_adv_stop did not throw, checked by APP_ERROR_CHECK).

    If I ignore errors on ble_advertising_start (like the avove snippet) everythong works fine ! When the peripheral shutdowns, central starts scanning with whitelist, and advertises correctly.

    Do you know why I get the NRF_ERROR_CONN_COUNT the first time ?

Children
  • Hi Quentin, 
    You have NRF_ERROR_CONN_COUNT  when you haven't setup the correct link count in sdk_config.h. 

    You have a potential of having up to 2 connections  (one as a peripheral and one as a central). So you need to configure that in sdk_config.h. Please check the following configuration: 

    - NRF_SDH_BLE_PERIPHERAL_LINK_COUNT

    - NRF_SDH_BLE_CENTRAL_LINK_COUNT

    - NRF_SDH_BLE_TOTAL_LINK_COUNT (this is the max concurrent connections)

  • My config is very simple :
    #define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1
    #define NRF_SDH_BLE_CENTRAL_LINK_COUNT 1
    #define NRF_SDH_BLE_TOTAL_LINK_COUNT 2

    So here the error would occur if I'm trying to advertise two times ? But that is not the case, as I'm stopping advertising as you can see.

  • Hei Quentin, 
    Is there any chance that the device is already in a connection as a peripheral when you starts advertising again  ?
     You mentioned that if you ignore the error when calling ble_advertising_start () it works fine, but would it advertise ? Or you need to call ble_advertising_start () again to make it work ? 

  • Is there any chance that the device is already in a connection as a peripheral when you starts advertising again  ?
    No

    You mentioned that if you ignore the error when calling ble_advertising_start () it works fine, but would it advertise ? Or you need to call ble_advertising_start () again to make it work ? 

    As I mentionned, I only get the error the first time, before bonding the peripheral. I do not need to advertise again, it advertises correctly (exactly as if the advertising stopping did not work).


  • Hi Quentin, 

    It's quite strange that even with NRF_ERROR_CONN_COUNT  error the advertising still resume. Please try to debug and check if you only call sd_ble_gap_adv_stop() without calling ble_advertising_start() do you see the advertising stopped. 
    And then check again with ble_advertising_start(). I don't think the softdevice would do advertising if sd_ble_gap_adv_start() return NRF_ERROR_CONN_COUNT.
    Again, if possible please provide us the code so we can test here. 

Related