This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Softdevice couldn't initiate connection successfully

Hi,

I am developing a product based on nrf52840 soc as a central Bluetooth device. I want to connect to a Bluetooth device (as a slave) while it is advertising, but unfortunately, the process fails as the salve doesn't respond to the exchange MTU request. however, this salve device works fine with the windows Bluetooth framework.

I've attached the sniffre log while the slave connects to nrf52840 and windows bluetooth framework.

in nrf52840_trace, in packet 8118 you can see that the connection fails as the slave device doesn't respond to our request.

in windows_trace, in packet, 11838 you can see that the connection is established and works fine.

now my question is, is there any difference in the nrf52840 connection procedure with windows that can cause this problem?

as you can see, windows try to send LL_FEATRUE_REQUEST in the first step (in packet 11839) while softdevice doesn't send this request. can this cause the problem? if yes how can I manage to configure softdevice to send LL_FEATURE_REQUEST with specific parameters at first of the connection before exchanging the MTU?

I would really appreciate any hint or advice.
thanks

3821.windows_trace.pcapng

5305.nrf52840_trace.pcapng

Parents
  • Hello,

    So the central device in your nrf52840_trace.pcapng is the device you are working on, correct?

    If so, how do did you call the MTU update on this device? Perhaps you can show some code snippets? I guess if you want this to be persistent across all devices, you can initiate it from the peripheral, if you are developing that one as well. If not, I suggest you look into having this in the connected event. If this is what you are doing already, perhaps you need to add a delay. I see from the sniffer trace that the central is asking for an MTU update immediately after the connection request, which seems a bit off. The peripheral didn't event respond to the connection request yet. Did you call it from the BLE_GAP_EVT_CONNECTED event?

    Best regards,

    Edvin

Reply
  • Hello,

    So the central device in your nrf52840_trace.pcapng is the device you are working on, correct?

    If so, how do did you call the MTU update on this device? Perhaps you can show some code snippets? I guess if you want this to be persistent across all devices, you can initiate it from the peripheral, if you are developing that one as well. If not, I suggest you look into having this in the connected event. If this is what you are doing already, perhaps you need to add a delay. I see from the sniffer trace that the central is asking for an MTU update immediately after the connection request, which seems a bit off. The peripheral didn't event respond to the connection request yet. Did you call it from the BLE_GAP_EVT_CONNECTED event?

    Best regards,

    Edvin

