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);

Parents Reply Children
  • 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?

  • I get zero HVN_TX_COMPLETE unless I omit the loop and just ignore the return error. Perhaps the interrupt handling queue is full and interrupts from the radio can't be handled or something? I'm not sure of the detail of how things work in that respect, just guessing.

  • Are you running the loop at an interrupt context?  It could sound like thee loop is blocking the SD events from being handled in the application. I think this could happen if the loop is running in an interrupt context with priority 6.

    Best regards

    Bjørn

Related