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

ble_app-uart example - ble_nus_data_send() - BLE_NUS_EVT_TX_RDY - connection interval

I am sending 240-byte data from peripheral to central through notification (without response) by using the ble_nus_data_send() function when the BLE_NUS_EVT_TX_RDY event comes. The issue here is the BLE_NUS_EVT_TX_RDY is triggering 2x times of connection interval.
eg: If we put connection interval 7.5 then the event BLE_NUS_EVT_TX_RDY will trigger every 15 ms only.

parameters being used

nRF5 SDK v17.0.2

NRF_SDH_BLE_GAP_DATA_LENGTH 251

NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

NRF_SDH_BLE_GAP_EVENT_LENGTH 400

and also am using the conn_evt_len_ext_set() function.

why is that event BLE_NUS_EVT_TX_RDY is triggering 2x time of connection interval?

here I attached the sniffer log

Parents
  • Hi AKV, 

    We need to look at how your queue the data for sending. 


    From the sniffer trace what I can read is that the notification queue was not full, and it seems that you wait until you receive BLE_NUS_EVT_TX_RDY event before you queue the next one. When you queue data, you would need to queue until the buffer is full (until you receive NRF_ERROR_RESOURCES error code). 
    If you only queue one packet per BLE_NUS_EVT_TX_RDY event, what showed in the sniffer trace is expected. The chip send one packet, the packet get ACKed (in the next event) then you queue the next packet. This explain the 2x time of connection interval. 

  • Thanks for the reply..

    yes, I am sending data as you said only queue one packet per BLE_NUS_EVT_TX_RDY event,

    1. The data is sending from peripheral to central via notification. The notification does not have any response or acknowledgment from central right? Then why it takes the next event to give BLE_NUS_EVT_TX_RDY?

    2. Is the NRF_ERROR_RESOURCES mean that the buffer of the softdevice/stack is full right?

  • Hi AKV,

    I'm sorry for the late reply. I had a look at the error , it's 0x13 meaning 19 in decimal and that means: 

    #define NRF_ERROR_RESOURCES                   (NRF_ERROR_BASE_NUM + 19)

    So it's simply the softdevice buffer was full when queueing for write command packets. However the issue here is that our nrf_ble_gq module which supposed to queue the message when the buffer is full didn't handle the NRF_ERROR_RESOURCES but only handle the NRF_ERROR_BUSY. 

    A patch is needed, please have a look at this case and apply the patch: https://devzone.nordicsemi.com/f/nordic-q-a/60557/bug-improvement-in-handling-nrf_error_resources-response-in-gatt-queue-nrf_ble_gq_req_gatts_hvx-processing

    After that it should work. 

  • I am still getting that error even after I made that change in the nrf_ble_gq.c file.

    I have attached the code please verify the changes that I made nrf_ble_gq.c file.

    static void queue_process(nrf_queue_t const * const p_queue, uint16_t conn_handle)
    case NRF_BLE_GQ_REQ_GATTS_HVX:
                {
                    uint8_t  hvx_data[NRF_BLE_GQ_GATTS_HVX_MAX_DATA_LEN];
                    uint16_t len;
                    uint16_t hvx_len;
    
                    // Retrieve allocated data.
                    ble_req.params.gatts_hvx.p_data = hvx_data;
                    nrf_memobj_read(ble_req.p_mem_obj,
                                    (void *) &hvx_len,
                                    sizeof(uint16_t),
                                    0);
                    ble_req.params.gatts_hvx.p_len = &hvx_len;
                    nrf_memobj_read(ble_req.p_mem_obj,
                                    (void *) ble_req.params.gatts_hvx.p_data,
                                    *ble_req.params.gatts_hvx.p_len,
                                    sizeof(uint16_t));
    
                    len = hvx_len;
    
                    NRF_LOG_DEBUG("GATTS HVX");
                    err_code = sd_ble_gatts_hvx(conn_handle,
                                                &ble_req.params.gatts_hvx);
    
                    if ((err_code == NRF_SUCCESS) &&
                        (len != hvx_len))
                    {
                        err_code = NRF_ERROR_DATA_SIZE;
                    }
                    //Added change
                   if (err_code == NRF_ERROR_RESOURCES)
                    {
                        err_code = NRF_ERROR_BUSY;
                    }
                  
                } break;
                
                
                
      static bool request_process(nrf_ble_gq_req_t const * const p_req, uint16_t conn_handle)
      case NRF_BLE_GQ_REQ_GATTS_HVX:
            {
                uint16_t len = *p_req->params.gatts_hvx.p_len;
    
                NRF_LOG_DEBUG("GATTS Notification or Indication");
    
                err_code = sd_ble_gatts_hvx(conn_handle,
                                            &p_req->params.gatts_hvx);
    
                if ((err_code == NRF_SUCCESS) &&
                    (len != *p_req->params.gatts_hvx.p_len))
                {
                    err_code = NRF_ERROR_DATA_SIZE;
                }
                //Added change
                 if (err_code == NRF_ERROR_RESOURCES)
                {
                    err_code = NRF_ERROR_BUSY;
                }
                
    
            } break;

    Also attached function used to send data from central to peripheral

    void Ble_test_data_send(void)
    {
       uint32_t       err_code; 
       err_code = NRF_SUCCESS;
        
        while (err_code == NRF_SUCCESS)
        { 
        
          err_code = ble_nus_c_string_send(&m_ble_nus_c, Ble_tx_buf, Ble_Tx_length);
          NRF_LOG_INFO("ble_nus_c_string_send %d:",err_code);
    
          if (err_code == NRF_ERROR_RESOURCES)
            {            
                break;
            }
            else if (err_code != NRF_SUCCESS)
            {
                NRF_LOG_ERROR("nrf_ble_gq_item_add failed: 0x%x", err_code);
            }  
        }
    
    
    }

    log:

    <info> app: ble_nus_c_string_send 0:

    <info> app: ble_nus_c_string_send 0:

    <info> app: ble_nus_c_string_send 0:

    <info> app: ble_nus_c_string_send 0:

    <error> nrf_ble_gq: SD GATT procedure (1) failed on connection handle 0 with error: 0x00000013.

    <error> app: Fatal error

    <warning> app: System reset

  • Hi AKV, 
    It's my mistake, in your case you are doing a write command but in the case I pointed to the customer used the notification. 
    So what you need to modify is inside request_process() and in queue_process() to change the check from:


     if (err_code == NRF_ERROR_BUSY)

    to 

     if ((err_code == NRF_ERROR_BUSY)||(err_code == NRF_ERROR_RESOURCES))

    It should work after that. 

  • Thanks.

    After making those changes it's working now.

    <info> app: ble_nus_c_string_send 0:

    <info> app: ble_nus_c_string_send 0:

    <info> app: ble_nus_c_string_send 0:

    <info> app: ble_nus_c_string_send 0:

    <info> app: ble_nus_c_string_send 9:

    And why is that return value is getting 9 (NRF_ERROR_INVALID_LENGTH) instead of NRF_ERROR_RESOURCES

  • Please try to find what exact throwing error 9. If you see an error, you would need to debug it by stepping into the code and get on the function that throwing the error. You may need to step deep into the code to find the exact function, not just the first function that return you that code because it may be resulted from one of the child functions that called inside that first function. 

    So if you try to write and if the write command is larger than NRF_BLE_GQ_GATTC_WRITE_MAX_DATA_LEN (16 bytes) you will receive that invalid length. 
    Please check your sdk_config to increase the length. 

Reply
  • Please try to find what exact throwing error 9. If you see an error, you would need to debug it by stepping into the code and get on the function that throwing the error. You may need to step deep into the code to find the exact function, not just the first function that return you that code because it may be resulted from one of the child functions that called inside that first function. 

    So if you try to write and if the write command is larger than NRF_BLE_GQ_GATTC_WRITE_MAX_DATA_LEN (16 bytes) you will receive that invalid length. 
    Please check your sdk_config to increase the length. 

Children
No Data
Related