Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

nRF52840 - Device Reboots when BLE connection is terminated

I'm using a nRF52840 configured as Central and Peripheral, with nRF5_SDK 17.1.0 (I'm Not using Zephyr) for reading the Device Name from the Generic Service of a beacon. 
I'm already able to connect to the beacon GAP, discover the characteristic I need and read the device name. Up to this point everything is fine.
But when my beacon terminates the connection or when I try to finish it by calling sd_ble_gap_disconnect(...), my nRF52840 reboots.

Since I'm not using a development kit (I'm using a final product that has the nRF52840 as microcontroller) the only way I can debug is via a serial port the product has. But although I've put a lot of "printf like" calls to try to track where the reset is comming from, I wasn't able to find it. My serial debug goes all fine until I call the sd_ble_gap_disconnect or until the beacon shuts off the connection.

Does anyone have an idea of what can be happening and how can I solve it?

#define BEACON_GAP_UUID         0xFEAA
#define APP_BLE_CONN_CFG_TAG    1                        
#define APP_BLE_OBSERVER_PRIO   3                                       

uint8_t BufferDataRead[30];
uint16_t myConnHandle;

BLE_DB_DISCOVERY_DEF(m_db_disc);           
NRF_BLE_GQ_DEF(m_ble_gatt_queue,                           
               NRF_SDH_BLE_CENTRAL_LINK_COUNT,
               NRF_BLE_GQ_QUEUE_SIZE);
NRF_BLE_SCAN_DEF(m_scan);  

//========== MAIN ==========
int main(void)
{
    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    ble_stack_init();
    gatt_init();
    beacon_db_discovery_init();
    beacon_scan_init();

    beacon_scan_start(); //starts scanning
    //... rest of the program's logic
    //...
}
//==========================
void gatt_init(void)
{
    ret_code_t err_code;

    err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_gatt_att_mtu_central_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
    APP_ERROR_CHECK(err_code);
}
static void ble_stack_init(void)
{
    ret_code_t err_code;

    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);

    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
    uint16_t att_handle;
    ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;

    if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE)
    {
        if (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_GAP &&
            p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_BLE)
        {
            for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
            {
                if (p_chars[i].characteristic.uuid.uuid == BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME)
                {
                    att_handle = p_chars[i].characteristic.handle_value;
                    sd_ble_gattc_read(p_evt->conn_handle, att_handle, 0);
                }
            }
        }
    }
}
void beacon_db_discovery_init(void)
{
    ble_db_discovery_init_t db_init;

    memset(&db_init, 0, sizeof(ble_db_discovery_init_t));

    db_init.evt_handler  = db_disc_handler;
    db_init.p_gatt_queue = &m_ble_gatt_queue;

    ret_code_t err_code = ble_db_discovery_init(&db_init);
    APP_ERROR_CHECK(err_code);
}
void beacon_scan_start(void)
{
    ret_code_t err_code;

    err_code = nrf_ble_scan_start(&m_scan);
    APP_ERROR_CHECK(err_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_CONNECTED:
            sd_ble_gap_scan_stop();
            break;
    }
}
void beacon_scan_init(void)
{
    ret_code_t          err_code;
    nrf_ble_scan_init_t init_scan;
    static ble_uuid_t beacon_uuid_generic;

    beacon_uuid_generic.type = BLE_UUID_TYPE_BLE;
    beacon_uuid_generic.uuid = BLE_UUID_GAP;

    ble_uuid_t beacon_uuid =
    {
        .type = BLE_UUID_TYPE_BLE,
        .uuid = BEACON_GAP_UUID,
    };

    memset(&init_scan, 0, sizeof(init_scan));

    init_scan.connect_if_match = true;
    init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;

    ble_db_discovery_evt_register(&beacon_uuid_generic);

    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_UUID_FILTER, &beacon_uuid);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_UUID_FILTER, false);
    APP_ERROR_CHECK(err_code);
}
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ret_code_t            err_code;
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch(p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
        {
            myConnHandle = p_ble_evt->evt.gattc_evt.conn_handle;
            err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
            APP_ERROR_CHECK(err_code);

            break;
        }
        case BLE_GATTC_EVT_READ_RSP:
        {
            uint8_t lengthDataRead = p_ble_evt->evt.gattc_evt.params.read_rsp.len;
            memcpy(BufferDataRead, p_ble_evt->evt.gattc_evt.params.read_rsp.data, lengthDataRead);
            //EVERYTHING GOES FINE UNTIL HERE
            //BUT WHEN I TRY DO DISCONNECT IT, uC REBOOTS
            sd_ble_gap_disconnect(myConnHandle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            break;
        }
        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
        {
            err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
            APP_ERROR_CHECK(err_code);
            break;
        }
        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
        {
            err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                                    &p_gap_evt->params.conn_param_update_request.conn_params);
            APP_ERROR_CHECK(err_code);
            break;
        }
        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
        {
            ble_gap_phys_t const phys =
            {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
            break;
        }
        case BLE_GATTC_EVT_TIMEOUT:
        {
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
        }
        case BLE_GATTS_EVT_TIMEOUT:
        {
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
        }
    }
}

Related