<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/87656/create-custom-event-to-trigger-updating-data-in-gatt-table</link><description>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</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 03 Jun 2022 06:12:36 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/87656/create-custom-event-to-trigger-updating-data-in-gatt-table" /><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/370788?ContentTypeID=1</link><pubDate>Fri, 03 Jun 2022 06:12:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:52db06d6-5f99-4e4e-85c7-cb62ec082ef6</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;Hi Hung,&lt;/p&gt;
&lt;p&gt;one last question: if the stack is full (err_code = NRF_ERROR_RESOURCES) will this not result in a loss of data?&lt;/p&gt;
&lt;p&gt;Thanks a lot for your support. It&amp;#39;s working and you helped me to understand what needs to be done. I need to see if this approach achieves the required throughput and then add i2s to this approach, since I need to send audio data. But I think it&amp;#39;s more meaningful to open another thread for that.&lt;/p&gt;
&lt;p&gt;Here is the final version of my main() for the reference of others (based on the BLE template app in the SDK examples):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**@brief Function for application main entry.
 */
int main(void)
{
    bool erase_bonds;
    uint8_t err_code;

    // Initialize.
    log_init();
    timers_init();
    buttons_leds_init(&amp;amp;erase_bonds);
    power_management_init();

    // Initialize BLE
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
    peer_manager_init();

    // Start execution.
    NRF_LOG_INFO(&amp;quot;Template example started.&amp;quot;);

    // Start advertising
    advertising_start(erase_bonds);

    // max length of array
    uint8_t max_len = 243;
    // declare write pointer
    uint8_t write_pointer = 0;

    // Enter main loop.
    for (;;)
    {
        if (i2s_transfer) 
        {
            while (write_pointer &amp;lt;= max_len)
            {
                m_array[write_pointer] = rand() % 100;
                write_pointer++;
            }

            if (write_pointer &amp;gt;= max_len)
            {
                err_code = ble_aas_value_update(&amp;amp;m_aas, &amp;amp;m_array);
                if ((err_code != NRF_SUCCESS) &amp;amp;&amp;amp;
                    (err_code != NRF_ERROR_INVALID_STATE) &amp;amp;&amp;amp;
                    (err_code != NRF_ERROR_RESOURCES) &amp;amp;&amp;amp;
                    (err_code != NRF_ERROR_BUSY) &amp;amp;&amp;amp;
                    (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                   )
                {
                    APP_ERROR_CHECK(err_code);
                }

                if (err_code == NRF_ERROR_RESOURCES)
                {
                    NRF_LOG_DEBUG(&amp;quot;error resources&amp;quot;);
                    if (ble_ready != true)
                    {
                        idle_state_handle();
                    }
                    ble_ready = false;
                }
              
                write_pointer = 0;
              
            }
        }
    }    
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/370614?ContentTypeID=1</link><pubDate>Thu, 02 Jun 2022 08:27:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:38ba357d-8a1c-47fa-926b-1584e356c6dd</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi Moritz,&amp;nbsp;&lt;br /&gt;You are getting there.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The&amp;nbsp;&lt;span&gt;APP_ERROR_CHECK(err_code)&amp;nbsp; should only be used for err_code that are&amp;nbsp;critical and the operation should be stopped.&amp;nbsp;&lt;br /&gt;In your case&amp;nbsp;NRF_ERROR_RESOURCES&amp;nbsp;only means that the buffer of the stack is full. So you don&amp;#39;t need to call&amp;nbsp;APP_ERROR_CHECK() on it. Usually we we do this:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1654158316183v1.png" alt=" " /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In addition you may not want to use nrf_delay_ms(10) because it will just simply keep the CPU in busy loop and not putting it to sleep. You will end up having high current consumption. Instead you can put the CPU to sleep using&amp;nbsp;&amp;nbsp;idle_state_handle();&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;You don&amp;#39;t even need the&amp;nbsp;&amp;nbsp;while (ble_ready != true), you can use&amp;nbsp;&amp;nbsp;if (ble_ready != true) then put the CPU to sleep with&amp;nbsp;idle_state_handle();. The CPU will automatically wake up and continue when you receive&amp;nbsp;BLE_GATTS_EVT_HVN_TX_COMPLETE&amp;nbsp; event.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/370499?ContentTypeID=1</link><pubDate>Wed, 01 Jun 2022 15:04:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6fc25d05-8d32-4b5e-abaa-58c9f496b6d9</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;Hi Hung,&lt;/p&gt;
&lt;p&gt;sorry for the late response. I was out of office for some time and just found time today to continue working on that.&lt;/p&gt;
&lt;p&gt;I moved the loop into my main function as you suggested. I can now send some packages (usually around 4), but then the app stops with the following error message:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;error&amp;gt; app: ERROR 19 [NRF_ERROR_RESOURCES] at /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:906
PC at: 0x00032F6F
&amp;lt;error&amp;gt; app: End of error report&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here is what I did:&lt;/p&gt;
&lt;p&gt;1. I added a new case to the ble_evt_handler in main.c:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;case BLE_GATTS_EVT_HVN_TX_COMPLETE:
            NRF_LOG_INFO(&amp;quot;transfer complete&amp;quot;);
            ble_ready = true;
            break;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;ble_ready is initially false and set to true as soon as the event is received. However, the &amp;quot;transfer complete&amp;quot; doesn&amp;#39;t appear in the debugging window, so I wonder if this event is received properly?&lt;/p&gt;
&lt;p&gt;2. my loop in the main function looks like that now.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    // max length of array
    uint8_t max_len = 243;
    // declare write pointer
    uint8_t write_pointer = 0;

    // Enter main loop.
    for (;;)
    {
        idle_state_handle();

        if (i2s_transfer) 
        {
          NRF_LOG_INFO(&amp;quot;Starting data generation&amp;quot;);
          while (write_pointer &amp;lt;= max_len)
          {
              m_array[write_pointer] = rand() % 100;
              write_pointer++;
          }

          if (write_pointer &amp;gt;= max_len)
          {
              err_code = ble_aas_value_update(&amp;amp;m_aas, &amp;amp;m_array);
              APP_ERROR_CHECK(err_code);

              if (err_code == NRF_ERROR_RESOURCES)
              {
                  while (ble_ready != true)
                  {
                      nrf_delay_ms(10);
                  }
              }
              
              write_pointer = 0;
              
          }
        }
    }   &lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;i2s_transfer is another flag that is set to true as soon as notifications are enabled by the peer. Subsequently, the m_array is filled with data. As soon as the array is filled, I&amp;#39;m sending the data. If the returned err_code is NRF_ERROR_RESOURCES, I&amp;#39;m waiting until the ble_ready is set to true (which should happen when the BLE_GATTS_EVT_HVN_TX_COMPLETE is received).&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m new to BLE and event-based programming, so I&amp;#39;m sure that there are better approaches to handle that. Do you have any idea why I&amp;#39;m only able to send so little packages and the receive that error? How can I change my code to handle such errors so that it works?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;EDIT: &lt;br /&gt;I checked again and it seems I&amp;#39;m receiving the BLE_GATTS_EVT_HVN_TX_COMPLETE (the &amp;quot;transfer complete&amp;quot;) is printed. But if I put a breakpoint inside the if-clause that checks err_code == NRF_ERROR_RESOURCES, it&amp;#39;s never reached. So it seems the error is raised by something else. So far I wasn&amp;#39;t able to track that down.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;EDIT2:&lt;/p&gt;
&lt;p&gt;I realized now that the NRF_ERROR_RESOURCES occurs when calling APP_ERROR_CHECK(err_code) (line 23 in the code above). When I comment out that line (what I don&amp;#39;t want to do), the code works. So how can I resolve this?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/368229?ContentTypeID=1</link><pubDate>Wed, 18 May 2022 08:28:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c74cf4be-7015-4117-9abf-29598b20355a</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi Mortitz,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So you are calling&amp;nbsp;generate_data() from an interrupt handler ?&amp;nbsp;&lt;br /&gt;It&amp;#39;s not a good practice since you have an infinite loop inside&amp;nbsp;&lt;span&gt;generate_data() this will keep the CPU running in interrupt handler context and won&amp;#39;t be able to pull more events from the softdevice.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;br /&gt;If you want to do an infinite loop you should better do that inside main context.&amp;nbsp;&lt;br /&gt;It&amp;#39;s better to stop sending when you receive&amp;nbsp;NRF_ERROR_RESOURCES and then continue when you receive&amp;nbsp;BLE_GATTS_EVT_HVN_TX_COMPLETE&amp;nbsp; event.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/368041?ContentTypeID=1</link><pubDate>Mon, 16 May 2022 12:05:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:97b5ef8f-6b3d-410d-93d0-242b6e5fb2a8</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;Hi Hung,&lt;/p&gt;
&lt;p&gt;I&amp;#39;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: &lt;a href="https://github.com/NordicPlayground/nRF52-Bluetooth-Course/blob/master/main.c"&gt;https://github.com/NordicPlayground/nRF52-Bluetooth-Course/blob/master/main.c&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After passing the array to ble_cus_value_update(), I don&amp;#39;t receive any error (error code 0). I implemented it now this way:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void generate_data()
{
    ret_code_t err_code;

    NRF_LOG_INFO(&amp;quot;Starting data generation&amp;quot;);

    // max length of array
    uint8_t max_len = 243;
    // declare write pointer
    uint8_t write_pointer = 0;

    for (;;)
    {
        while (write_pointer &amp;lt;= max_len)
        {
            m_array[write_pointer] = rand() % 100;
            write_pointer++;
        }

        if (write_pointer &amp;gt;= max_len)
        {
            do 
            {
                err_code = ble_aas_value_update(&amp;amp;m_aas, &amp;amp;m_array);
                APP_ERROR_CHECK(err_code);
                nrf_delay_ms(10);
            } while (err_code == NRF_ERROR_RESOURCES);

            write_pointer = 0;
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;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&amp;#39;t receive anything new).&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Any ideas by what this could be caused?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/367454?ContentTypeID=1</link><pubDate>Wed, 11 May 2022 14:26:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3999043e-888e-454f-9552-4b2ff8075929</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi Moritz,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Could you let me know how you call&amp;nbsp;generate_data() ? Did you call it from main context ?&amp;nbsp;&lt;br /&gt;&lt;br /&gt;It&amp;#39;s normal to receive&amp;nbsp;&lt;span&gt;NRF_ERROR_RESOURCES&amp;nbsp;, it happens when the softdevice buffer is full and you can not queue more notification or indication.&amp;nbsp;&lt;br /&gt;What you need to do is to retry it after you receive&amp;nbsp;BLE_GATTS_EVT_HVN_TX_COMPLETE event and then retry. It&amp;#39;s explained in the documentation of the function&amp;nbsp;sd_ble_gatts_hvx() in ble_gatts.h:&amp;nbsp;&lt;br /&gt;&lt;img src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/communityserver-discussions-components-files/4/pastedimage1652279062951v1.png" alt=" " /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Note that you should only reset the&amp;nbsp;write_pointer when you managed to queue the data (err_code returns NRF_SUCCESS)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In your code I would suggest to add a small delay to give the softdevice time to send data.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/367448?ContentTypeID=1</link><pubDate>Wed, 11 May 2022 14:04:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:86300bb4-dda7-48e3-9d70-2874990e7aef</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;Hi Hung, thanks for your answer. &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you suggested I implemented the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On BLE_CUS_EVT_NOTIFICATION_ENABLED, I call my function generate_data(). I don&amp;#39;t call app_timer_start() as it is done in the tutorial.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void generate_data()
{
    ret_code_t err_code;

    NRF_LOG_INFO(&amp;quot;Starting data generation&amp;quot;);

    // 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 &amp;gt; max_len)
        {
            write_pointer = 0;

            err_code = ble_cus_value_update(&amp;amp;m_aas, &amp;amp;m_array);
            APP_ERROR_CHECK(err_code);
        }
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;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).&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;Do you have any idea what might be wrong and how I could fix this?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Create custom event to trigger updating data in GATT table</title><link>https://devzone.nordicsemi.com/thread/366893?ContentTypeID=1</link><pubDate>Mon, 09 May 2022 10:56:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3637e270-8aa0-4ea4-a85a-a17cead2bca9</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi Mortiz,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t see any problem doing what you plan to do.&amp;nbsp;&lt;br /&gt;You can just call&amp;nbsp;&lt;span&gt;ble_cus_custom_value_update() when you receive the full amount of data buffer.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;If you have a look at the ble_app_uart example you can find this:&lt;br /&gt;&lt;img src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/communityserver-discussions-components-files/4/pastedimage1652093674949v1.png" alt=" " /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;ble_nus_data_send (which is similar to&amp;nbsp;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.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;As long as the interrupt handler is running&amp;nbsp;at&amp;nbsp;APP_LOW level or lower priority then it should be fine calling a BLE API.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>