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

How to deal with [NRF_ERROR_RESOURCES]

Hello
If "NRF_ERROR_RESOURCES" occurs, does the set transmission data not be transmitted? Will it be sent partway? I do not know either.
If "NRF_ERROR_RESOURCES" is returned when executing [ble_nus_data_send ()], can I freeze the time and execute [ble_nus_data_send ()] again?
Thanking you in advance
 
Parents
  • Hi,

    If ble_nus_data_send() returns NRF_ERROR_RESOURCES, it means that too many notifications are queued. All the BLE buffers in the SoftDevice are full, and you can not upload any more notifications until the BLE_GATTS_EVT_HVN_TX_COMPLETE event occurs. You will need to call ble_nus_data_send() again when that happens.

    You have 2 options, either call ble_nus_data_send() in a loop until the function returns NRF_SUCCESS, or wait for the BLE_GATTS_EVT_HVN_TX_COMPLETE and then send the packet. Waiting in a loop is how it’s implemented in ble_app_uart, but there is a small bug in SDK 15.0, where the wrong error-code is tested. NRF_ERROR_BUSY is tested, but it should be NRF_ERROR_RESOURCES.

    Here is the uart_event_handle() for SDK 15.0 with the bug fixed:

    void uart_event_handle(app_uart_evt_t * p_event)
    {
        static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
        static uint8_t index = 0;
        uint32_t       err_code;
    
        switch (p_event->evt_type)
        {
            case APP_UART_DATA_READY:
                UNUSED_VARIABLE(app_uart_get(&data_array[index]));
                index++;
    
                if ((data_array[index - 1] == '\n') || (index >= (m_ble_nus_max_data_len)))
                {
                    NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                    NRF_LOG_HEXDUMP_DEBUG(data_array, index);
    
                    do
                    {
                        uint16_t length = (uint16_t)index;
                        err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
                        if ( (err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_RESOURCES) &&
                             (err_code != NRF_ERROR_NOT_FOUND) )
                        {
                            APP_ERROR_CHECK(err_code);
                        }
                    } while (err_code == NRF_ERROR_RESOURCES);
    
                    index = 0;
                }
                break;
    
            case APP_UART_COMMUNICATION_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_communication);
                break;
    
            case APP_UART_FIFO_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_code);
                break;
    
            default:
                break;
        }
    }

  • What if I am sending packet at a faster rate than I'm getting BLE_GATTS_EVT_HVN_TX_COMPLETE  event. This will result in lost of packets right ? Is there any work around for this, except increasing the softdevice buffer tx size ?

  • Hi Haaris,

    If you get NRF_ERROR_RESOURCES from sd_ble_gatts_hvx, the packet is not sent. 

    Also note that BLE_GATTS_EVT_HVN_TX_COMPLETE  event contains a count field that could be higher than 1. So you could e.g. send 3 packets calling sd_ble_gatts_hvx() 3 times, and get 1 TX complete event with count=3.

    If you get NRF_ERROR_RESOURCES  from sd_ble_gatts_hvx(), you could try to increase the NRF_SDH_BLE_GAP_EVENT_LENGTH in sdk_config.h, and depending on how many packets per connection interval the other side of the BLE link supports, you could also try to decrease the connection interval(MIN_CONN_INTERVAL/MAX_CONN_INTERVAL).

  • Hey Sigurd,

    Yes I've tried counting the number of packets being sent using 

    packet_count = p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count;

    in the BLE_GATTS_EVT_HVN_TX_COMPLETE  event. That count always shows as 1, so the problem is my central device only supports one packet and a connection interval of minimum 11.25ms.

    What's weird is another central device (different mobile manufacturer) also supports one packet but has minimum connection interval as 7.5ms , "NRF_ERROR_RESOURCES" error doesn't occur there. What is think is the connection interval shouldn't matter because for both the central devices I was setting the connection interval as 15ms. What could possibly be the reason for this ?

  • Hi Haaris,

    It could be that one of the phones support more packets per connection interval than the other phone. Note that the event BLE_GATTS_EVT_HVN_TX_COMPLETE can be generated more than one time during the connection interval. The phones could also support different ATT MTU sizes and data length extension sizes( on-air packet size). These are all factors that affects the throughput. See this page for more information.

Reply Children
  • I'm reading out the variable 

     p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count;
    in BLE_GATTS_EVT_HVN_TX_COMPLETE event, doesn't that variable shows you how many packets are sent in an overall connection event? If not then how do I keep count of the numbers of packets that are sent.

    I couldn't implement DLE because the central devices use BLE v4.1.  I'm able to increase the MAX_ATT_MTU to 247, but it's of no use because as soon I increase the data size to above 20 it gives me "NRF_ERROR_RESOURCES" error.

    I recently tested with one plus 6 mobile which supports BLE v5 and even that shows me one packet. 

    What do you think I'm doing wrong here

  • Hi,

    doesn't that variable shows you how many packets are sent in an overall connection event?

    No, you could get that event several times during the connection event. E.g. if you send 4 packets in a connection event, you could get the tx-complete event first with count=1 and then again with count=3.

    If not then how do I keep count of the numbers of packets that are sent.

    The easiest way is just to check nRFSniffer to see what is happening on-air.

Related