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

Event length configuration on Central for concurrent Connection

Hello, 

I am trying to get central to concurrently connect to multiple (as many as possible) peripherals and stream data from each peripheral concurrently at 12KBytes/s. But I keep getting the error below. The error indicates that it can't send the data within the given event length. But from my calculation below this should not happen.

<error> nrf_ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned NRF_ERROR_RESOURCES.
<error> nrf_ble_gatt: The requested TX/RX packet length is too long by 94/94 octets.
<error> nrf_ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned NRF_ERROR_RESOURCES.
<error> nrf_ble_gatt: The requested TX/RX packet length is too long by 94/94 octets.

What I need to achieve

  • I need to connect central to as many peripherals as possible while maintaining a baud rate of 12KBytes/s (i.e 600 bytes within 50ms)
    • I can connect to 1 peripheral and get a max through put of 32KBytes/s
  • The connection intervals are 7.5ms 
  • Date Rate: 1Mbps
  • The data length = 251
  • The MTU size = 247
  • Packet per connection interval: 1 (peripheral can only send 1 packet per connection interval) 
  • By my calculations I can connect 3 peripherals and support this baud rate.
    • It would take 3 connection intervals to send all 600 bytes and 3 connection intervals only takes 22.5ms which is well below 50ms.  
    • Set the event length on central to 2.5ms 
      • This should allow the soft device to connect to 3 peripherals within that 7.5ms window. Every event length it connect to another peripheral.
      • To send 265bytes of data on 1Mbps connection only takes 2.12ms
  • I have setup the event length to be 3.75 to just be safe and I still get the error above

SDK configuration applied

  • NRF_SDH_BLE_GAP_DATA_LENGTH = 251

  • NRF_SDH_BLE_PERIPHERAL_LINK_COUNT = 0

  • NRF_SDH_BLE_CENTRAL_LINK_COUNT = 6

  • NRF_SDH_BLE_TOTAL_LINK_COUNT = 6

  • NRF_SDH_BLE_GAP_EVENT_LENGTH = 3 --> 3*1.25 = 3.75ms

  • NRF_SDH_BLE_GATT_MAX_MTU_SIZE = 247

  • I have also enabled extended BLE connection events as seen below
    •     ble_opt_t opt = { 0 };
      
          opt.common_opt.conn_evt_ext.enable = 1;
      
          rc = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
          assert(NRF_SUCCESS == rc);

This is for a S140 softdevice

  • When you mentioned "But I am just hammering the peripheral to send data as fast as it can. " what exactly you did ? 

    I would call ble_nus_data_send() as fast as I can. See below:

            do {
                 retval = ble_nus_data_send(&m_nus, (uint8_t*)data, &chunk, m_conn_handle);
            } while (retval == NRF_ERROR_RESOURCES);

    I have also tried when you said and it doesn't help. I am still only sending 1 packet at a time.

    When I received `NRF_ERROR_RESOURCES` I would wait for the `BLE_GATTS_EVT_HVN_TX_COMPLETE` but this only works for a little while and then the SD stops sending the `BLE_GATTS_EVT_HVN_TX_COMPLETE`. That is the SD would return `NRF_ERROR_RESOURCES` but `BLE_GATTS_EVT_HVN_TX_COMPLETE` would never happen. It works for a while and just stops.

    So instead of waiting for the `BLE_GATTS_EVT_HVN_TX_COMPLETE` I just keep calling `ble_nus_data_send()` until resource are available. 

    Either way none of this actually help me achieve my end goal. 

    I still don't understand why I can't use a event length of 2.5ms? After some testing I found I have to use an event length of at least 6.25ms on central if not central SD produces the error code below. Which make no sense this is very large event time. 

    <error> nrf_ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned NRF_ERROR_RESOURCES.
    <error> nrf_ble_gatt: The requested TX/RX packet length is too long by 94/94 octets.
    <error> nrf_ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned NRF_ERROR_RESOURCES.
    <error> nrf_ble_gatt: The requested TX/RX packet length is too long by 94/94 octets.

    Even if we assume there overhead 3.75ms should be more thane enough time to send a packet of 265 bytes + any overhead. Using 6.25ms makes no sense and the central SD should have the ability to do this.

  • Just an update I can only call ble_nus_data_send() once before it returns NRF_ERROR_RESOURCES
    On the peripheral I have NRF_SDH_BLE_GAP_EVENT_LENGTH set to 6. 

    I am only send 244 bytes into ble_nus_data_send(). NRF_SDH_BLE_GAP_DATA_LENGTH is set to 251. 

    Even if I send 10 bytes after the first call to ble_nus_data_send() it will always return NRF_ERROR_RESOURCES. Which makes nno sense to me.

  • Hi, 

    This code: 

         do {
                 retval = ble_nus_data_send(&m_nus, (uint8_t*)data, &chunk, m_conn_handle);
            } while (retval == NRF_ERROR_RESOURCES);

    will only execute once if the result is successful. It stays in the loop if retval == NRF_ERROR_RESOURCES. 

    Instead you should use do{} while (retval==NRF_SUCCESS). And then come back to the loop when there is BLE_GATTS_EVT_HVN_TX_COMPLETE event. 

    Another reason why you see only 1 packet in a 7.5ms interval with NRF_SDH_BLE_GAP_EVENT_LENGTH  set to 6 probably is that by default we set both max_rx_octets and max_tx_octets equal to the NRF_SDH_BLE_GAP_DATA_LENGTH inside data_length_update() in nrf_ble_gatt.c 

    The scheduler in the softdevice is not smart enough to detect that the packet is only one direction and the other packet is empty ( 26bytes with empty payload) but it simply calculated the maximum possible size of RX and TX packet to schedule the event (the number of packets per event). 

    In this case if we have both RX and TX at 251 bytes (277 bytes on air) it would take 2238us to transmit and therefore can't fit 4 packets inside a 7.5ms 

    So if you call sd_ble_gap_data_length_update() with correct RX&TX size (set TX close to or equal to 0 on central and RX to close 0 on peripheral) you should be able to fit 2 notification packet inside one 7.5ms interval. 

    In my setup I set RX = 20 (peripheral)  and TX = 20 ( central) and NRF_SDH_BLE_GAP_EVENT_LENGTH  = 5. And can see 2 packets of notification per connection event. 

    Please try to get hold of a NRF52 DK and use it as a sniffer, it can reveal many information and can help your development. 

Related