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

Caching Device Information Service handle in client gives invalid read response

Hi,

Some background, I'm writing a test firmware for the NRF52840 DK that will be used in our production line. We're programming 10 devices simultaneously with the same FW (NRF52832) and after programming we're running a short diagnostics test on all 10 devices at the same time from the NRF52840 DK.

The production test looks like this

  • Find and connect to all devices within range
  • Read out Serial Number String from Device Information Service (DIS) from all devices using Nordic ble_dis_c
  • Start custom diagnostics check and wait for results from our custom service for all devices

To speed things up we want to only run Service Discovery on the first device that we detect so that subsequent 10, 100, 1000 etc devices can skip this.

But when debugging it's clear that this approach does not work. When reading DIS data from a device with cached discovery data I'm often getting a zero byte response read response without errors from a DIS attribute that I'm 100% positive that it is hard coded to a value. Disconnecting the device and connecting to it again gives the same value. Some devices however display the correct value even when using cached data. So it's a bit confusing.

Please see code below

static ble_dis_c_handle_t m_dis_handles[BLE_DIS_C_CHAR_TYPES_NUM];
// This is when/how cached data is used
case BLE_GAP_EVT_CONNECTED:
{

    if (m_dis_disc_completed)
    {
        NRF_LOG_DEBUG("Discovery completed. Use cached data.");
        err_code = ble_dis_c_handles_assign(&m_dis_c[p_gap_evt->conn_handle], p_gap_evt->conn_handle, m_dis_handles);
        APP_ERROR_CHECK(err_code);
        // Here I'm also reading some data from our custom service but removed for clarity
        // Caching of our custom serice is done in the same way  
        err_code = ble_dis_c_read(&m_dis_c[p_gap_evt->conn_handle], BLE_DIS_C_SERIAL_NUM);
        APP_ERROR_CHECK(err_code);
    }
    else
    {
        NRF_LOG_DEBUG("Starting discovery.");
        err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle], p_gap_evt->conn_handle);
    }
}
// Part of the discovery code
static void dis_c_evt_handler(ble_dis_c_t * p_ble_dis_c, ble_dis_c_evt_t const * p_evt)
{
    switch (p_evt->evt_type)
    {
        ...
        case BLE_DIS_C_EVT_DISCOVERY_COMPLETE:
            err_code = ble_dis_c_handles_assign(&m_dis_c[p_evt->conn_handle], p_evt->conn_handle, p_evt->params.disc_complete.handles);
            APP_ERROR_CHECK(err_code);
            memcpy(m_dis_handles, p_evt->params.disc_complete.handles, sizeof(m_dis_handles));
            m_dis_disc_completed = true;
            break;
        ...
    }
}

I would be very grateful if someone could help me out here.

Is there something going on at the SD/lower layers that requires a Discovery to be run and that caching is not possible? Or is this approach OK and there is some other error in my code?

Oh and running the Service Discovery for all devices then everything works as expected. Moving the queuing of DIS read operations code from the BLE_GAP_EVT_CONNECTED event to the main context did not matter.

Thanks for the help! 

Parents Reply Children
No Data
Related