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

Disconnection within short range

Hello ,

I am working on a project in which two devices(one is central and other is peripheral ) uses Nordic bluetooth controller  for connection and data exchange. nrf51822 for peripheral and nrf51422 for the central. I have random disconnection when I try to send too many messages from the remote(central) to the peripheral. 

The short range disconnection happens by pressing the buttons on the remote in a fast random manner at a distance of 20 metres from the peripheral. The issue does not  happen, when the same buttons are pressed randomly fast in a close range(5-10 m) or if the buttons are pressed not so fast at long range(> 30m).

The analysis points to the fact that, when packets/messages sent from remote to the wheel is very high, some of the packets are lost and disconnection event is triggered by the soft device.

More analysis on the short range disconnection issue is due to distance between central and peripheral, some packets are getting lost and do not get BLE_EVT_TX_COMPLETE/BLE_GATTS_EVT_HVX_TX_COMPLETE for those messages. Due to which the transmit buffers are not cleared and on sending more messages fills up the transmit buffers very fast. This would lead to NRF_ERROR_NO_TX_PACKETS.

Our code does not use APP_ERROR_CHECK(err_code) . and no soft device resets happen due to that. Below the code to send ble messages.

#define MAX_TIMEOUT_COUNT 0xFFFF

while (ble_nus_c_control_send(&m_ble_nus_c_first_client, data_array, leng) != NRF_SUCCESS)   
      {
       // repeat until sent or until timeout counter reached maximum count
       timeout_counter++;
       if(timeout_counter > MAX_TIMEOUT_COUNT)
       {
        break;
       }
      }

Could you please look at the above code that we use to send ble messages and let us know if this could cause any issues to fill up the TX buffer fast.

Kindly answer the questions below for us to help in debugging.

1, In above scenario, is it possible to tell the BLE layer to clear the transmit buffers irrespective the sent message was successful or not. Which method to use, BLE_GATT_HVX_NOTIFICATION or BLE_GATT_HVX_INDICATION ?

2, Can you please suggest optimistic connection parameters (too short connection supervision timeout relative to the connection interval) so that only a few packet drops will lead to disconnect. In our case, we will have frequent out of range scenarios and expect to reconnect back quickly. when in range.

#define MIN_CONNECTION_INTERVAL     MSEC_TO_UNITS(7.5, UNIT_1_25_MS)    /**< Determines minimum connection interval in millisecond. */

#define MAX_CONNECTION_INTERVAL     MSEC_TO_UNITS(30, UNIT_1_25_MS)     /**< Determines maximum connection interval in millisecond. */
#define SLAVE_LATENCY               0                                   /**< Determines slave latency in counts of connection events. */
#define SUPERVISION_TIMEOUT         MSEC_TO_UNITS(1000, UNIT_10_MS)     /**< Determines supervision time-out in units of 10 millisecond. */

3, Please advise if the LF_CLK_SRC values are opptimal.

#define NRF_CLOCK_LFCLKSRC      {.source        = NRF_CLOCK_LF_SRC_RC,            \

                                 .rc_ctiv       = 16,                                \
                                 .rc_temp_ctiv  = 2,                                \
                                 .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM}

Adding the previous queries what was posted in previous mail.

1, Is it possible to increase the transmit/receive FIFO/buffer size or number of TX/RX buffer ?

2, Can we use any function to clear the TX/RX FIFO/buffer ? If yes can you please let us know what function could do this ?

Kind Regards,

Thomas

