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

sd_ble_gatts_hvx() in softdevice event

Hello.
I have one multirole device (device A) and three peripherals (devices B, C, D).
Device A connects to devices B, C, and D as a central role, and connects to the phone as a peripheral role.
Device A transfers the connection status of devices B, C and D to the phone.
But there is a problem.
When devices B, C and D disconnect from device A at the same time, disconnect event occurs 3 times in device A.
In the disconnect event, sd_ble_gatts_hvx() is called and sometimes NRF_ERROR_RESOURCES is acquired. In this case, while() waits until the BLE_GATTS_EVT_HVN_TX_COMPLETE event occurs, it retransmits.

It has been confirmed that this method is working properly. When sd_ble_gatts_hvx() is called from the normal routine instead of the event routine, the resend processing is performed normally using this method.
However, when calling sd_ble_gatts_hvx() from the softdevice event (disconnect event), the BLE_GATTS_EVT_HVN_TX_COMPLETE event is blocked and loops forever.

The cause is that BLE_GAP_EVT_DISCONNECTED and BLE_GATTS_EVT_HVN_TX_COMPLETE are the same event handler, so we recognize that the resending process when NRF_ERROR_RESOURCES occurs cannot be performed. (Referenced below: devzone.nordicsemi.com/.../153271

In the disconnect event, sd_ble_gatts_hvx() is not called only by performing a flag operation, but it is modified to check the flag in the normal routine and call sd_ble_gatts_hvx().

I have a question.
1. Is it appropriate to call sd_ble_gatts_hvx(), sd_ble_gatts_write(), etc. in the softdevice event (disconnect etc.)? (When resending is performed when NRF_ERROR_RESOURCES is acquired)

2. I increased NRF_SDH_BLE_GAP_EVENT_LENGTH to suppress the occurrence of NRF_ERROR_RESOURCES. Is there a way to actually know the number of tx_buffer?

3. I can't find the location updating hvn_tx_queue_size in ble_gatts_conn_cfg_t. It seems that BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT is not referenced either. Do these have any meaning?

Thank you.

  • Hi,

    When devices B, C and D disconnect from device A at the same time, disconnect event occurs 3 times in device A.

     Correct, that is as expected, you can check the connection handle to see what device that is causing each of these 3 events.

    p_ble_evt->evt.gap_evt.conn_handle
     

    1. Is it appropriate to call sd_ble_gatts_hvx(), sd_ble_gatts_write(), etc. in the softdevice event (disconnect etc.)?

     No,the link has been disconnected. The data will not be sent to the central, and you will not get BLE_GATTS_EVT_HVN_TX_COMPLETE for these packets.

    2. I increased NRF_SDH_BLE_GAP_EVENT_LENGTH to suppress the occurrence of NRF_ERROR_RESOURCES.

     Let's say that you are in a connection, continuously sending data from your peripheral. Then the central suddenly turns off. In this case, the disconnect event will not happen before the supervision timeout(typically 4 seconds). In this 4 seconds window, calling sd_ble_gatts_hvx() will fill-up the internal tx queue, but the packets will not be sent since the central is turned off. You can increase the queue size, indirectly by increasing NRF_SDH_BLE_GAP_EVENT_LENGTH, but in the end, these packets that are queued up will not be sent.

    Is there a way to actually know the number of tx_buffer?

    The hvn_tx_queue_size will be indirectly configured based on NRF_SDH_BLE_GAP_DATA_LENGTH and NRF_SDH_BLE_GAP_EVENT_LENGTH values.There is no API to read the buffer size.

    3. I can't find the location updating hvn_tx_queue_size in ble_gatts_conn_cfg_t.

    Snippet: 

    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        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 = 50;
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);
    
    
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }

    https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s132.api.v7.0.1%2Fstructble__gatts__conn__cfg__t.html

  • No,the link has been disconnected. The data will not be sent to the central, and you will not get BLE_GATTS_EVT_HVN_TX_COMPLETE for these packets.

    I am wondering if it is okay to call sd_ble_gatts_hvx() in a softdevice event such as a disconnect event.
    For example, when device A disconnects from devices B, C, and D, device A executes sd_ble_gatts_hvx() within the disconnect event (three times) for the phone.
    If sd_ble_gatts_hvx() returns NRF_ERROR_RESOURCES, and wait in a while loop until BLE_GATTS_EVT_HVN_TX_COMPLETE is called, it will be in a wait state with disconnect event, so BLE_GATTS_EVT_HVN_TX_COMPLETE will not occur and it will be a permanent loop.
    So I thought the following, is it correct?

    1. In the case of calling sd_ble_gatts_hvx() from within the softdevice event, the process when NRF_ERROR_RESOURCES occurs does not wait for BLE_GATTS_EVT_HVN_TX_COMPLETE in the while() loop, but continues calling sd_ble_gatts_hvx() until NRF_SUCCESS returns.

    2. Control flags in the softdevice event. Check the flag in the normal routine and execute sd_ble_gatts_hvx().

    Thank you.

  • suke said:
    For example, when device A disconnects from devices B, C, and D, device A executes sd_ble_gatts_hvx() within the disconnect event (three times) for the phone.

     Yes, that is ok.

    suke said:
    If sd_ble_gatts_hvx() returns NRF_ERROR_RESOURCES, and wait in a while loop until BLE_GATTS_EVT_HVN_TX_COMPLETE is called, it will be in a wait state with disconnect event, so BLE_GATTS_EVT_HVN_TX_COMPLETE will not occur and it will be a permanent loop.

     Yes, you are blocking the TX complete event to be sent to the application when you are sending(sd_ble_gatts_hvx) in the disconnect event.

    suke said:
    So I thought the following, is it correct?

     Both approaches will work. But if you are sending a lot of data, then I would go for option 2. For option 1, it should maybe have a "timeout" implemented, that allows you to break out of the while-loop after x amount of time.

Related