Reducing the Time Required to Read 16 KB of Data

Hi,

I want to reduce the time required to read 16 KB of data from the datalogger. Currently, it takes about 6 seconds to read all the data. How can I decrease this time?

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_1_25_MS)
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_1_25_MS)
#define SLAVE_LATENCY 0
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)



///////////////////////////////////////////ALLICATION SEND DATA
for(char i=0;i<66;i++)
{
DATA_SEND_BLUE_TX[0]=i+1;
nrf_fstorage_read(&f_storage,0x28000+i*240, &DATA_SEND_BLUE_TX[1],240);
DATA_SEND_BLUE_TX[241]=Chksum8_2sComplement(&DATA_SEND_BLUE_TX[1],240);
SEND_TO_APP( DATA_SEND_BLUE_TX,242);// 242 //56
}
//////////////////////////////////////////////////////////////////

void SEND_TO_APP(uint8_t * data_array, uint16_t index)
{
uint32_t err_code;
uint16_t length = index; count_send=0;
do
{
err_code = ble_data_send(&m_data, data_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);
}
count_send++;
} while (err_code == NRF_ERROR_RESOURCES);

}

uint32_t ble_data_send(ble_data_t * p_dat,
uint8_t *p_data,
uint16_t p_length,
uint16_t conn_handle)
{
ble_gatts_value_t gatts_value;
memset(&gatts_value, 0, sizeof(gatts_value));
gatts_value.len = p_length;
gatts_value.offset = 0;
gatts_value.p_value = p_data;
return sd_ble_gatts_value_set(p_dat->conn_handle, p_dat->tx_handles.value_handle, &gatts_value);
}

