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

Maximizing Notification throughput

I'm attempting to transfer 256K bps (1 244-byte notification every ~7.5ms) using an nRF52840 using Notifications and am not getting close to the necessary bandwidth.  I'm getting the (dreaded) NRF_ERROR_RESOURCES error and have a few questions about the way that the S140 soft devices handles notifications:   I used sd_ble_gap_phy_update to specify BLE_GAP_PHY_2MBPS after receiving the BLE_GAP_EVT_CONNECTED event.    I also set BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT to 20.  My questions (so far):

  1. When a characteristic value is sent using a Notification (via sd_ble_gatts_hvx), a pointer to the ble_gatts_hvx_params_t structure is sent.   In sd_ble_gatts_hvx, is this information copied, or, if BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT is greater than 1 (eg. 20) should an array of ble_gatts_hvx_params_t be created and used for this information?   In other words, if more than 1 Notification can be queued, is the information sent to sd_ble_gatts_hvx queued internally or should I maintain an array?
  2. When > 1 Notifications can be queued, are the associated characteristic values always sent in the order submitted?
  3. I increased the mtu size (NRF_SDH_BLE_GATT_MAX_MTU_SIZE) to 247 (as shown in several examples).    Is this a hard upper limit, or can the mtu size be increased to get additional bandwidth?
  4. I also increased NRF_SDH_BLE_GAP_DATA_LENGTH to 251 (as shown in several examples).   Is this the equivalent to enabling DLE?   If not, what specifically must be done?
  5. When the event BLE_GATTS_EVT_HVN_TX_COMPLETE is issued, what value is passed in the p_context argument?   Is this the pointer to the ble_gatts_hvx_params_t structure that was sent with the associated call to sd_ble_gatts_hvx that initiated the Notification?   
  6. Is there any detailed documentation that I can read to help optimize the S140 with my application?

Thanks!

Parents
  • Hi,

    1) It's copied and queued internally.

    2) The packets are buffered and transmitted in the order they were queued.

    3) It can be increased further, but 247 will give you the max throughput. By setting NRF_SDH_BLE_GAP_DATA_LENGTH = 251 (this is max), and NRF_SDH_BLE_GATT_MAX_MTU_SIZE = 247, then we avoid fragmentation of the ATT packet into several on-air data packets.

    4) Yes.

    5) No. As far as I can see, it's only a parameter to the event handler that you pass when the observer is registered. e.g. here only NULL is passed,

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);

    6) We have a chapter about throughput in the SDS, see this link. This blog-post from novel bits might be helpful as well.

    For increased throughput, I recommend increasing NRF_SDH_BLE_GAP_EVENT_LENGTH in sdk_config.h to e.g. 320, and enable connection event length extension.

    You can enable Connection Event Length Extension with a function like this:

    void conn_evt_len_ext_set(bool status)
    {
        ret_code_t err_code;
        ble_opt_t  opt;
    
        memset(&opt, 0x00, sizeof(opt));
        opt.common_opt.conn_evt_ext.enable = status ? 1 : 0;
    
        err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
        APP_ERROR_CHECK(err_code);
    
    }
    

    Then call conn_evt_len_ext_set(true) after you have enabled the SoftDevice.

    If you still are having issues with throughput, please do a sniffer trace with nRF Sniffer.

  • Another update:

    1.   I had increased the TX_QUEUE size by modifying BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT to 20 in ble_gatts.h.    I thought perhaps doing it dynamically might have a better outcome, so I changed the #define back to 1 and used the code segment:  

        // Increase the TX QUEUE size
        ble_cfg_t ble_cfg;
        memset(&ble_cfg, 0, sizeof ble_cfg);
        ble_cfg.conn_cfg.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
        ble_cfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = 20;
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);

    to attempt to increase it.    This resulted in an error that there was not enough memory, so I switched back to setting the QUEUE size to 20 in the .h file.

    2. Using the code in the earlier post, I attempted to run with my emulator sending one 244 byte Notification every 7.6 ms.   Many of the notifications don't get sent because sd_ble_gatts_hvx returns error 19 (NRF_ERROR_RESOURCES) even though the variable I maintain that tracks the number of TX queue entries shows there should be 16 empty queue positions (per an NRF_LOG_DEBUG message that logs the err_code and bleNotificationsAvailable variable.)

    3. I'm using a Samsung S8 phone (BLE 5.x) to receive (as the central) and set the phy to 2MBPS in the peripheral when the BLE_GAP_EVT_CONNECTED is received.    With the MIN_CONN_INTERVAL set to 7.5 ms, a significant number of packets don't get sent.    I increased the MIN_CONN_INTERVAL to 50 ms and even more packets don't get set.

    Are there other resources that must be increased when the TX QUEUE size is increased?

    Thanks...

Reply
  • Another update:

    1.   I had increased the TX_QUEUE size by modifying BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT to 20 in ble_gatts.h.    I thought perhaps doing it dynamically might have a better outcome, so I changed the #define back to 1 and used the code segment:  

        // Increase the TX QUEUE size
        ble_cfg_t ble_cfg;
        memset(&ble_cfg, 0, sizeof ble_cfg);
        ble_cfg.conn_cfg.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
        ble_cfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = 20;
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);

    to attempt to increase it.    This resulted in an error that there was not enough memory, so I switched back to setting the QUEUE size to 20 in the .h file.

    2. Using the code in the earlier post, I attempted to run with my emulator sending one 244 byte Notification every 7.6 ms.   Many of the notifications don't get sent because sd_ble_gatts_hvx returns error 19 (NRF_ERROR_RESOURCES) even though the variable I maintain that tracks the number of TX queue entries shows there should be 16 empty queue positions (per an NRF_LOG_DEBUG message that logs the err_code and bleNotificationsAvailable variable.)

    3. I'm using a Samsung S8 phone (BLE 5.x) to receive (as the central) and set the phy to 2MBPS in the peripheral when the BLE_GAP_EVT_CONNECTED is received.    With the MIN_CONN_INTERVAL set to 7.5 ms, a significant number of packets don't get sent.    I increased the MIN_CONN_INTERVAL to 50 ms and even more packets don't get set.

    Are there other resources that must be increased when the TX QUEUE size is increased?

    Thanks...

Children
No Data
Related