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

nRF52840 and s340: can BLE and ANT+ be used to send data at the same time?

I'm experimenting with multiprotocol support on a PCA10056 (nRF52840) and the S340 softdevice. I need to use BLE and ANT+ at the same time, sending data to either ANT+ or BLE sport receivers.

I'm using SDK15.3 and the S340 6.1.1 softdevice

I have successfully tested the ANT+ Bike Speed and Cadence Tx example (and adapted it to my needs), as well as the equivalent BLE example. I also tested the multiprotocol hrm relay example (receive ANT+ heart rate monitor data and relay it via BLE).

I'm now trying to combine the ANT+ speed and cadence sensor example with the BLE one. I have managed to have a project I can successfully compile and use either ANT+ or BLE independently. If I try to enable them at the same time, the ANT+ portion starts sending data as soon as the SDK board is powered/debug started. But as soon as I try to connect via BLE, I get an error:

[00:00:10.164,154] <debug> nrf_ble_gatt: Peer on connection 0x0 requested a data length of 27 bytes.
[00:00:10.164,184] <debug> nrf_ble_gatt: Updating data length to 27 on connection 0x0.
[00:00:10.209,075] <debug> nrf_ble_gatt: Data length updated to 27 on connection 0x0.
[00:00:10.209,106] <debug> nrf_ble_gatt: max_rx_octets: 27
[00:00:10.209,106] <debug> nrf_ble_gatt: max_tx_octets: 27
[00:00:10.209,106] <debug> nrf_ble_gatt: max_rx_time: 328
[00:00:10.209,136] <debug> nrf_ble_gatt: max_tx_time: 2120
[00:00:10.344,146] <debug> app: PHY update request.
[00:00:10.344,177] <debug> app: PHY update request.
[00:00:10.344,573] <error> app: ERROR 17 [NRF_ERROR_BUSY] at C:\Nordic\Projects\AntBLE_CSC\core\main.c:851 PC at: 0x0003AAA5
[00:00:10.344,909] <error> app: End of error report

I tried reading the SoftDevice Specification S332 SoftDevice (can't find an equivalent for S340) and the S140 Concurrent multiprotocol implementation using the Radio Timeslot API (once agian, can't find the S340 equivalent), but I'm not sure I understand how to use it

The HRM relay multiprotocol example seems to be able to open both a ANT and BLE radio at the same time with no error, but I can't find anything different in the softdevice calls compared to what I'm doing.

I did add the following, but doesn't seem to help

// <o> APP_ANT_OBSERVER_PRIO - Application ANT event observer priority. 
#ifndef APP_ANT_OBSERVER_PRIO
#define APP_ANT_OBSERVER_PRIO 1
#endif

// <o> APP_BLE_OBSERVER_PRIO - Application BLE event observer priority. 
#ifndef APP_BLE_OBSERVER_PRIO
#define APP_BLE_OBSERVER_PRIO 0
#endif

// <o> APP_SHUTDOWN_HANDLER_PRIORITY - Application shutdown observer priority. 
#ifndef APP_SHUTDOWN_HANDLER_PRIORITY
#define APP_SHUTDOWN_HANDLER_PRIORITY 1
#endif

Can anyone help with pointers on how to troubleshoot or handle BLE and ANT+ sending data in sequence (the timing of the data packet is not as time-critical, since each packet carries its own timing information, so the receiver will always be able to correctly interpret the packets)

Parents
  • Quick update. I temporarily worked around the issue adding

    while (sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys) != NRF_SUCCESS) 
    {}

    in ble_evt_handler(), as per below. I'm not sure, though, if it's an acceptable workaround, and the ble_ant_app_hrm_pca10056_s340 example doesn't seem to need this workaround (granted, it looks as if in that case the ANT+ stack is not actively used while waiting for the BLE connection)

            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                while (sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys) != NRF_SUCCESS)
                {}
            } break;

    After this hack, everything seems to work well, and I can receive BLE and ANT+ data at the same time

    Any recommendations on how safe the hack is? I'm still struggling to understand how BLE and ANT+ coexist in S340

  • Hi,

    NRF_ERROR_BUSY is not really a critical error that you need to assert on. It basically means busy, try again later (for instance due to an on-going procedure that need to complete before you can execute this one). I don't know which softdevice call you are trying that is returning this error, but my suggestion is to for instance try again in a while loop (as it seems you are doing) or start an app_timer single shot that try again for instance in 100ms.

    Best regards,
    Kenneth

  • Thanks Kenneth,

    I was using the same code as in the ble_ant_app_hrm_pca10056_s340 example, as per below

    Since all the examples I saw were asserting on NRF_ERROR_BUSY returned by sd_ble_gap_phy_update(), I was not sure if it was safe to retry.

    I will implement appropriate retry logic, thanks for confirming that what I'm going is safe (also, re-reading more of the softdevice documentation, and the softdevice is already written to allow BLE and ANT+ to coexist, the cocnurrent multiprotocol/radio timeslot is only for proprietary implementations)

    Do you know why there is no S340 documentation, outside of the list of APIs? All other softdevices are much better documented

    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected");
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected");
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }

Reply
  • Thanks Kenneth,

    I was using the same code as in the ble_ant_app_hrm_pca10056_s340 example, as per below

    Since all the examples I saw were asserting on NRF_ERROR_BUSY returned by sd_ble_gap_phy_update(), I was not sure if it was safe to retry.

    I will implement appropriate retry logic, thanks for confirming that what I'm going is safe (also, re-reading more of the softdevice documentation, and the softdevice is already written to allow BLE and ANT+ to coexist, the cocnurrent multiprotocol/radio timeslot is only for proprietary implementations)

    Do you know why there is no S340 documentation, outside of the list of APIs? All other softdevices are much better documented

    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected");
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected");
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }

Children
No Data
Related