Parents
  • Hi Sigurd,

    Thanks for the reply. 

    Each press of a button would send a packet/message to the peripheral.  MAX_TIMEOUT_COUNT IS 0xFFFF. Yes we use SDK version 12.3. 

    From your reply, what I understand is

    ”since the soft device was not able to send packets that was queued up, the BLE link would be disconnected. In our case the reason for not able to send packets was bad link. Is this right ?

    Or

    1, Could you suggest other possible reasons where BLE link would be disconnected when tx queue is full.

    2, Will there be disconnect if soft device is not able to execute because CPU time is used by other resources?

    3, Can a buffer overflow of tx queue cause this disconnection.

    Kind Regards,

    Thomas

  • ”since the soft device was not able to send packets that was queued up, the BLE link would be disconnected. In our case the reason for not able to send packets was bad link. Is this right ?

    This is most likely. When the disconnect happens, you will get a event called BLE_GAP_EVT_DISCONNECTED, here you can check the disconnect reason code

    Snippet:

    case BLE_GAP_EVT_DISCONNECTED:
            
                NRF_LOG_INFO("Disconnected reason: %d.",p_ble_evt->evt.gap_evt.params.disconnected.reason);

    1, Could you suggest other possible reasons where BLE link would be disconnected when tx queue is full.

    It could be any scenario where the other side of the link stops responding, such as going out of range.

    2, Will there be disconnect if soft device is not able to execute because CPU time is used by other resources?

    The SoftDevice is running at highest interrupt priority, so that would be unlikely. But if you have blocking code in your application, you won't be able to process any new SoftDevice events in the application. I therefore recommend decreasing the value of "MAX_TIMEOUT_COUNT".

    3, Can a buffer overflow of tx queue cause this disconnection.

    No.

    You should check the disconnect reason, if it happens because you went out of range, the supervision timeout will trigger and and you will get a BLE_GAP_EVT_DISCONNECTED event with reason BLE_HCI_CONNECTION_TIMEOUT(0x08).

  • 1, At what scenarios BLE_HCI_CONNECTION_TIMEOUT can occur ? Does it happen only when out of range ?

    If your BLE peripheral/central is in a connection with a peripheral/central, and the peripheral /central stops responding for so long that the supervision timeout triggers, you will get the event BLE_GAP_EVT_DISCONNECTED with reason BLE_HCI_CONNECTION_TIMEOUT (0x08).

    Going out of range could be one root cause, but if the other device e.g. enters the error-handler, and is therefore unable to send packets, this could also cause the disconnect with this disconnect reason.

    Also, when there is a BLE_HCI_CONNECTION_TIMEOUT, do we get BLE_GAP_EVT_TIMEOUT.

    No.

    f we get BLE_GAP_EVT_TIMEOUT, how should it be handled. Should we call sd_ble_gap_disconnect() or start scanning again ?

    Start scanning again.

    3, Is it possible to not use either indication or notification, so that the buffers are cleared without ACK being received. Can we tell the link layer to not use indication or notification ?

    You don’t need to send a notification/indication, but if you do, they need to be delivered, or else the connection will timeout.

    Even after trying to set the bandwidth to 6 as in above methods, the bandwidth does not change.

    Use both methods. But you forgot to set the role for method 2. Use this code for method 2:

         /*Configure bandwidth */
     ble_opt_t ble_opt;
     ble_common_opt_conn_bw_t conn_bw;
     memset(&conn_bw, 0x00, sizeof(conn_bw));
     memset(&ble_opt, 0x00, sizeof(ble_opt));
    
     conn_bw.conn_bw.conn_bw_rx = BLE_CONN_BW_HIGH;
     conn_bw.conn_bw.conn_bw_tx = BLE_CONN_BW_HIGH;
     conn_bw.role = BLE_GAP_ROLE_CENTRAL;
     
     ble_opt.common_opt.conn_bw = conn_bw;
     
     uint32_t err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_BW, &ble_opt);
     APP_ERROR_CHECK(err_code);

    The reason for disconnection is BLE_HCI_CONNECTION_TIMEOUT(0x08)

    1) Do you get this reason at the central or peripheral? Do you get any events at the other device?

    2) Did you set MAX_TIMEOUT_COUNT to a low value ?

  • Hi Sigurd,

    Yes, I had partial success in configuring tx buffer width to 6 using the below code. Thanks for the code snippet.

    I verified using sd_ble_tx_packet_count_get() and could see the count as 6. But when I try to connect to both the peripherals from the central it does not succeed. The product currently I am working has a remote which is the central and two peripherals.

        /*Configure bandwidth */

     ble_opt_t ble_opt;
     ble_common_opt_conn_bw_t conn_bw;
     memset(&conn_bw, 0x00, sizeof(conn_bw));
     memset(&ble_opt, 0x00, sizeof(ble_opt));
     conn_bw.conn_bw.conn_bw_rx = BLE_CONN_BW_HIGH;
     conn_bw.conn_bw.conn_bw_tx = BLE_CONN_BW_HIGH;
     conn_bw.role = BLE_GAP_ROLE_CENTRAL;
     
     ble_opt.common_opt.conn_bw = conn_bw;
     
     uint32_t err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_BW, &ble_opt);
     APP_ERROR_CHECK(err_code);
    The queries I have is 
    1, Since I am increasing the tx buffer bandwidth from 3 to 6, do I need to make any changes in RAM(memory configuration) file ?
    2, How much memory should I increase for the soft device, when the tx buffer is increased from 3 to 6 .
    Currently I increase 24 bytes(since MTU is 23 bytes) for one buffer, then for 3 buffers 3*24=72.
    Since our product has two peripherals and so two connections, I make it 72+72 = 144.
    Please share your thoughts on this calculations.
    3, Do I need to check the buffer width for peripheral. For peripheral I assume tx buffer width to be 6 by default.
    Answers to your previous questions

    1) Do you get this reason at the central or peripheral? Do you get any events at the other device?

    [tpoly] - I get the BLE_HCI_CONNECTION_TIMEOUT(0x08) at the central.

    2) Did you set MAX_TIMEOUT_COUNT to a low value ?

    [tpoly] - I have set the MAX_TIMOUT_COUNT to 1, but still issue persists.

    Kind Regards,

    Thomas

  • Hi Sigurd,
    Yes, I had partial success in configuring tx buffer width to 6 using the below code. Thanks for the code snippet.
    I verified using sd_ble_tx_packet_count_get() and could see the count as 6. But when I try to connect to both the peripherals from the central it does not succeed. The product currently I am working has a remote which is the central and two peripherals.
        /*Configure bandwidth */
     ble_opt_t ble_opt;
     ble_common_opt_conn_bw_t conn_bw;
     memset(&conn_bw, 0x00, sizeof(conn_bw));
     memset(&ble_opt, 0x00, sizeof(ble_opt));
     conn_bw.conn_bw.conn_bw_rx = BLE_CONN_BW_HIGH;
     conn_bw.conn_bw.conn_bw_tx = BLE_CONN_BW_HIGH;
     conn_bw.role = BLE_GAP_ROLE_CENTRAL;
     
     ble_opt.common_opt.conn_bw = conn_bw;
     
     uint32_t err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_BW, &ble_opt);
     APP_ERROR_CHECK(err_code);
    The queries I have is
    1, Since I am increasing the tx buffer bandwidth from 3 to 6, do I need to make any changes in RAM(memory configuration) file ?
    2, How much memory should I increase for the soft device, when the tx buffer is increased from 3 to 6 .
    Currently I increase 24 bytes(since MTU is 23 bytes) for one buffer, then for 3 buffers 3*24=72.
    Since our product has two peripherals and so two connections, I make it 72+72 = 144.
    Please share your thoughts on this calculations.
    3, Do I need to check the buffer width for peripheral. For peripheral I assume tx buffer width to be 6 by default.
    Answers to your previous questions
    1) Do you get this reason at the central or peripheral? Do you get any events at the other device?
    [tpoly] - I get the BLE_HCI_CONNECTION_TIMEOUT(0x08) at the central.
    2) Did you set MAX_TIMEOUT_COUNT to a low value ?
    [tpoly] - I have set the MAX_TIMOUT_COUNT to 1, but still issue persists.
    Kind Regards,
    Thomas
  • Hi Sigurd,

    I tried to increase the tx buffer in 2 methods. The first method, i call the sd_ble_opt_set() during ble_stack_init()
    and in the second method i call sd_ble_opt_set(), when connection is made(BLE_GAP_EVT_ADV_REPORT). In our product we have a central and two peripherals, so for each connection the sd_ble_opt_set() is called.

    1, 1st method
    static void ble_stack_init(void)
    {
        uint32_t err_code;
      NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
      NRF_CLOCK->TASKS_HFCLKSTART = 1;
      uint32_t count = 0;
      do
      {
       count++;
       if(count>0xFFFF)
       {
        break;//timeout count in a while loop
       }
      }while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0); 
     
     
        nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;
        // Initialize the SoftDevice handler module.
        SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);
        ble_enable_params_t ble_enable_params;
        err_code = softdevice_enable_get_default_config(NRF_BLE_CENTRAL_LINK_COUNT,
                                                        NRF_BLE_PERIPHERAL_LINK_COUNT,
                                                        &ble_enable_params);
        APP_ERROR_CHECK(err_code);
        //Check the ram settings against the used number of links
        CHECK_RAM_START_ADDR(NRF_BLE_CENTRAL_LINK_COUNT, NRF_BLE_PERIPHERAL_LINK_COUNT);
        // Enable BLE stack.
    #if (NRF_SD_BLE_API_VERSION == 3)
        ble_enable_params.gatt_enable_params.att_mtu = NRF_BLE_GATT_MAX_MTU_SIZE;
    #endif
        err_code = softdevice_enable(&ble_enable_params);
        APP_ERROR_CHECK(err_code);
        // Register with the SoftDevice handler module for BLE events.
        err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
        APP_ERROR_CHECK(err_code);
        // Register with the SoftDevice handler module for System events.
        err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
        APP_ERROR_CHECK(err_code);
     /*Configure bandwidth */
     ble_opt_t ble_opt;
     ble_common_opt_conn_bw_t conn_bw;
     memset(&conn_bw, 0x00, sizeof(conn_bw));
     memset(&ble_opt, 0x00, sizeof(ble_opt));
     conn_bw.conn_bw.conn_bw_rx = BLE_CONN_BW_HIGH;
     conn_bw.conn_bw.conn_bw_tx = BLE_CONN_BW_HIGH;
     conn_bw.role = BLE_GAP_ROLE_CENTRAL;
     
     ble_opt.common_opt.conn_bw = conn_bw;
     
     uint32_t err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_BW, &ble_opt);
     APP_ERROR_CHECK(err_code);
    }
    2, 2nd method
    case BLE_GAP_EVT_ADV_REPORT:
     {
    ble_opt_t ble_opt;
    ble_common_opt_conn_bw_t conn_bw = { .role = BLE_GAP_ROLE_CENTRAL, .conn_bw = {
                          .conn_bw_rx = BLE_CONN_BW_HIGH, .conn_bw_tx = BLE_CONN_BW_HIGH } };
    ble_opt.common_opt.conn_bw = conn_bw;
    sd_ble_opt_set(BLE_COMMON_OPT_CONN_BW, &ble_opt);
     }

    With both the methods, i am not successfully able to connect to the peripherals.
    1, Is this the correct method to increase the tx buffer bandwidth ?
    2, Do we need to change the below parameters to increase tx/rx bandwidth
    #define HCI_MEM_POOL_ENABLED 0
    #define HCI_TX_BUF_SIZE 600
    #define HCI_RX_BUF_SIZE 600
    #define HCI_RX_BUF_QUEUE_SIZE 4
    Or does changing these parameters give the same result as setting through sd_ble_opt_set()
    3, Since I am increasing the tx buffer bandwidth from 3 to 6, do I need to make any changes in RAM(memory configuration) file ?
    4, How much memory should I increase for the soft device, when the tx buffer is increased from 3 to 6 .
    Currently I increase 24 bytes(since MTU is 23 bytes) for one buffer, then for 3 buffers 3*24=72.
    Since our product has two peripherals and so two connections, I make it 72+72 = 144.
    Please share your thoughts on this calculations.
    5, Do I need to check the buffer width for peripheral. For peripheral I assume tx buffer width to be 6 by default.
    Thanks,
    Thomas
  • 1, Is this the correct method to increase the tx buffer bandwidth ?

    Yes.

    2, Do we need to change the below parameters to increase tx/rx bandwidth

    No.

    3, Since I am increasing the tx buffer bandwidth from 3 to 6, do I need to make any changes in RAM(memory configuration) file ?

    If you are able to enable the SoftDevice, and sd_ble_opt_set() returns NRF_SUCCESS, then the SoftDevice already have enough RAM allocated.

    4, How much memory should I increase for the soft device, when the tx buffer is increased from 3 to 6 .

    When you set  ble_enable_params.common_enable_params.p_conn_bw_counts, before you enable the SoftDevice, the SoftDevice will calculate the RAM requirements, and sd_ble_enable() will return the amount of RAM the SoftDevice needs.

    5, Do I need to check the buffer width for peripheral. For peripheral I assume tx buffer width to be 6 by default.

    As described at this page, the default bandwidth for peripheral role is "BLE_CONN_BW_HIGH"

Reply
  • 1, Is this the correct method to increase the tx buffer bandwidth ?

    Yes.

    2, Do we need to change the below parameters to increase tx/rx bandwidth

    No.

    3, Since I am increasing the tx buffer bandwidth from 3 to 6, do I need to make any changes in RAM(memory configuration) file ?

    If you are able to enable the SoftDevice, and sd_ble_opt_set() returns NRF_SUCCESS, then the SoftDevice already have enough RAM allocated.

    4, How much memory should I increase for the soft device, when the tx buffer is increased from 3 to 6 .

    When you set  ble_enable_params.common_enable_params.p_conn_bw_counts, before you enable the SoftDevice, the SoftDevice will calculate the RAM requirements, and sd_ble_enable() will return the amount of RAM the SoftDevice needs.

    5, Do I need to check the buffer width for peripheral. For peripheral I assume tx buffer width to be 6 by default.

    As described at this page, the default bandwidth for peripheral role is "BLE_CONN_BW_HIGH"

Children
No Data
Related