Parents
  • Hi Loc, 

    Could you explain how you send data to the peer device? 
    I can see you are setting the value of the characteristic using sd_ble_gatts_value_set() in ble_data_send() 
    But then there is no guarantee that the value is notified to the peer device. 
    Usually to send data to the peer device (the client) the server send a notification. 

    Are you familiar with our example in the SDK, for example ble_app_hrs ? or ble_app_uart ?

  • Hi Hung, 

    I am using the ble_app_uart example. The Android application sends a command to the BLE device, and then waits for the device to send back 66 data packets.

    Thanks,

  • Hi Loc, 
    Could you explain why you use sd_ble_gatts_value_set() . This only set the value of the characteristic, not sending the content to the peer. 
    If you look at the ble_nus_data_send() in ble_nus.c you can find that we are using sd_ble_gatts_hvx() instead. 


    Please also be aware that nRF5 SDK is very old and has been deprecated for a few years already. If you are developing a new product, it's recommended that you start with nRF Connect SDK . 

  • Hi Hung,


    My current implementation is based on the ble_app_uart example using nRF5 SDK v16, where sd_ble_gatts_value_set() is used.
    I am planning to try the nRF Connect SDK. If I migrate to the new SDK, will the total time required to read all data be reduced or improved compared to nRF5 SDK

    Thanks,

  • Hi Loc,
    Please point me to where you see that ? 
    Here is the ble_nus.c file in SDK v16.0.0 

    /**
     * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include "sdk_common.h"
    #if NRF_MODULE_ENABLED(BLE_NUS)
    #include "ble.h"
    #include "ble_nus.h"
    #include "ble_srv_common.h"
    
    #define NRF_LOG_MODULE_NAME ble_nus
    #if BLE_NUS_CONFIG_LOG_ENABLED
    #define NRF_LOG_LEVEL       BLE_NUS_CONFIG_LOG_LEVEL
    #define NRF_LOG_INFO_COLOR  BLE_NUS_CONFIG_INFO_COLOR
    #define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR
    #else // BLE_NUS_CONFIG_LOG_ENABLED
    #define NRF_LOG_LEVEL       0
    #endif // BLE_NUS_CONFIG_LOG_ENABLED
    #include "nrf_log.h"
    NRF_LOG_MODULE_REGISTER();
    
    
    #define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003               /**< The UUID of the TX Characteristic. */
    #define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002               /**< The UUID of the RX Characteristic. */
    
    #define BLE_NUS_MAX_RX_CHAR_LEN        BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */
    #define BLE_NUS_MAX_TX_CHAR_LEN        BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */
    
    #define NUS_BASE_UUID                  {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */
    
    
    /**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice.
     *
     * @param[in] p_nus     Nordic UART Service structure.
     * @param[in] p_ble_evt Pointer to the event received from BLE stack.
     */
    static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
    {
        ret_code_t                 err_code;
        ble_nus_evt_t              evt;
        ble_gatts_value_t          gatts_val;
        uint8_t                    cccd_value[2];
        ble_nus_client_context_t * p_client = NULL;
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
                                     p_ble_evt->evt.gap_evt.conn_handle,
                                     (void *) &p_client);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          p_ble_evt->evt.gap_evt.conn_handle);
        }
    
        /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */
        memset(&gatts_val, 0, sizeof(ble_gatts_value_t));
        gatts_val.p_value = cccd_value;
        gatts_val.len     = sizeof(cccd_value);
        gatts_val.offset  = 0;
    
        err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle,
                                          p_nus->tx_handles.cccd_handle,
                                          &gatts_val);
    
        if ((err_code == NRF_SUCCESS)     &&
            (p_nus->data_handler != NULL) &&
            ble_srv_is_notification_enabled(gatts_val.p_value))
        {
            if (p_client != NULL)
            {
                p_client->is_notification_enabled = true;
            }
    
            memset(&evt, 0, sizeof(ble_nus_evt_t));
            evt.type        = BLE_NUS_EVT_COMM_STARTED;
            evt.p_nus       = p_nus;
            evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            evt.p_link_ctx  = p_client;
    
            p_nus->data_handler(&evt);
        }
    }
    
    
    /**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice.
     *
     * @param[in] p_nus     Nordic UART Service structure.
     * @param[in] p_ble_evt Pointer to the event received from BLE stack.
     */
    static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
    {
        ret_code_t                    err_code;
        ble_nus_evt_t                 evt;
        ble_nus_client_context_t    * p_client;
        ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
                                     p_ble_evt->evt.gatts_evt.conn_handle,
                                     (void *) &p_client);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          p_ble_evt->evt.gatts_evt.conn_handle);
        }
    
        memset(&evt, 0, sizeof(ble_nus_evt_t));
        evt.p_nus       = p_nus;
        evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
        evt.p_link_ctx  = p_client;
    
        if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) &&
            (p_evt_write->len == 2))
        {
            if (p_client != NULL)
            {
                if (ble_srv_is_notification_enabled(p_evt_write->data))
                {
                    p_client->is_notification_enabled = true;
                    evt.type                          = BLE_NUS_EVT_COMM_STARTED;
                }
                else
                {
                    p_client->is_notification_enabled = false;
                    evt.type                          = BLE_NUS_EVT_COMM_STOPPED;
                }
    
                if (p_nus->data_handler != NULL)
                {
                    p_nus->data_handler(&evt);
                }
    
            }
        }
        else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) &&
                 (p_nus->data_handler != NULL))
        {
            evt.type                  = BLE_NUS_EVT_RX_DATA;
            evt.params.rx_data.p_data = p_evt_write->data;
            evt.params.rx_data.length = p_evt_write->len;
    
            p_nus->data_handler(&evt);
        }
        else
        {
            // Do Nothing. This event is not relevant for this service.
        }
    }
    
    
    /**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice.
     *
     * @param[in] p_nus     Nordic UART Service structure.
     * @param[in] p_ble_evt Pointer to the event received from BLE stack.
     */
    static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
    {
        ret_code_t                 err_code;
        ble_nus_evt_t              evt;
        ble_nus_client_context_t * p_client;
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
                                     p_ble_evt->evt.gatts_evt.conn_handle,
                                     (void *) &p_client);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          p_ble_evt->evt.gatts_evt.conn_handle);
            return;
        }
    
        if (p_client->is_notification_enabled)
        {
            memset(&evt, 0, sizeof(ble_nus_evt_t));
            evt.type        = BLE_NUS_EVT_TX_RDY;
            evt.p_nus       = p_nus;
            evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
            evt.p_link_ctx  = p_client;
    
            p_nus->data_handler(&evt);
        }
    }
    
    
    void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
    {
        if ((p_context == NULL) || (p_ble_evt == NULL))
        {
            return;
        }
    
        ble_nus_t * p_nus = (ble_nus_t *)p_context;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                on_connect(p_nus, p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_WRITE:
                on_write(p_nus, p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_HVN_TX_COMPLETE:
                on_hvx_tx_complete(p_nus, p_ble_evt);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
    {
        ret_code_t            err_code;
        ble_uuid_t            ble_uuid;
        ble_uuid128_t         nus_base_uuid = NUS_BASE_UUID;
        ble_add_char_params_t add_char_params;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
        VERIFY_PARAM_NOT_NULL(p_nus_init);
    
        // Initialize the service structure.
        p_nus->data_handler = p_nus_init->data_handler;
    
        /**@snippet [Adding proprietary Service to the SoftDevice] */
        // Add a custom base UUID.
        err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
        VERIFY_SUCCESS(err_code);
    
        ble_uuid.type = p_nus->uuid_type;
        ble_uuid.uuid = BLE_UUID_NUS_SERVICE;
    
        // Add the service.
        err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                            &ble_uuid,
                                            &p_nus->service_handle);
        /**@snippet [Adding proprietary Service to the SoftDevice] */
        VERIFY_SUCCESS(err_code);
    
        // Add the RX Characteristic.
        memset(&add_char_params, 0, sizeof(add_char_params));
        add_char_params.uuid                     = BLE_UUID_NUS_RX_CHARACTERISTIC;
        add_char_params.uuid_type                = p_nus->uuid_type;
        add_char_params.max_len                  = BLE_NUS_MAX_RX_CHAR_LEN;
        add_char_params.init_len                 = sizeof(uint8_t);
        add_char_params.is_var_len               = true;
        add_char_params.char_props.write         = 1;
        add_char_params.char_props.write_wo_resp = 1;
    
        add_char_params.read_access  = SEC_OPEN;
        add_char_params.write_access = SEC_OPEN;
    
        err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        // Add the TX Characteristic.
        /**@snippet [Adding proprietary characteristic to the SoftDevice] */
        memset(&add_char_params, 0, sizeof(add_char_params));
        add_char_params.uuid              = BLE_UUID_NUS_TX_CHARACTERISTIC;
        add_char_params.uuid_type         = p_nus->uuid_type;
        add_char_params.max_len           = BLE_NUS_MAX_TX_CHAR_LEN;
        add_char_params.init_len          = sizeof(uint8_t);
        add_char_params.is_var_len        = true;
        add_char_params.char_props.notify = 1;
    
        add_char_params.read_access       = SEC_OPEN;
        add_char_params.write_access      = SEC_OPEN;
        add_char_params.cccd_write_access = SEC_OPEN;
    
        return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles);
        /**@snippet [Adding proprietary characteristic to the SoftDevice] */
    }
    
    
    uint32_t ble_nus_data_send(ble_nus_t * p_nus,
                               uint8_t   * p_data,
                               uint16_t  * p_length,
                               uint16_t    conn_handle)
    {
        ret_code_t                 err_code;
        ble_gatts_hvx_params_t     hvx_params;
        ble_nus_client_context_t * p_client;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client);
        VERIFY_SUCCESS(err_code);
    
        if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL))
        {
            return NRF_ERROR_NOT_FOUND;
        }
    
        if (!p_client->is_notification_enabled)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (*p_length > BLE_NUS_MAX_DATA_LEN)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_nus->tx_handles.value_handle;
        hvx_params.p_data = p_data;
        hvx_params.p_len  = p_length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(conn_handle, &hvx_params);
    }
    
    
    #endif // NRF_MODULE_ENABLED(BLE_NUS)
    

    sd_ble_gatts_hvx() is used in ble_nus_data_send()


    What do you expect the sd_ble_gatts_value_set() do ? 

  • Hi Hung,

    Maybe I am mistaken. I will check it again.Thank you for your help. 

Reply Children
No Data
Related