This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BLE Multilink example + Throughput example

Hi there,

I'm trying to combine the BLE Multilink example with the Throughput example, with the hope that I can connect 1 Central to 2 Peripherals and get a high throughput.

In creating the AMTS instance, I'm a bit unsure of which ones have to be 2 instances and which one can share the function.

For example:
1) I created 2 instances of m_amts

nrf_ble_amts_t m_amts[2]

2) I only call NRF_SDH_BLE_OBSERVER once, since I assume I can reuse the m_amts_ble_obs and the handler nrf_ble_amts_on_ble_evt for both connection.

NRF_SDH_BLE_OBSERVER(m_amts_ble_obs, BLE_AMTS_BLE_OBSERVER_PRIO, nrf_ble_amts_on_ble_evt, NULL);

--> I'm thinking to put the condition inside nrf_ble_amts_on_ble_evt.  So conn_handle==0 will use m_amts[0] and conn_handle==1 will use m_amts[1]

3) I called nrf_ble_amts_init twice, but with different m_amts
nrf_ble_amts_init(&m_amts[0], amts_evt_handler, ...)

nrf_ble_amts_init(&m_amts[1], amts_evt_handler, ...)

4) I reuse the UUID for both, ie AMT_SERVICE_UUID, AMTS_CHAR_UUID, AMT_RCV_BYTES_CNT_CHAR_UUID are used for both m_amts[0] and m_amts[1]

So far I can connect to 2 Peripherals.  However, it fails in the "on_write" function inside nrf_ble_amts_on_ble_evt.


In this check

if ((p_evt_write->handle == p_ctx->amts_char_handles.cccd_handle) && (p_evt_wirte->len ==2)) {

//CCCD written, call the application event handler...

...

}

The 2nd connection always fails because for the 2nd connection the "p_evt_write->handle" is 13 or 14 and "p_ctx->amts_char_handles.cccd_handle" for the 2nd connection is 19 or 20.


Should I have created new set of services for the 2nd peripheral?  Or other things I can do for workaround this?


