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

sd_softdevice_disable() causes application to crash/hang if device is paired

If the device is paired (but not bonded) using "Just Works", sd_softdevice_disable() causes the application to hang/crash (nothing happens until reset by watchdog timer).

I use dfu_app_handler.c from sdk 8.1.0, so sd_softdevice_disable() is called from bootloader_start() when going from application to bootloader/DFU.

If pairing is not performed (using the exact same application) before writing START_DFU Op Code to the DFU Control Point characteristic, everything works as expected.

It should be fairly easy to recreate the issue. I use the following security parameters:

#define SEC_PARAM_TIMEOUT                    10
#define SEC_PARAM_BOND                       0
#define SEC_PARAM_MITM                       0
#define SEC_PARAM_IO_CAPABILITIES            BLE_GAP_IO_CAPS_NONE
#define SEC_PARAM_OOB                        0
#define SEC_PARAM_MIN_KEY_SIZE               7
#define SEC_PARAM_MAX_KEY_SIZE               16

And for the services I want encrypted I use:

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM()

Any help would be greatly appreciated.

Parents
  • Yes, the following function is called to do this:

    static void reset_prepare(void)
    {
        uint32_t err_code;
    
        if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
        {
            // Disconnect from peer.
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
        }
        else
        {
            // If not connected, the device will be advertising. Hence stop the advertising.
            advertising_stop();
        }
    
        err_code = ble_conn_params_stop();
        APP_ERROR_CHECK(err_code);
    
        nrf_delay_ms(500);
    }
    /** @snippet [DFU BLE Reset prepare] */
    #endif // BLE_DFU_APP_SUPPORT
    

    In context, this is what happens before sd_softdevice_disable() is called (when DFU is triggered):

    uint32_t err_code;
    uint16_t sys_serv_attr_len = sizeof(m_peer_data.sys_serv_attr);
    
    err_code = sd_ble_gatts_sys_attr_get(conn_handle,
                                         m_peer_data.sys_serv_attr,
                                         &sys_serv_attr_len,
                                         BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
    if (err_code != NRF_SUCCESS)
    {
        // Any error at this stage means the system service attributes could not be fetched.
        // This means the service changed indication cannot be sent in DFU mode, but connection
        // is still possible to establish.
    }
    
    m_reset_prepare();
    
    err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);
    APP_ERROR_CHECK(err_code);
    
Reply
  • Yes, the following function is called to do this:

    static void reset_prepare(void)
    {
        uint32_t err_code;
    
        if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
        {
            // Disconnect from peer.
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
        }
        else
        {
            // If not connected, the device will be advertising. Hence stop the advertising.
            advertising_stop();
        }
    
        err_code = ble_conn_params_stop();
        APP_ERROR_CHECK(err_code);
    
        nrf_delay_ms(500);
    }
    /** @snippet [DFU BLE Reset prepare] */
    #endif // BLE_DFU_APP_SUPPORT
    

    In context, this is what happens before sd_softdevice_disable() is called (when DFU is triggered):

    uint32_t err_code;
    uint16_t sys_serv_attr_len = sizeof(m_peer_data.sys_serv_attr);
    
    err_code = sd_ble_gatts_sys_attr_get(conn_handle,
                                         m_peer_data.sys_serv_attr,
                                         &sys_serv_attr_len,
                                         BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
    if (err_code != NRF_SUCCESS)
    {
        // Any error at this stage means the system service attributes could not be fetched.
        // This means the service changed indication cannot be sent in DFU mode, but connection
        // is still possible to establish.
    }
    
    m_reset_prepare();
    
    err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);
    APP_ERROR_CHECK(err_code);
    
Children
No Data
Related