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

send packets continuously in ble_app_uart example

I have to send packages continuously; How can I get feedback on the success of transmission before sending the next package? Which event should I use? and in what callback function?

I'm using SDK 15 and softdevice 6.0. The event BLE_EVT_TX_COMPLETE is missing in ble.h

Thanks

  • Hi,

     

    You can use the BLE_GATTS_EVT_HVN_TX_COMPLETE event to know that a Handle Value Notification transmission has completed. (This is allready used in the NUS implementation, ble_nus.c). Note that you can queue more than one, but you will get NRF_ERROR_RESOURCES returned when there are too many in the queue. In that case, you have to wait for the BLE_GATTS_EVT_HVN_TX_COMPLETE event before you call ble_nus_data_send() (or sd_ble_gatts_hvx()) again.

  • Hello, I wait the event BLE_GATTS_EVT_HVN_TX_COMPLETE before the next transmission with ble_nus_data_send(). Please see the while loop in the main:

        // Enter main loop.
        for (;;)
        {
            //idle_state_handle();
    
            if ((flag_connected==1)&&(flag_transmitted==1))
            //if (flag_connected==1)
    	{
              flag_transmitted = 0;
              
              //nrf_delay_ms(100);
              nrf_gpio_pin_toggle(OUT_COMP);
              SendData();
    
              num_packets++;
                                               
    	}
    
        }

    the flag_transmitted is asserted in following function handler:

    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
        int break_point;
        char debug_str[10] = {0};
    
        if (p_evt->type == BLE_NUS_EVT_RX_DATA)
        {
            uint32_t err_code;
    
            NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
            NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    
            break_point = 25;
    
            // **************** ha ricevuto i dati su BLE RX, commentato il blocco inferiore che li rigirava sulla UART fisica
            /*
            for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
            {
                do
                {
                    err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
                    if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
                    {
                        NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_BUSY);
            }
            if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
            {
                while (app_uart_put('\n') == NRF_ERROR_BUSY);
            }
            */
        }
        else if (p_evt->type == BLE_NUS_EVT_TX_RDY)
        {
            flag_transmitted = 1;
    
            NRF_LOG_INFO("TX OK");
            //sprintf(debug_str, "numbers of packets = %d", num_packets);
            //NRF_LOG_INFO("%s",(uint32_t)debug_str);
        }
    
    }

    then, at the connection, the continuous transmission starts. About 6000 packages can be transmitted  before the software goes to the function "__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)" with error 19 "NRF_ERROR_RESOURCES".

    Every transmission I toggle a pin, please see the attached image of the monitoring of pin with the scope. Every change of level is a transmission

    A scope division i 5 ms and this is a very strange behaviour because I set the connction interval at 15 ms.

    What do you think?

  • Hello,

    Einar is currently out of office, so I have taken this case, and will follow it up.

     

    I see that the BLE_NUS_EVT_TX_RDY is called on the BLE_EVT_TX_COMPLETE event, so it should be fine.

     

    What does your SendData() function look like?

     

    Can you please try the following:

    define "DEBUG" in your preprocessor defines, and disable optimization (set it to -O0). Then you should be able to find out what function that returns NRF_ERROR_RESOURCES. Set a breakpoint on line 90 in app_error_weak.c, and it should break there when you receive the error. Check what file name and line number that is stored in p_info. Is this within your SendData() function?

     

    Best regards,

    Edvin

  • Hello,

    following the function SendData()

    void SendData(void)
    {
    
        static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
        static uint8_t index = 0;
        uint32_t       err_code;
        uint16_t length;
    
        for (index=0; index<18; index++)
        {
          data_array[index] =  (unsigned char)tempo_IC1;//index+1;
        }
    
        length = 18;
    
        do
        {
          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_BUSY) && (err_code != NRF_ERROR_NOT_FOUND))
          {
            APP_ERROR_CHECK(err_code);
          }
        } while (err_code == NRF_ERROR_BUSY);
    
    }
    

    The file name in p_info is main.c where there is the function SendData and the line number is "APP_ERROR_CHECK(err_code)" always in function SendData

  • Hello,

    ble_nus_data_send() returns NRF_ERROR_RESOURCES this means that the sending buffer for this characteristic is full. Please see the description in ble_gatts.h, on line 632.

     

    Do you use notification or indication?

     

    I don't see why you use the NRF_ERROR_BUSY return value.

     

    if you want to send more packets you should do something like:

    err_code = NRF_SUCCESS;
    while (err_code == NRF_SUCCESS)
    {
        err_code = ble_nus_data_send()
    }
    if (err_code != NRF_ERROR_RESOURCES (or anything else you want to filter out...)
    {
        APP_ERROR_CHECK(err_code)
    }

     

    When you receive an err_code = NRF_ERROR_RESOURCES, you should wait for the BLE_GATTS_EVT_HVN_TX_COMPLETE event, which means that some buffer space is free, and do the same until you are done sending data.

     

    Best regards,

    Edvin

Related