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

Random disconnection when messages are sent from central to peripheral at high rate.

hello there!

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.

From the stack collected at the point of disconnection, the reason is BLE_HCI_CONNECTION_TIMEOUT and this happens because the supervision timeout is hit (no packets from the peer is received in x seconds).

The stack traces were collected both at remote(central) and peripheral  and both points to BLE_HCI_CONNECTION_TIMEOUT. Attached the stack traces(Remote and wheel).

Below are the BLE connection interval and supervision timeout

#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. */

#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}

 

It would be great if someone can point me with the correct parameters or guide how to debug the issue. Does BLE have a queue limit, since disconnection happens when messages are sent at high rate. If there is queue limit, how do I change it ?

Kind Regards,

Thomas

Parents
  • Hi Edwin,
    Thanks for your inputs.

    Summarizing the issue, tx buffers are getting full when messages are sent at high rate and it results in a disconnection event.
    1, 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, Please suggest a way so that irrespective the ACK is received for the messages, the buffer could be cleared.
    3, Does configuring as BLE_GATT_HVX_NOTIFICATION means buffers are cleared and no ACKS are needed to clear the tx buffer.
    Request you to give answers to the above queries.
    Thanks,
    Thomas
  • 1: no

    2: not possible to clear the buffer.

    3: no.

    What SDK version do you use?

    When a message is queued it is not possible to remove it before it is ACKed. 

    You can wait for the TX_COMPLETE event. The name of this event depends on the SDK version that you use. Therefore I keep asking what SDK version you use. What SDK version do you use?

    You can use these events to know when you have some free space in the buffer.

    Note that if you use indication instead of notification, the message has to be ACKed in the application layer of the receiver (central). If this is not done, the buffer will not be cleared. 

  • Hi Edwin,
    Thanks for the resposnses.
    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
  • Hello Thomas,

    I believe what you really should be changing is the gatt_init() function (typically called in the main() function, such as it is done in the ble_app_uart example.

    void gatt_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); // NRF_SDH_BLE_GATT_MAX_MTU_SIZE is defined as 247 in sdk_config.h
        APP_ERROR_CHECK(err_code);
    }

    On second thought, this is how you do it in SDK15.2.0. In SDK12.3.0, this was not yet supported, and isn't really supported at all in the S130 softdevice.

    regardless, changing the queue size shouldn't affect your project. It doesn't change the data going over the air, and it doesn't affect disconnections.

    Can you please give the nRF Sniffer a try. It is Alpha Omega for BLE development debugging. Let me know when you have a sniffer trace, or if you have any issues with the sniffer.

  • Thanks Edwin for the responses.

    I am using SDK 12.3 and S130.  I am able to see following code in my project

    /* GATT Module init. */
    void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
        APP_ERROR_CHECK(err_code);
    }

    So I think, I could add 

    err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); // NRF_SDH_BLE_GATT_MAX_MTU_SIZE is defined as 247 in sdk_config.h
    APP_ERROR_CHECK(err_code);

    But the above call increases the MTU size. Does it increase the tx buffer width.

    1, Is the tx buffer width and MTU size the same or is it related ?

    2, When a message is sent from central to peripheral and no ACK is received from peripheral within the supervision timeout, do we get BLE_GAP_EVT_DISCONNECTED event or do we get any other BLE_GAP_EVT_TIMEOUT/BLE_GATTC_EVT_TIMEOUT ?

    3, Yes, tried with sniffer, but could not get it follow the connection. In the sniffer could see traces of connection events but failed to see any events when data was sent.

    Kind Regards,

    Thomas

  • Hi Edwin,

    Can you help us with these queries also

    1, 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()
    2, Since I am increasing the tx buffer bandwidth from 3 to 6, do I need to make any changes in RAM(memory configuration) file ?
    3, 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.
    4, Do I need to check the buffer width for peripheral. For peripheral I assume tx buffer width to be 6 by default.
    Kind Regards,
    Thomas
  • Hello Thomas, 

    Sorry if I wasn't clear. It is not possible to increase the MTU size on the nRF51 series, because the softdevices for nRF51 does not support longer MTU sizes than 23.

    1.1 Yes and no. MTU size is the actual message size that is transmitted on air. buffer size is how much the softdevice can store.

    1.2 If no ACK is ever received, you will get a disconnect. The softdevice will keep re-transmitting until the message is ACKed.

    1.3 Is your connection encrypted? If it is, you can enter the out of band passkey in wireshark. If you don't use a passkey, but just works bonding, then you should be able to sniff the connection if the sniffer is listening  while they exchange the keys. So if you delete the bonding information on both devices, then you should be able to sniff it.

    2.1. The HCI buffer sizes, this is not related, since you are not using HCI.

    2.2 exactly where do you increase this buffer from 3 to 6? The log should always tell you what your RAM memory configurations should be.

    2.3 Check the log.

    2.4 not necessarily. Since the MTU isn't increased when you use the nRF51, the peripheral will get events on all received messages.

    I really don't think that the buffer sizes is your cause of disconnection. You shouldn't focus at the buffer sizes at this point in time, if you want to find the cause of your disconnections. Focus on the sniffer trace. Try to sniff with encryption. 

    Is it possible to send the sniffer logs?

Reply
  • Hello Thomas, 

    Sorry if I wasn't clear. It is not possible to increase the MTU size on the nRF51 series, because the softdevices for nRF51 does not support longer MTU sizes than 23.

    1.1 Yes and no. MTU size is the actual message size that is transmitted on air. buffer size is how much the softdevice can store.

    1.2 If no ACK is ever received, you will get a disconnect. The softdevice will keep re-transmitting until the message is ACKed.

    1.3 Is your connection encrypted? If it is, you can enter the out of band passkey in wireshark. If you don't use a passkey, but just works bonding, then you should be able to sniff the connection if the sniffer is listening  while they exchange the keys. So if you delete the bonding information on both devices, then you should be able to sniff it.

    2.1. The HCI buffer sizes, this is not related, since you are not using HCI.

    2.2 exactly where do you increase this buffer from 3 to 6? The log should always tell you what your RAM memory configurations should be.

    2.3 Check the log.

    2.4 not necessarily. Since the MTU isn't increased when you use the nRF51, the peripheral will get events on all received messages.

    I really don't think that the buffer sizes is your cause of disconnection. You shouldn't focus at the buffer sizes at this point in time, if you want to find the cause of your disconnections. Focus on the sniffer trace. Try to sniff with encryption. 

    Is it possible to send the sniffer logs?

Children
No Data
Related