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

ble_nus_data_send() can not send large data from BLE_GAP_EVT_CONN_PARAM_UPDATE event

Hi,

In short, my problem is that my code works when I execute it inside one event handler, but doesn't work inside another event handler, and I don't understand why it fails to succeed.

This is what I want to do: I have a central and a peripheral (both are nrf52840's with SD s140, and SDK 17.0.2) and I want the peripheral to send a large amount of data to the central. I want the data sending to happen automatically, after the devices have negotiated the following parameters:

  • 7.5 ms connection interval
  • DLE extension and 247 byte MTU
  • 2 M PHY

I have taken the ble_app_uart example as my project base. First, I modified the example's uart_event_handle() so that when my peripheral receives an "a", a uint8_t array with length 244 is generated and sent by the function ble_nus_data_send(). Actually, to simulate a large amount of data, I send the same array 1000 times from within a loop like so:

if (command == 'a')
            {
                uint8_t byte_array[244];
                length = 244;

                generate_array(byte_array, length);
            }
            
            for (int i=0; i<1000; i++){
              do
                  {
                      err_code = ble_nus_data_send(&m_nus, byte_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);
            }

The above code works fine, I guess, since the central gets all the packets. Whenever the err_code becomes NRF_ERROR_RESOURCES, the while loop tries to execute the message sending, until the resources get freed up. So far so good.

However, now I want to eliminate the keyboard interaction. I want the peripheral to start sending the messages as soon as the aforementioned connection parameters have been negotiated. Therefore, I place the same code in the ble_evt_handler() function, in the BLE_GAP_EVT_CONN_PARAM_UPDATE event, like so:

case BLE_GAP_EVT_CONN_PARAM_UPDATE:
            NRF_LOG_INFO("Conn params updated");
            NRF_LOG_INFO("updated:min_conn_interval: %i*1.25 ms", p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.min_conn_interval);
            NRF_LOG_INFO("updated:max_conn_interval: %i*1.25 ms", p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.max_conn_interval);
            
            ble_gap_conn_params_t conn_interval = p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params;

            if (conn_interval.max_conn_interval == MAX_CONN_INTERVAL)
            {
                uint16_t length = 244; //byte_array is already generated in main

                for (int i=0; i<1000; i++)
                {
                  do
                    {
                        err_code = ble_nus_data_send(&m_nus, byte_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);
                }
            }
            break;

What happens during execution is that the ble_nus_data_send() function starts sending the messages when the 7.5 ms connection interval has been negotiated, but after the 3rd message it returns NRF_ERROR_RESOURCES and the rest of the messages never get sent. However, the central and peripheral remain in connection, sending empty packets to each other, according to the nRF Sniffer:

Sniffer output

Please help me understand what's wrong with the code! Thanks!

Related