MTU exchange issue – ble_app_uart_c / ble_app_uart with MTU 247

I am using the nRF5 SDK, nRF52833, and nRF52832.

I flashed the following two demos:

  • nRF5_SDK_17.1.0_ddde560\examples\ble_central\ble_app_uart_c\pca10100\s122 (nRF52833)

  • nRF5_SDK_17.1.0_ddde560\examples\ble_peripheral\ble_app_uart\pca10040\s132 (nRF52832)

I changed BLE_GATT_ATT_MTU_DEFAULT to 247 in both projects.

However, the MTU exchange does not happen. In the following function:

void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
    if (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)
    {
        NRF_LOG_INFO("ATT MTU exchange completed.");
        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
        NRF_LOG_INFO("Ble NUS max data length set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    }
}

These two log messages do not appear.

In actual data transmission, I can only send 20 bytes. Sending 23 bytes causes an error.

Could you please help me understand why the MTU exchange is not taking place?

Thank you.

Parents
  • Hello,

    I have not tried to reproduce this yet, but as a test, please try set NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED to "0" in your ble_app_uart build so that the MTU exchange is only initiated by the central. 

    Best regards,

    Vidar

  • Hi Vidar,

    Thank you for your suggestion. Setting NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED to 0 on the peripheral side worked – the MTU exchange now happens successfully.

    However, I have a follow-up question. Looking at the logs:

    00> <debug> nrf_ble_gatt: max_rx_octets: 27
    00> 
    00> <debug> nrf_ble_gatt: max_tx_octets: 27

    Why is it showing 27 bytes?

    Here is the full log for reference:

    00> <info> app_timer: RTC: initialized.
    00> 
    00> <info> app: Debug logging for UART over RTT started.
    00> 
    00> <info> app: Advertising_start.
    00> 
    00> <debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
    00> 
    00> <info> app: Connected
    00> 
    00> <debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 247 bytes.
    00> 
    00> <debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
    00> 
    00> <info> app: Data len is set to 0xF4(244)
    00> 
    00> <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    00> 
    00> <debug> nrf_ble_gatt: Data length updated to 27 on connection 0x0.
    00> 
    00> <debug> nrf_ble_gatt: max_rx_octets: 27
    00> 
    00> <debug> nrf_ble_gatt: max_tx_octets: 27
    00> 
    00> <debug> nrf_ble_gatt: max_rx_time: 328
    00> 
    00> <debug> nrf_ble_gatt: max_tx_time: 328
    00> 
    00> <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    00> 

    The ATT MTU exchange shows 247 bytes (0xF7), but the data length update shows only 27 octets. I expected the data length to be updated to a larger value as well.

    Could you please explain why the data length remains at 27 bytes in this case?

    Thank you for your help.

  • Hi Vidar,

    Thank you for the suggestion.

    I have checked both projects (central and peripheral), and NRF_SDH_BLE_GAP_DATA_LENGTH is already set to 251 in both sdk_config.h files:

    // <i> Requested BLE GAP data length to be negotiated.
    #ifndef NRF_SDH_BLE_GAP_DATA_LENGTH
    #define NRF_SDH_BLE_GAP_DATA_LENGTH 251
    #endif

    However, the log still shows max_rx_octets: 27 and max_tx_octets: 27 after the data length update.

    Could there be another configuration or setting that is limiting the data length to 27 bytes?

    Thank you for your continued support.

  • Hi,

    Have you made any other changes to these projects? I tried to reproduce this here using the examples from SDK 17.1.0, but without any luck.

    Log output

  • Hi Vidar,

    Thank you for trying to reproduce the issue.

    I noticed something in my setup. In the ble_app_uart_c (central) project, the data_length_update() function is grayed out – meaning it is not compiled. This is controlled by the following preprocessor condition:

    /**@brief   Start a data length update request procedure on a given connection. */
    #if !defined (S112) && !defined(S312) && !defined(S122)
    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) && !defined (S122)

    My central project (ble_app_uart_c) uses S122 SoftDevice. Since S122 is explicitly excluded by !defined(S122), the data length update code is disabled.

    My peripheral project (ble_app_uart) uses S132 – which is not excluded – so the data length update code is enabled there.

    Could this be the reason why the data length negotiation is not succeeding? Is S122 capable of supporting Data Length Extension (DLE) beyond 27 bytes? If not, does that mean the central (S122) is limited to 27 bytes regardless of the MTU setting?

    Thank you.

  • Hi,

    Sorry, I overlooked the fact that you were using s122. This is a size optimised softdevice variant with a reduced feature set and does not include the "LE Data Packet Length Extension" feature. I would recommend you consider using the s140 instead if you have enough flash.

  • Hi Vidar,

    Thank you for the confirmation. That explains the issue perfectly.

    The ble_app_uart_c example for the nRF52833 (pca10100) in SDK 17.1.0 only includes a project file for the S122 SoftDevice by default . There is no pre-configured S140 folder for this specific central example.

    Could you please guide me on how to manually migrate the ble_app_uart_c example to use the S140 SoftDevice on the nRF52833? I understand the hardware is capable, as the nRF52833 is fully compatible with S140 .

    Thank you.

Reply
  • Hi Vidar,

    Thank you for the confirmation. That explains the issue perfectly.

    The ble_app_uart_c example for the nRF52833 (pca10100) in SDK 17.1.0 only includes a project file for the S122 SoftDevice by default . There is no pre-configured S140 folder for this specific central example.

    Could you please guide me on how to manually migrate the ble_app_uart_c example to use the S140 SoftDevice on the nRF52833? I understand the hardware is capable, as the nRF52833 is fully compatible with S140 .

    Thank you.

Children
  • Hi,

    I see. My suggestion would be to make a copy of the "s122" named "s140", then update the project configurations to match the s140 softdevice. You can use the pca10056/s140 project as a reference for this.

    Key changes needed:

     - Change application start address to accommodate the larger Softdevice

     - Change include paths so the point to the s140 API headers instead of s122

     - Change preprocessors symbol from s122 to s140

    Best regards,

    Vidar

Related