<?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>Libuarte async high speed data receive and NUS transfer</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/65251/libuarte-async-high-speed-data-receive-and-nus-transfer</link><description>Hi, 
 I successfully added libuarte async library to the ble_app_uart example. Now I am able to receive data over UART from another board and my goal is to transfer it to the android application using NUS service just like in the ble_app_uart example</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 28 Aug 2020 08:15:52 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/65251/libuarte-async-high-speed-data-receive-and-nus-transfer" /><item><title>RE: Libuarte async high speed data receive and NUS transfer</title><link>https://devzone.nordicsemi.com/thread/266897?ContentTypeID=1</link><pubDate>Fri, 28 Aug 2020 08:15:52 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c54a26ea-f466-4dc4-afe5-33ac7e2e3198</guid><dc:creator>Edvin</dc:creator><description>[quote user="ullnorse"]I think I finally got it. I didn&amp;#39;t really understand what you meant with buffering at first but I think I got it. Because there is more than 30KB or unused ram I split that into two buffers as you suggested and started filling them up in the&amp;nbsp;&lt;span&gt;NRF_LIBUARTE_ASYNC_EVT_RX_DATA event. After the buffer is full I set the flag in the main loop and switch the buffers so I can fill the next one. In the main loop, I bulk transfer the whole array instead of individual chunks like before.&lt;/span&gt;[/quote]
&lt;p&gt;&amp;nbsp;Good! That was at least what I was trying to say. Since the softdevice may keep the CPU busy for short periods, you may receive two NRF_LIBUARTE_ASYNC_EVT_RX_DATA before you manage to handle the first one of them. So if you increase to having two buffers, the application should be able to push the data to the queue before the 3rd NRF_LIBUARTE_ASYNC_EVT_RX_DATA. At least as long as the BLE link has a higher throughput than the UART.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Have a nice weekend.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Edvin&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Libuarte async high speed data receive and NUS transfer</title><link>https://devzone.nordicsemi.com/thread/266824?ContentTypeID=1</link><pubDate>Thu, 27 Aug 2020 18:33:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7396d679-e2ee-4b66-853a-c848eaa0574e</guid><dc:creator>Aleksa</dc:creator><description>&lt;p&gt;I think I finally got it. I didn&amp;#39;t really understand what you meant with buffering at first but I think I got it. Because there is more than 30KB or unused ram I split that into two buffers as you suggested and started filling them up in the&amp;nbsp;&lt;span&gt;NRF_LIBUARTE_ASYNC_EVT_RX_DATA event. After the buffer is full I set the flag in the main loop and switch the buffers so I can fill the next one. In the main loop, I bulk transfer the whole array instead of individual chunks like before.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I managed to transfer close to 100KB this way and received every byte in the android application. Naturally, there is more testing to be done with regards to what delay is acceptable in our case but I definitely think this is the way forward for higher speeds.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I just want to thank you again for timely responses and ideas it really helped.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thanks,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Aleksa&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Libuarte async high speed data receive and NUS transfer</title><link>https://devzone.nordicsemi.com/thread/266714?ContentTypeID=1</link><pubDate>Thu, 27 Aug 2020 11:36:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9b8bf4e7-0813-4061-8e10-c08180fbca51</guid><dc:creator>Aleksa</dc:creator><description>&lt;p&gt;Ok, so first few questions and then I&amp;#39;ll show you what I tried.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What priority should I set &lt;strong&gt;.int_prio&lt;/strong&gt; field in the &lt;strong&gt;nrf_libuarte_async_config_t&lt;/strong&gt; struct so that it doesn&amp;#39;t clash with BLE stack? All I know is that it should be higher than &lt;strong&gt;APP_IRQ_PRIORITY_LOWEST&lt;/strong&gt; to not cause assert.&lt;/li&gt;
&lt;li&gt;Do I need to use a do-while loop when calling &lt;strong&gt;ble_nus_data_send&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Do I need to do something in the &lt;strong&gt;BLE_GATTS_EVT_HVN_TX_COMPLETE&lt;/strong&gt; event? If I am correct it should fire after &lt;strong&gt;ble_nus_data_send&lt;/strong&gt; is finished.&lt;/li&gt;
&lt;li&gt;What is the purpose of parameter &lt;strong&gt;_rx_buf_cnt&lt;/strong&gt; in &lt;strong&gt;NRF_LIBUARTE_ASYNC_DEFINE&lt;/strong&gt;? It says &amp;quot;Size impacts accepted latency&lt;br /&gt;* between &lt;strong&gt;NRF_LIBUARTE_ASYNC_EVT_RX_DATA&lt;/strong&gt; event and&lt;br /&gt;* @ref nrf_libuarte_async_rx_free. But doesn&amp;#39;t mention is it for better or for worse or why. In the libuarte example, the number of buffers is 3 but I tested with also 10 and didn&amp;#39;t find any difference.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So here is what I figured out.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
        {
            NRF_LOG_INFO(&amp;quot;data length = %d&amp;quot;, p_evt-&amp;gt;data.rxtx.length);

            // measure received bytes
            cnt += p_evt-&amp;gt;data.rxtx.length;

            if (active_buffer == 1)
            {
                buf = buffer2;
            }
            else if (active_buffer == 2)
            {
                buf = buffer1;
            }

            memcpy(buf, p_evt-&amp;gt;data.rxtx.p_data, p_evt-&amp;gt;data.rxtx.length);
            buf_len = p_evt-&amp;gt;data.rxtx.length;

            err_code = ble_nus_data_send(&amp;amp;m_nus, buf, &amp;amp;buf_len, m_conn_handle);
            if ((err_code != NRF_ERROR_INVALID_STATE) &amp;amp;&amp;amp;
               (err_code != NRF_ERROR_RESOURCES) &amp;amp;&amp;amp;
               (err_code != NRF_ERROR_NOT_FOUND))
            {
                APP_ERROR_CHECK(err_code);
            }

            nrf_libuarte_async_rx_free(&amp;amp;libuarte, p_evt-&amp;gt;data.rxtx.p_data, p_evt-&amp;gt;data.rxtx.length);
            break;
        }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;First I tried to put&amp;nbsp;&lt;strong&gt;ble_nus_data_send&amp;nbsp;&lt;/strong&gt;in the do-while loop but it just straight-up hands. So I tried removing it from the loop and I got it to send data. The strange thing is that the original ble_app_uart example uses the loop and it works just fine.&lt;/p&gt;
