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

sd_ble_gatts_hvx NRF_ERROR_RESOURCES in do while loop

After a few notifications in short succession this code will reliably get stuck in an infinite loop (15.2.0). Can sd_ble_gatts_hvx not be used in this way? Do you have to wait for BLE_GATTS_EVT_HVN_TX_COMPLETE? This makes things more difficult as you then have to queue the notifications in the application.

do {
    err_code = sd_ble_gatts_hvx(conn_handle, &params);
} while (err_code == NRF_ERROR_RESOURCES);

  • Hi Nick, 

    sd_ble_gatts_hvx() is a synchronous API call so it should return NRF_ERROR_RESOURCES as long as the notification queue is full and should not halt if called in a loop. 

    Yes, the recommended and most power-efficient approach is to call sd_ble_gatts_hvx untill you get the NRF_ERROR_RESOURCES return code and then wait until you get the BLE_GATTS_EVT_HVN_TX_COMPLETE before you call sd_ble_gatts_hvx again. 

    Note: The number of Handle Value Notifications that can be queued is configured by ble_gatts_conn_cfg_t::hvn_tx_queue_size.

    Best regards

    Bjørn 

  • Thanks for your response but the code does not halt on sd_ble_gatts_hvx, just the loop continues indefinitely i.e. sd_ble_gatts_hvx continues to return NRF_ERROR_RESOURCES forever. So perhaps the function does not work correctly, as I assume it shouldn't return NRF_ERROR_RESOURCES forever as the queue will become free at some point.

  • Ok, and you're not getting the BLE_GATTS_EVT_HVN_TX_COMPLETE either? Are you able to capture a sniffer trace of the on air packets with the nRF Sniffer v2 ? It would be interesting to see if the notification packets are actually sent or not. 

    Btw, which SDK and SoftDevice version are you using? And which IC?

    Best regards

    Bjørn 

  • SDK 15.2.0 SoftDevice S132 6.1.0. on NRF52832

    It seems calling either sd_ble_gatts_hvx or nrf_pwr_mgmt_run (as below) in a loop prevents HVN_TX_COMPLETE occurring. If I use either to attempt to wait for the HVN_TX_COMPLETE it never occurs and the loop gets stuck.

    static volatile bool m_notifications_queue_full = false;
    
    void ble_blister_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ble_blister_t * p_blister = (ble_blister_t *)p_context;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GATTS_EVT_HVN_TX_COMPLETE:
                NRF_LOG_DEBUG("HVN_TX_COMPLETE: %d", p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count);
                m_notifications_queue_full = false;
                break;
            default:
                break;
        }
    }
    
    void send() {
    do {
    err_code = sd_ble_gatts_hvx(conn_handle, &params);
    if(err_code == NRF_ERROR_RESOURCES) {
        NRF_LOG_WARNING("Queue full, waiting");
        NRF_LOG_FLUSH();
        m_notifications_queue_full = true;
        while(m_notifications_queue_full) {
            nrf_pwr_mgmt_run();
        }
    }
    } while (err_code == NRF_ERROR_RESOURCES);
    }

    5 notifications are sent and received by the connected device. The firmware gets stuck sending the 6th.

    I should probably note that 1 notification is being sent on GPIO interrupt, and this is occurring when many interrupts occur at the same time.

  • Hmm, calling nrf_pwr_mgmt_run to sleep the device while waiting for the HVN_TX_COMPLETE event should not lead to the behaviour you're describing. WHen you call send, how many HVN_TX_COMPLETE events do you get before the code is deadlocked? And which .hvn_tx_complete.count is passed in the event?

Related