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
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;
if ((data_array[index - 1] == '\n') || (index >= (m_ble_nus_max_data_len)))
NRF_LOG_DEBUG("Ready to send data over BLE NUS");
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) )
} while (err_code == NRF_ERROR_RESOURCES);
index = 0;
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 ?
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).
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 ?
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.