&lt;p&gt;I then conducted the following test. On the test board (STM32F4) I create a loop with 1000 counter and send 244 bytes with uart_send. I would expect to receive 244000 bytes on android application but that is not happening. I keep receiving less data then I should.&lt;/p&gt;
&lt;p&gt;Now here is the catch. I verified that my test board sends the correct amount of data. Also, variable cnt in the code snippet is set to 244000 as it should be after the test. I assume that I did receive all data on the nordic board. I also know that when I call&amp;nbsp;&lt;strong&gt;ble_nus_data_send&amp;nbsp;&lt;/strong&gt;in a for loop I get reliable transfer at ~100KBps. I can&amp;#39;t really figure out what am I doing wrong.&lt;/p&gt;
&lt;p&gt;If the counter is set to 244000 that means that I did enter the event exactly 1000 times and I should have called the function 1000 timer.&amp;nbsp;Obviously that is not happening. Any help is appreciated.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Libuarte async high speed data receive and NUS transfer</title><link>https://devzone.nordicsemi.com/thread/266627?ContentTypeID=1</link><pubDate>Thu, 27 Aug 2020 07:30:42 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fb641f74-9d6a-419d-a3bc-4c98c406e9e7</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;I would check if it helps to double buffer the messages coming from your libuarte event handler, so that you alternate between two buffers.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The first time you get a&amp;nbsp;&lt;span&gt;NRF_LIBUARTE_ASYNC_EVT_RX_DATA event, copy it to the first buffer, and the next time, copy it to the second buffer. And on each&amp;nbsp;NRF_LIBUARTE_ASYNC_EVT_RX_DATA&amp;nbsp;event, you trigger queuing to the ble_nus_data_send.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In that case, it will reduce the chance of two events coming in too close causing the buffer to be overwritten before it is sent to the softdevice.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The softdevice has first priority, as you may know. So from time to time the&amp;nbsp;NRF_LIBUARTE_ASYNC_EVT_RX_DATA&amp;nbsp;events may be a bit delayed. By doubling the buffer you may have enough time to send the incoming packets between the connection events (every connection interval).&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Libuarte async high speed data receive and NUS transfer</title><link>https://devzone.nordicsemi.com/thread/266563?ContentTypeID=1</link><pubDate>Wed, 26 Aug 2020 15:06:34 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:04144c85-b791-46c2-a496-d2ca471ea1f1</guid><dc:creator>Aleksa</dc:creator><description>&lt;p&gt;Thank you for&amp;nbsp;your reply. I think I have pretty good parameters in terms of BLE throughput. I had a test where I just went through for loop using&amp;nbsp;&lt;span&gt;ble_nus_data_send function and I was able to achieve more than 100KBps on conn_interval = 7.5, PHY: 2MBPS, MTU = max, DLE enabled. The only thing I still wasn&amp;#39;t able to achieve was to increase conn_interval and make it work. But for our case, 100KBps is more than enough on the BLE part.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Now the&amp;nbsp;BLE_NUS_MAX_DATA_LEN == 244 bytes and function logically assert if I try to send a larger length packet. So I made sure that the libuarte async buffer is also 244 bytes and I am sending 244 bytes packets from the test board to the nordic chip.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In my mind, things should work like this. The test board transfers 244 bytes over UART. Libuarte receives the data and I get an event in which I set the flag that is caught in the main loop. Because everything is the same size there is no need for another queue or &amp;quot;gluing&amp;quot; few smaller packets into a larger one.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I am afraid that I may be approaching limits of this mechanism with libuarte and NUS which is troublesome. If that is the case do you maybe have any suggestions on how should I approach this problem to get the higher speed with reliable transfer above ~45KBps? I was also thinking about going level below and working with libuarte_drv library but I don&amp;#39;t think that that is the correct way forward.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Libuarte async high speed data receive and NUS transfer</title><link>https://devzone.nordicsemi.com/thread/266551?ContentTypeID=1</link><pubDate>Wed, 26 Aug 2020 14:39:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3c75809f-ce09-44cb-91cb-b20bb6aa6da6</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;Hello Aleksa,&lt;/p&gt;
&lt;p&gt;Your second approach seems reasonable. The first approach will work if things go slow, and you always have room in the softdevice queue, but that may not always be the case. Once ble_nus_data_send returns NRF_ERROR_RESOURCES, it will not be able to leave the interrupt, and hence not update the return value for the ble_nus_data_send().&lt;/p&gt;
&lt;p&gt;So let us discuss the second approach:&lt;/p&gt;
&lt;p&gt;If you receive a lot of uart messages, you will start filling the softdevice queue using ble_nus_data_send(). What happens if you call ble_nus_data_send, but it returns NRF_ERROR_RESOURCES, and then you get a new interrupt from the libuarte, which will overwrite the previous buffer that has not yet been successfully queued using ble_nus_data_send()? My assumption is that this happened. What should happen in this case? You can of course increase the size of the buffer, but if you keep receiving data faster than you are able to send it, the buffer will eventually fill up.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Perhaps you need to look into how you can increase the throughput on the BLE link? You can experiment with the ble_app_att_mtu_throughput example to see what connection parameters that will give the highest throughput. I think it is something like: Conn_interval = 400ms, PHY: 2MBPS, MTU = max, DLE enabled, connection event length = connection interval.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You can read the test description for this example here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.0/ble_sdk_app_att_mtu.html"&gt;https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.0/ble_sdk_app_att_mtu.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So first of all, you should use 2MBPS if possible. Then you should send as long packets as possible. This means that if you are sending a lot of small packets, try to combine them to one large before queuing it using ble_nus_data_send.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;BR,&lt;/p&gt;
&lt;p&gt;Edvin&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>