Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
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

Create custom event to trigger updating data in GATT table

Hi,

I have implemented the nRF5x-Custom-BLE-Service-Tutorial (https://github.com/NordicPlayground/nRF5x-custom-ble-service-tutorial) using nRF5 SDK 17.1.0 on my nRF52 DK using Segger Embedded Studio. The used Softdevice is S132.

At the end of the tutorial, a timer is implemented to call a function (ble_cus_custom_value_update()) at a regular interval to update the data in the GATT table and send a notification to the peer.

I would like to change that procedure, so that ble_cus_custom_value_update() is called when a specific event occurs, and not by the timer. In particular, I want to fill a buffer with data and as soon as the buffer is full, I want to raise an event and pass the content of the buffer to the ble_cus_custom_value_update() that will insert the data into the GATT table.

Unfortunately, I couldn't find any tutorial or question that demonstrates how to implement that functionality. Could somebody point me towards the right resources or suggest how I can approach this issue?

Thanks a lot in advance!

  • Hi Mortiz, 

    I don't see any problem doing what you plan to do. 
    You can just call ble_cus_custom_value_update() when you receive the full amount of data buffer. 

    If you have a look at the ble_app_uart example you can find this:

    ble_nus_data_send (which is similar to ble_cus_custom_value_update() ) is called when the index (number of UART data received) is equal or above m_ble_nus_mas_data_len then the GATT update and notification will be sent. 

    As long as the interrupt handler is running at APP_LOW level or lower priority then it should be fine calling a BLE API. 

  • Hi Hung, thanks for your answer.

    As you suggested I implemented the following:

    1. On BLE_CUS_EVT_NOTIFICATION_ENABLED, I call my function generate_data(). I don't call app_timer_start() as it is done in the tutorial.
    2. The generate_data() function populates m_array (a global variable) with random numbers. Once the write_pointer passes the last index, the array is passed to ble_cus_value_update() as shown in the code below.

    static void generate_data()
    {
        ret_code_t err_code;
    
        NRF_LOG_INFO("Starting data generation");
    
        // max length of array
        uint8_t max_len = 244;
        // declare write pointer
        uint8_t write_pointer = 0;
    
        for (;;)
        {
            m_array[write_pointer] = rand() % 100;
            write_pointer++;
    
            if (write_pointer > max_len)
            {
                write_pointer = 0;
    
                err_code = ble_cus_value_update(&m_aas, &m_array);
                APP_ERROR_CHECK(err_code);
            }
        }
    }

    Unfortunately, after entering the if-clause for the first time, calling ble_cus_value_update() and re-entering the for-loop again, the program stops at the NRF_BREAKPOINT_COND (line 100 in app_error_weak.c).

    My guess is that sending the data via BLE has not finished yet when the for-loop is entered again. I tried handling NRF_ERROR_RESOURCES as shown in your screenshot above, but so far without any success.

    Do you have any idea what might be wrong and how I could fix this?

  • Hi Moritz, 

    Could you let me know how you call generate_data() ? Did you call it from main context ? 

    It's normal to receive NRF_ERROR_RESOURCES , it happens when the softdevice buffer is full and you can not queue more notification or indication. 
    What you need to do is to retry it after you receive BLE_GATTS_EVT_HVN_TX_COMPLETE event and then retry. It's explained in the documentation of the function sd_ble_gatts_hvx() in ble_gatts.h: 

    Note that you should only reset the write_pointer when you managed to queue the data (err_code returns NRF_SUCCESS)

    In your code I would suggest to add a small delay to give the softdevice time to send data. 

  • Hi Hung,

    I'm calling generate_data() from on_cus_evt() the main.c file and I call it when the BLE_CUS_EVT_NOTIFICATION_ENABLED event is received (see also line 395 here: https://github.com/NordicPlayground/nRF52-Bluetooth-Course/blob/master/main.c).

    After passing the array to ble_cus_value_update(), I don't receive any error (error code 0). I implemented it now this way:

    static void generate_data()
    {
        ret_code_t err_code;
    
        NRF_LOG_INFO("Starting data generation");
    
        // max length of array
        uint8_t max_len = 243;
        // declare write pointer
        uint8_t write_pointer = 0;
    
        for (;;)
        {
            while (write_pointer <= max_len)
            {
                m_array[write_pointer] = rand() % 100;
                write_pointer++;
            }
    
            if (write_pointer >= max_len)
            {
                do 
                {
                    err_code = ble_aas_value_update(&m_aas, &m_array);
                    APP_ERROR_CHECK(err_code);
                    nrf_delay_ms(10);
                } while (err_code == NRF_ERROR_RESOURCES);
    
                write_pointer = 0;
            }
        }
    }
    

    The APP_ERROR_CHECK(err_code) still leads to the NRF_BREAKPOINT_COND (line 100 in app_error_weak.c). If I outcomment the APP_ERROR_CHECK(err_code), the code keeps running, but I only receive the first data block (afterwards, I don't receive anything new).

    Any ideas by what this could be caused?

  • Hi Mortitz, 

    So you are calling generate_data() from an interrupt handler ? 
    It's not a good practice since you have an infinite loop inside generate_data() this will keep the CPU running in interrupt handler context and won't be able to pull more events from the softdevice. 


    If you want to do an infinite loop you should better do that inside main context. 
    It's better to stop sending when you receive NRF_ERROR_RESOURCES and then continue when you receive BLE_GATTS_EVT_HVN_TX_COMPLETE  event. 

Related