This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Unable to send more than 4 bytes of data over BLE

Hi,

I am trying to create a custom BLE service.

Following is the main code:

            err_code = ble_cus_flash_update(&m_cus, m_rx_buf, m_conn_handle);
            if (err_code != NRF_SUCCESS &&
                err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                err_code != NRF_ERROR_INVALID_STATE &&
                err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)

            {
                APP_ERROR_CHECK(err_code);
            }

These are my BLE write functions:

    uint8_t flash_init_value [6] = {0};

    memset(&add_char_params, 0, sizeof(add_char_params));
    add_char_params.uuid              = FLASH_UUID;
    add_char_params.uuid_type         = p_cus->uuid_type;

    add_char_params.init_len          = 6;// (in bytes)
    add_char_params.max_len           = 6;
    add_char_params.p_init_value      = flash_init_value;

    add_char_params.char_props.read   = 1;
    add_char_params.char_props.notify = 1;

    add_char_params.read_access       = SEC_OPEN;
    add_char_params.cccd_write_access = SEC_OPEN;

    err_code = characteristic_add(p_cus->service_handle,
                                  &add_char_params,
                                  &p_cus->flash_handles);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    return NRF_SUCCESS;

uint32_t ble_cus_flash_update(ble_cus_t * p_cus, uint8_t * flash_data_byte, uint16_t conn_handle)
{
    ble_gatts_hvx_params_t params;
    uint16_t len = sizeof(flash_data_byte);

    memset(&params, 0, sizeof(params));
    params.type   = BLE_GATT_HVX_NOTIFICATION;
    params.handle = p_cus->flash_handles.value_handle;
    params.p_data = flash_data_byte;
    params.p_len  = &len;

    return sd_ble_gatts_hvx(conn_handle, &params);
}

My sdk_config file says MAX_MTU is defined 23

// <o> NRF_SDH_BLE_GAP_EVENT_LENGTH - GAP event length. 
// <i> The time set aside for this connection on every connection interval in 1.25 ms units.

#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH
#define NRF_SDH_BLE_GAP_EVENT_LENGTH 6
#endif

// <o> NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size. 
#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE
#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 23
#endif

// <o> NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. 
#ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE
#define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408
#endif

I am using nrf Connect to debug BLE, which gives me output like this:

0x A1-A2-A3-A4-00-00

I am able to send 4 bytes successfully, but the rest of the values are not updating.
Any help would be really appreciated.

Regards,
Anurag

Parents
  • Hi Anurag,

    The problem here is that the size you specify is always 4. See this part of your code:

    uint32_t ble_cus_flash_update(ble_cus_t * p_cus, uint8_t * flash_data_byte, uint16_t conn_handle)
    {
        ble_gatts_hvx_params_t params;
        uint16_t len = sizeof(flash_data_byte);

    Here the len variable is set to the sizeof a pointer, which is always 4 byte. This is not what you want. There is no way to know the length of the input in this function, so you must pass the length as an additional parameter.

  • Hi Einar,

    Thanks for the response, I have resolved the issue as following:

    uint32_t ble_cus_flash_update(ble_cus_t * p_cus, uint8_t * flash_data_byte, uint16_t len, uint16_t conn_handle)
    {
        ble_gatts_hvx_params_t params;
    
        memset(&params, 0, sizeof(params));
        params.type   = BLE_GATT_HVX_NOTIFICATION;
        params.handle = p_cus->flash_handles.value_handle;
        params.p_data = flash_data_byte;
        params.p_len  = &len;
    
        return sd_ble_gatts_hvx(conn_handle, &params);
    }
    

    Though I am getting another Issue, when I am enabling notifications in the nrfGo app, my program crashes with a hard fault.

    I am sending 50 bytes of data at 100 ms intervals.

    This is the location of Hard fault:

    void app_error_handler_bare(ret_code_t error_code)
    {
        error_info_t error_info =
        {
            .line_num    = 0,
            .p_file_name = NULL,
            .err_code    = error_code,
        };
    
        app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
    
        UNUSED_VARIABLE(error_info);
    }

  • Hi,

    There is no information here about what caused the error. However, the error handler is hit, so you can find more information by using a debug build. In that case, you will see which error code was detected at which line number in which file. If you are using SES, then simply select the "Debug" build target and test again. If using something else, define "DEBUG" for the project. See An introduction to error handling in nRF5 projects for more about this.

    PS: This thread was automatically locked as you verified the answer to the original question, but I unlocked it in order to answer the second question. Please make new threads for new questions in the future.

Reply
  • Hi,

    There is no information here about what caused the error. However, the error handler is hit, so you can find more information by using a debug build. In that case, you will see which error code was detected at which line number in which file. If you are using SES, then simply select the "Debug" build target and test again. If using something else, define "DEBUG" for the project. See An introduction to error handling in nRF5 projects for more about this.

    PS: This thread was automatically locked as you verified the answer to the original question, but I unlocked it in order to answer the second question. Please make new threads for new questions in the future.

Children
  • Thanks,

    I will start a new thread for this question.

    Can you just tell me if there is a limitation as to how often we can call ble write functions, like every 1 or 2 ms?

  • Hi,

    There is no fixed limit on how often you can call sd_ble_gatts_hvx(), but if you call it too frequently so that there are no more buffers available it will return NRF_ERROR_NO_MEM. In that case the best is normally to wait for a BLE_EVT_TX_COMPLETE event before you try again.

  • Hi Einar,

    I am trying to implement BLE_ERROR_NO_TX_BUFFERS as described here

    But, it gives me "undeclared error", I have tried including "ble_err.h" with nomluck.
    Can you tell me which header contains "BLE_EVT_TX_COMPLETE ", I can try to include and call it.

    Regards,

    Anurag

  • Hi Anurag,

    _anurag said:

    I am trying to implement BLE_ERROR_NO_TX_BUFFERS as described here

    But, it gives me "undeclared error", I have tried including "ble_err.h" with nomluck

    That thread is too old. There is no BLE_ERROR_NO_TX_BUFFERS unless you are using an ancient SDK and SoftDevices version(?), which is why you get the error.

    _anurag said:
    Can you tell me which header contains "BLE_EVT_TX_COMPLETE ", I can try to include and call it.

    Sorry, I wrote the last post from memory, and that does not serve me too well it seems. Assuming you use a recent SDK version (17.x.x for instance) you will get NRF_ERROR_RESOURCES if the queue is full. Then you should wait for BLE_GATTS_EVT_HVN_TX_COMPLETE before you try again. (This is from ble_gatts.h. You get this as a BLE event in your BLE event handler.)

Related