Thanks,
Cecylia

  • Hi Cecylia

    It should be fine for the two peripherals to have the same service sets. What have you done in terms of debugging? Are you able to see any error codes on the central side when trying to connect to the second peripheral. Debugging should give you a better idea of what exactly goes wrong when trying to connect to the second device. You'll need to find out what specifically causes the connection to fail.

    Best regards,

    Simon

  • Hi Simon,

    I've been using the IAR Segger debugger, and also Serial UART print for debug log for debugging these past few days.  


    I wonder if you can look at my log here and point me to where the issue is, or at least how to debug further?
    The first connection is always successful, but the 2nd connection fails to set Notifications enabled.  And it seems to be because the incoming p_ble_evt->evt.gatts_evt.params.write.handle value matches with the first instance instead of the second one.

    I'm thinking that if the Central is trying to establish connection to the 2nd peripheral, the incoming p_ble_evt's handler should match that of the 2nd one.  But, why is it still using the first connection's handler?

    Maybe it's clearer from the log.  This is the log from the Central

    >>>> Central waiting for Peripheral to connect.

    [00:00:00.396,484] <info> app: Multilink example started.
    [00:00:00.396,484] <info> app: Start scanning for device name PIVOT Yoga 000H1 and PIVOT Yoga 000S1.

    >>>> Powering on 1st Peripheral.  Establishing 1st Connection
    [00:00:08.990,966] <info> app: CONNECTION 0x0 established, starting DB discovery.
    [00:00:08.990,966] <info> app: Discovering GATT database...
    [00:00:08.991,027] <info> app: Sending PHY Update, 2 Mbps.
    [00:00:08.991,088] <info> app: Resume scanning
    [00:00:08.991,088] <info> app: Start scanning for device name PIVOT Yoga 000H1 and PIVOT Yoga 000S1.
    [00:00:09.202,453] <info> app: Conn:0 ATT MTU exchange completed. MTU set to 247 bytes.
    [00:00:09.232,482] <info> app: Conn:0 Data length updated to 251 bytes.
    [00:00:09.652,587] <error> AMTS: cwati on_write Conn:0x0 p_ble_evt's gatts_evt handle:14 len:2 m_amts[0].amts_char_handles.cccd_handle:14
    [00:00:09.652,587] <info> app: AMTS: Conn 0 Notifications enabled.
    [00:00:09.680,419] <info> app: Connection 0 PHY update accepted. PHY set to 2 Mbps.
    [00:00:09.832,275] <info> AMTC: cwati: AMT service discovered at peer. uuid:0x1525 rbc_handle:16 conn_handle:0
    [00:00:09.832,336] <info> app: AMTC: Conn 0 service discovered at peer.
    [00:00:09.892,395] <info> AMTC: cwati CCCD configured. Conn 0 Peer DB amt_cccd_handle:10056

    >>>> Powering on the 2nd Peripheral.  2nd Connection always fails to get Notifications enabled
    [00:00:26.318,664] <info> app: CONNECTION 0x1 established, starting DB discovery.
    [00:00:26.318,664] <info> app: Discovering GATT database...
    [00:00:26.318,725] <info> app: Sending PHY Update, 2 Mbps.
    [00:00:26.318,786] <info> app: CONNECTION COMPLETE. Got both connection. Will not scan.
    [00:00:26.452,514] <info> app: Conn:1 ATT MTU exchange completed. MTU set to 247 bytes.
    [00:00:26.512,573] <info> app: Conn:1 Data length updated to 251 bytes.
    [00:00:26.870,422] <info> app: Connection 1 PHY update accepted. PHY set to 2 Mbps.
    [00:00:26.872,497] <error> AMTS: cwati on_write Conn:0x1 p_ble_evt's gatts_evt handle:14 len:2 m_amts[1].amts_char_handles.cccd_handle:20

    >>>> Since the handlers don't match, the Notifications enabled will never get established.  If I remove this check then I do get the "Conn 1 Notifications enabled".  But, further communication from Central to 2nd Peripheral will fail with " AMTS: sd_ble_gatts_hvx() conn 1 failed: 0x3401"  So I think I need to resolve this properly

    [00:00:27.052,368] <info> AMTC: cwati: AMT service discovered at peer. uuid:0x1525 rbc_handle:16 conn_handle:1
    [00:00:27.052,368] <info> app: AMTC: Conn 1 service discovered at peer.
    [00:00:27.172,363] <info> AMTC: cwati CCCD configured. Conn 1 Peer DB amt_cccd_handle:11772

    Really appreciate your help!

    Thanks,
    Cecylia

  • Hi again

    It seems like you're only logging the <info> and <error> messages. Please try adding DEBUG to your preprocessor definitions in order to get more information in terms of logging (as explained in the link in my last reply). If you're able to see what error message the sd_ble_gatts_hvx() error returns you can take a look at the description of the possible errors here (from ble_gatts.h) :

    @retval ::NRF_SUCCESS Successfully queued a notification or indication for transmission, and optionally updated the attribute value.
     * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
     * @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true:
     *                                   - Invalid Connection State
     *                                   - Notifications and/or indications not enabled in the CCCD
     *                                   - An ATT_MTU exchange is ongoing
     * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
     * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
     * @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied. Only attributes added directly by the application are available to notify and indicate.
     * @retval ::BLE_ERROR_GATTS_INVALID_ATTR_TYPE Invalid attribute type(s) supplied, only characteristic values may be notified and indicated.
     * @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
     * @retval ::NRF_ERROR_FORBIDDEN The connection's current security level is lower than the one required by the write permissions of the CCCD associated with this characteristic.
     * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied.
     * @retval ::NRF_ERROR_BUSY For @ref BLE_GATT_HVX_INDICATION Procedure already in progress. Wait for a @ref BLE_GATTS_EVT_HVC event and retry.
     * @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value.
     * @retval ::NRF_ERROR_RESOURCES Too many notifications queued.
     *                               Wait for a @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event and retry.
     * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
     */

    One thought is that your service (on the central side) doesn't handle the connection handles correctly and isn't able to separate the two notification requests from each other.

    Best regards,

    Simon

  • Hi Simon,

    I added the verbosity level and I got more information.  As you predicted, I didn't seem to initialize the Central's Services properly.

    Here's how I initialized.  I tried to separate the functions for the 2 servers (m_amts) for debugging.

    // NRF_SDH_BLE_CENTRAL_LINK_COUNT is 2
    
    NRF_BLE_QWRS_DEF(m_qwr_array_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT);
    NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
    BLE_DB_DISCOVERY_ARRAY_DEF(m_ble_db_discovery, NRF_SDH_BLE_CENTRAL_LINK_COUNT); /**< Database discovery module instances. */
    NRF_BLE_SCAN_DEF(m_scan); /**< Scanning Module instance. */
    NRF_BLE_GQ_DEF(m_ble_gatt_queue, /**< BLE GATT Queue instance. */
    NRF_SDH_BLE_CENTRAL_LINK_COUNT,
    NRF_BLE_GQ_QUEUE_SIZE);
    
    // Here's how I initialized m_amts
    nrf_ble_amts_t m_amts[NRF_SDH_BLE_CENTRAL_LINK_COUNT];
    NRF_SDH_BLE_OBSERVER(m_amts_ble_obs, BLE_AMTS_BLE_OBSERVER_PRIO, nrf_ble_amts_on_ble_evt, &m_amts[0]);
    NRF_SDH_BLE_OBSERVER(m_amts_ble_obs1, BLE_AMTS_BLE_OBSERVER_PRIO, nrf_ble_amts_on_ble_evt1, &m_amts[1]);
    
    ...
    
    // And then here's the server init
    static void server_init(void)
    {
        qwr_init();
    
        for (uint8_t qq = 0; qq < NRF_SDH_BLE_CENTRAL_LINK_COUNT; qq++) {
            nrf_ble_amts_init(&m_amts[qq], amts_evt_handler, 244 /*sizeof(client_to_marc_t)*/,
                            sizeof(marc_to_client_t));
            m_amts[qq].conn_handle = BLE_CONN_HANDLE_INVALID;
        }
    }

    When I power on the 1st peripheral board and the first connection happens, both nrf_ble_amts_on_ble_evt and nrf_ble_amts_on_ble_evt1 are called and m_amts[0] and m_amts[1] are updated.  I.e., both conn_handle are now set to 0.

    Then when I power on the 2nd board, both m_amts[0] and m_amts[1]'s connection handles are set to 1. 

    I believe this is wrong.  I think the first connection should only set the conn_handle for the first server, so if done correctly they should end up as:
    m_amts[0].conn_handle = 0
    m_amts[1].conn_handle = 1

    Instead of what I have now, where after the 2nd connection,both are set to 1.


    So, my question is, when an event happen, and both 

    void nrf_ble_amts_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)

    and

    void nrf_ble_amts_on_ble_evt1(ble_evt_t const * p_ble_evt, void * p_context)

    are called, can I put a condition inside these functions so that based on the information inside p_ble_evt I can know if it should be handled by the first or the 2nd connection? 

    Or should the fix be way earlier, ie during the init, such that BLE events for the 1st connection should not even call the 2nd handler?

    PS: I didn't get much information from chasing the "sd_ble_gatts_hvx".  

    Thanks a lot,
    Cecylia

  • Hello , any thoughts? :) help, please...

Related