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

DLE goes to 27 when using PHY_2M

Hello,

We're trying to optimize the data transfer rate from our nRF52832 based peripheral device to the mobile phone. Tested with two different BLE >= 5 Android phones we encountered a weird behavior and would like to get your help to resolve it.

Our device uses SoftDevice s132 v6.1.1 and SDK 15.3 and in the beginning of the connection we set

MTU: 161 (RAM limited)
DLE: rx: 165 , tx: 165

The phone that I use (OnePlus 8) approves the MTU and requests DLE rx: 251, tx: 27 so the final negotiation results 165 (periph->central), 27 (central->periph). The phone is typically content using PHY_1M and this results the throughput (measured with Ellisys sniffer) of about 60kB/s which is pretty much what I would hope for it.

As soon as I change the connection to PHY_2M (either with nRF Connect debug mode on the phone or requesting it from the device software) the speed drops by about 50% resulting around 30-35 kB/s. The sniffer revealed the reason to be that the data length was dropped to 27 resulting a lot of very small packets. Initially I thought that the reason for this was the nrf_ble_gatt -module which I had enabled to take care of DLE and MTU settings since the RTT logs revealed some GATT module printouts and there was this really weird comment in the code ("The SoftDevice only supports symmetric RX/TX data length settings."), so I removed the GATT module and replaced the funtionality with direct SD calls.

However even after specifically setting DLE to (165,165) the connection defaults to 27 byte packets and really slow connection as soon as I set PHY_2M. This is really weird since the 1M PHY works great and I didn't think there was any extra limitations on DLE because of different PHYs. I did try to search for help in SoftDevice specification but did not find anything that sounded relevant...

Thank you in advance,

Petri L.
ps. I have the Ellisys logs available (the PHY_2M case with GATT module) but would like to keep them confidential if possible. 

 

  • Hi Petri, 

    You can move this thread to Private if you want to provide confidential information. Please click on "Go Private" button. 

    In the sniffer trace, please check for which side send the request to change the DLE size. 

    It could be the issue on the phone that it doesn't support long DLE size on 2Mbps PHY. 

  • I'm away from the sniffer and managed to distill the case to the minimal change of calling or not calling the sd_ble_gap_phy_update()-function after receiving BLE_GAP_EVT_CONNECTED.  The code calls sd_ble_gap_data_length_update() after receiving BLE_GATTC_EVT_EXCHANGE_MTU_RSP as well as BLE_GAP_EVT_PHY_UPDATE (when status == 0). The row with DataLengthSet is the one where the call to sd_ble_gap_data_length_update happens.

    With PHY 2M:

    00:00:14 BLE GAP: onConnect to 7A:A7:A8:35:1E:5C (Random private resolvable)
    00:00:15 BLE event: 0x3A - Exchange MTU Response event
    00:00:15 BLE_GATTC_EVT_EXCHANGE_MTU_RSP server_rx_mtu: 161
    00:00:15 BleGapService::DataLengthSet
    00:00:15 BLE event: 0x22 - BLE_GAP_EVT_PHY_UPDATE
    00:00:15 BLE_GAP_EVT_PHY_UPDATE (RX:2, TX:2, status:0)
    00:00:15 BleGapService::DataLengthSet
    00:00:15 BLE event: 0x24 - Data length update
    00:00:15 BLE_GAP_EVT_DATA_LENGTH_UPDATE: max_tx_octets: 165, max_rx_octets: 27
    00:00:15 BLE event: 0x12 - Connection Parameters updated
    00:00:15 BLE_GAP_EVT_CONN_PARAM_UPDATE. min_conn_interval: 6, max_conn_interval: 6, slave_latency: 0, conn_sup_timeout: 500
    00:00:16 BLE event: 0x12 - Connection Parameters updated
    00:00:16 BLE_GAP_EVT_CONN_PARAM_UPDATE. min_conn_interval: 36, max_conn_interval: 36, slave_latency: 0, conn_sup_timeout: 500

    Same code without requesting phy_update (so the speed stays PHY_1M):

    00:00:05 BLE GAP: onConnect to 42:B6:5F:10:19:CC (Random private resolvable)
    00:00:05 BLE event: 0x3A - Exchange MTU Response event
    00:00:05 BLE_GATTC_EVT_EXCHANGE_MTU_RSP server_rx_mtu: 161
    00:00:05 BleGapService::DataLengthSet
    00:00:05 BLE event: 0x24 - Data length update
    00:00:05 BLE_GAP_EVT_DATA_LENGTH_UPDATE: max_tx_octets: 165, max_rx_octets: 27
    00:00:06 BLE event: 0x12 - Connection Parameters updated
    00:00:06 BLE_GAP_EVT_CONN_PARAM_UPDATE. min_conn_interval: 6, max_conn_interval: 6, slave_latency: 0, conn_sup_timeout: 500
    00:00:06 BLE event: 0x12 - Connection Parameters updated
    00:00:06 BLE_GAP_EVT_CONN_PARAM_UPDATE. min_conn_interval: 36, max_conn_interval: 36, slave_latency: 0, conn_sup_timeout: 500

    In both cases I receive the event BLE_GAP_EVT_DATA_LENGTH_UPDATE (max_tx_octets: 165, max_rx_octets: 27) indicating that the DLE is setup identically but the xfer speed is half of 1M case (I'm not with the sniffer right now so I can't confirm it with it).

    EDIT: I confirmed same behavior with two different phones: OnePlus 8 (Android 11) and Sony XPeria XZ Premium (Android 9) so it does not feel like a phone quirk.

  • Hi Petri, 

    Please provide the sniffer trace. We would need to see why the throughput dropped. As you mentioned in your last reply the max TX octets remains at 165. So why the throughput dropped ? Was it because the transmitting rate dropped ? or smaller packet was sent even though the DLE TX is 165 ?

  • Hi,

    Sniffing revealed a couple of things. First, the DLE is now correct so the removal of nrf_ble_gatt module cured that issue. Unfortunately that didn't help the speed as seen in the previous message.

    I've attached the screen-grabs from Ellisys which reveal the following:

    Last connection update before data transfer sets the parameters as:
    - Transmit window size: 1.250 ms
    - Transmit window offset: 18.750 ms
    - Connection Event Interval: 45.000 ms
    (I could not find Event Length parameter anywhere). 

    The data transmit happens with correct PHY (2M) and data length (165) but for some reason the transmission only happens for ~10 ms of the whole 45 ms connection interval, the rest is spent waiting.


    When having 1M PHY the transmission happens over almost all connection interval (see pic) which explains the throughput difference now that DLE issue has been resolved.

    I've attached also here the raw 2M sniffer log in case your experts can use it to figure out the reason for packets not being sent:
    PHY_2M_DLEIssue.btt

  • Hi Petri, 

    Could you also send the 1M sniffer for comparison ? 

    From what I can find here in the last packet before the peers stopped transmission in a connection event is that the MD (More Data) bit is not set. This means the Peripheral doesn't want to send anything further. 

    There could be 2 reasons for this: 

    - There is no data queued. We need to take a look at how you queued your data, have you queued more data when you receive BLE_GATTS_EVT_HVN_TX_COMPLETE event ? 
    - Your event length configuration was too short. Could you please check NRF_SDH_BLE_GAP_EVENT_LENGTH configuration in sdk_config.h and check if you used that number in nrf_sdh_ble_default_cfg_set()  ? 

Related