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. 

 

  • My code reads next piece of data to send as soon as previous has been queued. The sending code calls in the loop with max 1ms delay until the packet goes thru (which trigger yet another send):

    // Try to send until there is buffers available (with wait, so we don't consume CPU)
    while (true)
    {
        error = sd_ble_gatts_hvx(m_conn_handle, &hvx_params);
        if (error != NRF_ERROR_RESOURCES) break;
        threadSleepMs(1);
    }

    The debug logging over the while look indicates that the code handles about 7-8 sends on first try and then waits for 30-40 ms until it succeeds.


    Event length should be ok (and indeed it works with PHY_1M):

    #define NRF_SDH_BLE_GAP_EVENT_LENGTH 36
  • Hi Petri, 

    Please send the 1Mbps trace.

    Could you try increasing the NRF_SDH_BLE_GAP_EVENT_LENGTH  ? 

    If you test the throughput example in the NRF5 SDK you can find that at 2M PHY the throughput can be achieved is around 1.4Mbps. 

  • Hello,

    Got back to office and did the following test runs (Ellisys files as attachment). Short result: No changes in behaviour from previous tests.



    - 1M1M (request 1M on rx & tx) => fast

    - 2M2M (request 2M on rx & tx) => slow

    - 2MxM (request 2M on tx, 1M or 2M on rx) => slow

    - RetAutoOnReq: Don't ask for PHY, just if requested set rx & tx to BLE_GAP_PHY_AUTO (phone chooses 1M) => fast

    - 2M2M_EL400 (request 2M on rx & tx, set NRF_SDH_BLE_GAP_EVENT_LENGTH to 400) => slow

    PHY2MTests.zip

  • Hi Petri, 

    In your code:

    while (true)
    {
        error = sd_ble_gatts_hvx(m_conn_handle, &hvx_params);
        if (error != NRF_ERROR_RESOURCES) break;
        threadSleepMs(1);
    }

    What happens when sd_ble_gatts_hvx returns NRF_SUCCESS  ? From what I can see it will just break out of the while loop. 
    How do you queue the next packets when the first one is successfully queued ? 
    Please try to test with just queueing more data right away when the previous packet is successfully queued. 

  • This loop resides in a "dlServiceSend" function which is part of our communication stack. There is a thread outside that calls that code in a loop until there is no more data to send. So the next call comes in as soon as the while loop (and the function) is exited.

    In my debug printouts it is clearly visible that the waiting happens in the while loop above until the connection interval is over (usually around 35 ms). So in short there is data waiting to be sent which causes it to wait in that while loop because sd_ble_gatts_hvx returns NRF_ERROR_RESOURCES.

Related