Children
  • Thanks for your attention,

    Yes, the central device is my nrf52850 and nrf52840_trace.pcapng is the sniffer trace when the connection hangs.
    I can't change the peripheral side as it is a ready product from authentrend company.

    Actually, I've just changed the NRF_SDH_BLE_GATT_MAX_MTU_SIZE to the 517 in the sdk_config.h and in the nrf_ble_gatt.c which is from the nordic SDK, in the on_connected_evt function, if the desired mtu was bigger than the effective mtu, calls the sd_ble_gattc_exchange_mtu_request function. in the attached file, in line 151 you can see this code snippet.

    is it safe to remove this from the nrf_ble_gatt.c and call it manually?

    /**
     * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    
    #include "sdk_common.h"
    #if NRF_MODULE_ENABLED(NRF_BLE_GATT)
    
    #include "nrf_ble_gatt.h"
    
    #define NRF_LOG_MODULE_NAME nrf_ble_gatt
    #include "nrf_log.h"
    NRF_LOG_MODULE_REGISTER();
    
    #include "nrf_strerror.h"
    
    #define BLE_GAP_DATA_LENGTH_DEFAULT     27          //!< The stack's default data length.
    #define BLE_GAP_DATA_LENGTH_MAX         251         //!< Maximum data length.
    
    
    STATIC_ASSERT(NRF_SDH_BLE_GAP_DATA_LENGTH < 252);
    
    
    /**@brief Initialize a link's parameters to defaults. */
    static void link_init(nrf_ble_gatt_link_t * p_link)
    {
        p_link->att_mtu_desired            = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
        p_link->att_mtu_effective          = BLE_GATT_ATT_MTU_DEFAULT;
        p_link->att_mtu_exchange_pending   = false;
        p_link->att_mtu_exchange_requested = false;
    #if !defined (S112) && !defined(S312)
        p_link->data_length_desired        = NRF_SDH_BLE_GAP_DATA_LENGTH;
        p_link->data_length_effective      = BLE_GAP_DATA_LENGTH_DEFAULT;
    #endif // !defined (S112) && !defined(S312)
    }
    
    /**@brief   Start a data length update request procedure on a given connection. */
    #if !defined (S112) && !defined(S312)
    static ret_code_t data_length_update(uint16_t conn_handle, uint16_t data_length)
    {
        NRF_LOG_DEBUG("Updating data length to %u on connection 0x%x.",
                      data_length, conn_handle);
    
        ble_gap_data_length_params_t const dlp =
        {
            .max_rx_octets  = data_length,
            .max_tx_octets  = data_length,
            .max_rx_time_us = BLE_GAP_DATA_LENGTH_AUTO,
            .max_tx_time_us = BLE_GAP_DATA_LENGTH_AUTO,
        };
    
        ble_gap_data_length_limitation_t dll = {0};
    
        ret_code_t err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, &dll);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("sd_ble_gap_data_length_update() (request) on connection 0x%x returned %s.",
                          conn_handle, nrf_strerror_get(err_code));
    
            if (   (dll.tx_payload_limited_octets != 0)
                || (dll.rx_payload_limited_octets != 0))
            {
                NRF_LOG_ERROR("The requested TX/RX packet length is too long by %u/%u octets.",
                              dll.tx_payload_limited_octets, dll.rx_payload_limited_octets);
            }
    
            if (dll.tx_rx_time_limited_us != 0)
            {
                NRF_LOG_ERROR("The requested combination of TX and RX packet lengths "
                              "is too long by %u microseconds.",
                              dll.tx_rx_time_limited_us);
            }
        }
    
        return err_code;
    }
    #endif // !defined (S112) && !defined(S312)
    
    
    /**@brief Handle a connected event.
     *
     * Begins an ATT MTU exchange procedure, followed by a data length update request as necessary.
     *
     * @param[in]   p_gatt      GATT structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_connected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt)
    {
        ret_code_t            err_code;
        uint16_t              conn_handle = p_ble_evt->evt.common_evt.conn_handle;
        nrf_ble_gatt_link_t * p_link      = &p_gatt->links[conn_handle];
    
        // Update the link desired settings to reflect the current global settings.
    #if !defined (S112) && !defined(S312)
        p_link->data_length_desired = p_gatt->data_length;
    #endif // !defined (S112) && !defined(S312)
    
        switch (p_ble_evt->evt.gap_evt.params.connected.role)
        {
            case BLE_GAP_ROLE_PERIPH:
                p_link->att_mtu_desired = p_gatt->att_mtu_desired_periph;
                break;
    
    #if !defined (S112) && !defined(S312)
            case BLE_GAP_ROLE_CENTRAL:
                p_link->att_mtu_desired = p_gatt->att_mtu_desired_central;
                break;
    #endif // !defined (S112) && !defined(S312)
    
            default:
                // Ignore.
                break;
        }
    
        // Begin an ATT MTU exchange if necessary.
        if (p_link->att_mtu_desired > p_link->att_mtu_effective)
        {
            NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x.",
                          p_link->att_mtu_desired, conn_handle);
    
            err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, p_link->att_mtu_desired);
    
            if (err_code == NRF_SUCCESS)
            {
                p_link->att_mtu_exchange_requested = true;
            }
            else if (err_code == NRF_ERROR_BUSY)
            {
                p_link->att_mtu_exchange_pending = true;
                NRF_LOG_DEBUG("sd_ble_gattc_exchange_mtu_request()"
                              " on connection 0x%x returned busy, will retry.", conn_handle);
            }
            else
            {
                NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request() returned %s.",
                              nrf_strerror_get(err_code));
            }
        }
    
    #if !defined (S112) && !defined(S312)
        // Send a data length update request if necessary.
        if (p_link->data_length_desired > p_link->data_length_effective)
        {
            (void) data_length_update(conn_handle, p_link->data_length_desired);
        }
    #endif // !defined (S112) && !defined(S312)
    }
    
    
    static void on_disconnected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt)
    {
        // Reset connection parameters.
        link_init(&p_gatt->links[p_ble_evt->evt.gap_evt.conn_handle]);
    }
    
    
    /**@brief   Handle a BLE_GATTC_EVT_EXCHANGE_MTU_RSP event.
     *
     * @details The effective ATT MTU is set to the lowest between what we requested and the peer's
     *          response. This events concludes the ATT MTU exchange. An event is sent to the user
     *          and a data length update procedure is started if necessary.
     *
     * @param[in]   p_gatt      GATT structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_exchange_mtu_rsp_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt)
    {
        uint16_t conn_handle   = p_ble_evt->evt.gattc_evt.conn_handle;
        uint16_t server_rx_mtu = p_ble_evt->evt.gattc_evt.params.exchange_mtu_rsp.server_rx_mtu;
    
        nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle];
    
        // Determine the lowest MTU between our own desired MTU and the peer's.
        // The MTU may not be less than BLE_GATT_ATT_MTU_DEFAULT.
        p_link->att_mtu_effective = MIN(server_rx_mtu, p_link->att_mtu_desired);
        p_link->att_mtu_effective = MAX(p_link->att_mtu_effective, BLE_GATT_ATT_MTU_DEFAULT);
    
        NRF_LOG_DEBUG("ATT MTU updated to %u bytes on connection 0x%x (response).",
                      p_link->att_mtu_effective, conn_handle);
    
        // Trigger an event indicating that the ATT MTU size has changed.
        // Send an event to the application only if an ATT MTU exchange was requested.
        if ((p_gatt->evt_handler != NULL) && (p_link->att_mtu_exchange_requested))
        {
            nrf_ble_gatt_evt_t const evt =
            {
                .evt_id                   = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED,
                .conn_handle              = conn_handle,
                .params.att_mtu_effective = p_link->att_mtu_effective,
            };
    
            p_gatt->evt_handler(p_gatt, &evt);
        }
    
        p_link->att_mtu_exchange_requested = false;
        p_link->att_mtu_exchange_pending   = false;
    }
    
    
    /**@brief Handle a BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event.
     *
     * @param[in]   p_gatt      GATT structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_exchange_mtu_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt)
    {
        ret_code_t err_code;
        uint16_t   conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
        uint16_t   client_mtu  = p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu;
    
        nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle];
    
        NRF_LOG_DEBUG("Peer on connection 0x%x requested an ATT MTU of %u bytes.",
                      conn_handle, client_mtu);
    
        client_mtu = MAX(client_mtu, BLE_GATT_ATT_MTU_DEFAULT);
        p_link->att_mtu_effective = MIN(client_mtu, p_link->att_mtu_desired);
        p_link->att_mtu_exchange_pending = false;
    
        NRF_LOG_DEBUG("Updating ATT MTU to %u bytes (desired: %u) on connection 0x%x.",
                      p_link->att_mtu_effective, p_link->att_mtu_desired, conn_handle);
    
        err_code = sd_ble_gatts_exchange_mtu_reply(conn_handle, p_link->att_mtu_desired);
    
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("sd_ble_gatts_exchange_mtu_reply() returned %s.", nrf_strerror_get(err_code));
        }
    
        // If an ATT_MTU exchange was requested to the peer, defer sending
        // the data length update request and the event to the application until
        // the response for that request is received.
        if (p_link->att_mtu_exchange_requested)
        {
            return;
        }
    
        // The ATT MTU exchange has finished. Send an event to the application.
        if (p_gatt->evt_handler != NULL)
        {
            nrf_ble_gatt_evt_t const evt =
            {
                .evt_id                   = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED,
                .conn_handle              = conn_handle,
                .params.att_mtu_effective = p_link->att_mtu_effective,
            };
    
            p_gatt->evt_handler(p_gatt, &evt);
        }
    }
    
    
    /**@brief   Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE event.
     *
     * @details Update the connection data length and send an event to the user.
     *
     * @param[in]   p_gatt      GATT structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    #if !defined (S112) && !defined(S312)
    static void on_data_length_update_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt)
    {
        ble_gap_evt_t const gap_evt     = p_ble_evt->evt.gap_evt;
        uint16_t      const conn_handle = gap_evt.conn_handle;
    
        // Update the connection data length.
        // The SoftDevice only supports symmetric RX/TX data length settings.
        p_gatt->links[conn_handle].data_length_effective =
            gap_evt.params.data_length_update.effective_params.max_tx_octets;
    
        NRF_LOG_DEBUG("Data length updated to %u on connection 0x%0x.",
                      p_gatt->links[conn_handle].data_length_effective,
                      conn_handle);
    
        NRF_LOG_DEBUG("max_rx_octets: %u",
                      gap_evt.params.data_length_update.effective_params.max_rx_octets);
        NRF_LOG_DEBUG("max_tx_octets: %u",
                      gap_evt.params.data_length_update.effective_params.max_tx_octets);
        NRF_LOG_DEBUG("max_rx_time: %u",
                      gap_evt.params.data_length_update.effective_params.max_rx_time_us);
        NRF_LOG_DEBUG("max_tx_time: %u",
                      gap_evt.params.data_length_update.effective_params.max_tx_time_us);
    
        if (p_gatt->evt_handler != NULL)
        {
            nrf_ble_gatt_evt_t const evt =
            {
                .evt_id             = NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED,
                .conn_handle        = conn_handle,
                .params.data_length = p_gatt->links[conn_handle].data_length_effective,
            };
    
            p_gatt->evt_handler(p_gatt, &evt);
        }
    }
    
    
    /**@brief   Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event.
     *
     *@details  Reply with a sd_ble_gap_data_length_update() call, using the minimum between the
     *          link's preferred data length, and what requested by the peer.
     *          The link preferred data length is set to the global preferred data length
     *          upon connection and can be overridden by calling nrf_ble_gatt_data_length_set().
     *          The default is NRF_SDH_BLE_GAP_DATA_LENGTH.
     *
     *@note     The SoftDevice will not send any BLE_GAP_EVT_DATA_LENGTH_UPDATE events on this side.
     *          Therefore, the connection data length is updated immediately and an event is sent
     *          to the user.
     *
     * @param[in]   p_gatt      GATT structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_data_length_update_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt)
    {
        ble_gap_evt_t       const * p_gap_evt = &p_ble_evt->evt.gap_evt;
        nrf_ble_gatt_link_t       * p_link    = &p_gatt->links[p_gap_evt->conn_handle];
    
        // The SoftDevice only supports symmetric RX/TX data length settings.
        uint8_t const data_length_requested =
            p_gap_evt->params.data_length_update_request.peer_params.max_tx_octets;
    
        NRF_LOG_DEBUG("Peer on connection 0x%x requested a data length of %u bytes.",
                      p_gap_evt->conn_handle, data_length_requested);
    
        uint8_t const data_length_effective = MIN(p_link->data_length_desired, data_length_requested);
    
        (void) data_length_update(p_gap_evt->conn_handle, data_length_effective);
    }
    #endif // !defined (S112) && !defined(S312)
    
    
    ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler)
    {
        VERIFY_PARAM_NOT_NULL(p_gatt);
    
        p_gatt->evt_handler             = evt_handler;
        p_gatt->att_mtu_desired_periph  = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
        p_gatt->att_mtu_desired_central = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
        p_gatt->data_length             = NRF_SDH_BLE_GAP_DATA_LENGTH;
    
        for (uint32_t i = 0; i < NRF_BLE_GATT_LINK_COUNT; i++)
        {
            link_init(&p_gatt->links[i]);
        }
    
        return NRF_SUCCESS;
    }
    
    
    ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu)
    {
        VERIFY_PARAM_NOT_NULL(p_gatt);
    
        if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE))
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        p_gatt->att_mtu_desired_periph = desired_mtu;
        return NRF_SUCCESS;
    }
    
    
    ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu)
    {
        VERIFY_PARAM_NOT_NULL(p_gatt);
    
        if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE))
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        p_gatt->att_mtu_desired_central = desired_mtu;
        return NRF_SUCCESS;
    }
    
    
    uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle)
    {
        if ((p_gatt == NULL) || (conn_handle >= NRF_BLE_GATT_LINK_COUNT))
        {
            return 0;
        }
    
        return p_gatt->links[conn_handle].att_mtu_effective;
    }
    
    #if !defined (S112) && !defined(S312)
    ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt,
                                            uint16_t         conn_handle,
                                            uint8_t          data_length)
    {
        if (p_gatt == NULL)
        {
            return NRF_ERROR_NULL;
        }
    
        // Check early to avoid requesting an invalid data length for upcoming connections.
        if (   (data_length > BLE_GAP_DATA_LENGTH_MAX)
            || (data_length < BLE_GAP_DATA_LENGTH_DEFAULT))
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        if (conn_handle == BLE_CONN_HANDLE_INVALID)
        {
            // Save value and request upon connection.
            p_gatt->data_length = data_length;
            return NRF_SUCCESS;
        }
    
        if (conn_handle >= NRF_BLE_GATT_LINK_COUNT)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        // Request data length on existing link.
        p_gatt->links[conn_handle].data_length_desired = data_length;
    
        return data_length_update(conn_handle, data_length);
    }
    
    
    ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt,
                                            uint16_t               conn_handle,
                                            uint8_t              * p_data_length)
    {
        if ((p_gatt == NULL) || (p_data_length == NULL))
        {
            return NRF_ERROR_NULL;
        }
    
        if (conn_handle == BLE_CONN_HANDLE_INVALID)
        {
            *p_data_length = p_gatt->data_length;
            return NRF_SUCCESS;
        }
    
        if (conn_handle >= NRF_BLE_GATT_LINK_COUNT)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        *p_data_length = p_gatt->links[conn_handle].data_length_effective;
        return NRF_SUCCESS;
    }
    #endif // !defined (S112) && !defined(S312)
    
    
    void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
    {
        nrf_ble_gatt_t * p_gatt      = (nrf_ble_gatt_t *)p_context;
        uint16_t         conn_handle = p_ble_evt->evt.common_evt.conn_handle;
    
        if (conn_handle >= NRF_BLE_GATT_LINK_COUNT)
        {
            return;
        }
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                on_connected_evt(p_gatt, p_ble_evt);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                on_disconnected_evt(p_gatt, p_ble_evt);
                break;
    
            case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
                on_exchange_mtu_rsp_evt(p_gatt, p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
                on_exchange_mtu_request_evt(p_gatt, p_ble_evt);
                break;
    
    #if !defined (S112) && !defined(S312)
            case BLE_GAP_EVT_DATA_LENGTH_UPDATE:
                on_data_length_update_evt(p_gatt, p_ble_evt);
                break;
    
            case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
                on_data_length_update_request_evt(p_gatt, p_ble_evt);
                break;
    #endif // !defined (S112) && !defined(S312)
    
            default:
                break;
        }
    
        if (p_gatt->links[conn_handle].att_mtu_exchange_pending)
        {
            ret_code_t err_code;
    
            err_code = sd_ble_gattc_exchange_mtu_request(conn_handle,
                                                         p_gatt->links[conn_handle].att_mtu_desired);
    
            if (err_code == NRF_SUCCESS)
            {
                p_gatt->links[conn_handle].att_mtu_exchange_pending   = false;
                p_gatt->links[conn_handle].att_mtu_exchange_requested = true;
    
                NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x (retry).",
                              p_gatt->links[conn_handle].att_mtu_desired, conn_handle);
            }
            else if (err_code != NRF_ERROR_BUSY)
            {
                NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request() returned %s.",
                              nrf_strerror_get(err_code));
            }
        }
    }
    
    #endif //NRF_BLE_GATT_ENABLED
    

    sincerely

  • What was the MTU size before you changed it, and was it working before you changed it? Can you try to set it to 247, does it work then?

  • excuse me for the delay,

    our MTU always was 517.

    I've changed the MTU to 247, but it doesn't work again. (you can see it in the attached sniff log in packet 1277).

    I've sme questoin:

    1) what is the LL_FEATURE_REQ and is there any way to send that request with the soft device?

    2) the slave device has two modes, connection, and pairing mode. in the connection mode, LE_General_Discoverable flag in the adverting data is false and in the pairing mode, LE_General_Discoverable flag in the advertising data is true.

    in the pairing mode, we can connect and communicate with the device as expected (in the 5305.nrf52840_trace.pcapng trace packet 4981 you can see a connection established successfully).

    do you see any point in that? when the LE_General_Discoverable is true everything works but when that flag is false slave doesn't respond to us.

    3) can connection parameters like timeout or window size cause this problem?

    4) in the trace, 5305.nrf52840_trace.pcapng you've seen that softdevice tries 6 time to send MTU and then terminates the connection. is there any way to increase 6 to 16 and then when slave dosen't respond softdevice terminates the connection?

    thanks for your attention

    At with MTU.pcapng

  • Is there any other places in the application you may call something that updates the MTU? E.g. somewhere in main.c?

    alireza sadeghpour said:
    1) what is the LL_FEATURE_REQ and is there any way to send that request with the soft device?

    I don't think that is an active application call. I think the softdevice does this by itself. 

    alireza sadeghpour said:
    2) the slave device has two modes, connection, and pairing mode. in the connection mode, LE_General_Discoverable flag in the adverting data is false and in the pairing mode, LE_General_Discoverable flag in the advertising data is true.

    I am not sure I understand correctly. What do you mean with "slave doesn't respond to us"? You are not able to connect? Are you bonded?

    alireza sadeghpour said:
    3) can connection parameters like timeout or window size cause this problem?

    That is a wide question. The connection parameters can be quite complex, at least if you take the advertising parameters into account. But connection interval etc. should be fine, I guess. 

    alireza sadeghpour said:
    4) in the trace, 5305.nrf52840_trace.pcapng you've seen that softdevice tries 6 time to send MTU and then terminates the connection. is there any way to increase 6 to 16 and then when slave dosen't respond softdevice terminates the connection?

    You can try to increase the connection supervision timeout, but I think we should focus on figuring out why the central sends these messages so soon, and doesn't behave more like the other sniffer trace. Do you know? Is there any way for me to reproduce this using one or more DKs? I suspect that your application is doing this on it's own, and before it should. It is not from the file that you sent in the previous reply. Perhaps you are calling something from your main.c file?

    BR,
    Edvin

Related