<?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>nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/28297/nrf51422-sdk11-app_uart_fifo-race-condition-and-fix</link><description>Yet another app_uart_fifo question.
I&amp;#39;m using SDK 11 with uVision.
It is my expectation that, if using HW flow control and a FIFO to RX, no received characters should be dropped at all, under any conditions. 
 I&amp;#39;ve noticed errors thrown (UART driver</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Sun, 17 Dec 2017 16:48:52 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/28297/nrf51422-sdk11-app_uart_fifo-race-condition-and-fix" /><item><title>RE: nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/thread/111746?ContentTypeID=1</link><pubDate>Sun, 17 Dec 2017 16:48:52 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e65e03fc-6f25-4e43-94bf-788f1682d970</guid><dc:creator>shadowncs</dc:creator><description>&lt;p&gt;SDK12 has this issue fixed. As Hung Bui pointed out, there is still a race condition in SDK12 however it is benign if using a queue with length more than 1.
If you want SDK12 to only call app handler when the first character is received, as opposed to when every character is received, you can modify app_uart_fifo.c like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Notify that there are data available.
else if (FIFO_LENGTH(m_rx_fifo) == 1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;== 1 instead of != 0&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/thread/111744?ContentTypeID=1</link><pubDate>Fri, 15 Dec 2017 23:49:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7ea00907-f4f0-4236-8601-3cf0bf1fcc9b</guid><dc:creator>shadowncs</dc:creator><description>&lt;p&gt;Unrelated question but I&amp;#39;n a n00b and you probably know this. How can I use SDK12 with uVision 5.24?
edit: nevermind, I figured it out.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/thread/111745?ContentTypeID=1</link><pubDate>Fri, 15 Dec 2017 12:51:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0e0199e9-605e-4a74-9241-e205a653f159</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;I&amp;#39;m not 100% certain on why we changed the event handling. I assume, in some application we don&amp;#39;t want to handle every time there is a byte in the buffer but rather wait til there is a number of byte in the buffer to extract. Then having an event for each of the byte would be useful.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/thread/111743?ContentTypeID=1</link><pubDate>Thu, 14 Dec 2017 20:01:28 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b7e2ebce-586b-43da-bdd7-ec53bfb926c8</guid><dc:creator>shadowncs</dc:creator><description>&lt;p&gt;Thanks. I&amp;#39;ll take a closer look at SDK12 implementation.
I didn&amp;#39;t like that SDK12 calls the application uart callback for every byte received. That is IMHO not needed so will also look if that can be improved to only call the callback if the FIFO is empty, on first received byte.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/thread/111742?ContentTypeID=1</link><pubDate>Thu, 14 Dec 2017 15:27:34 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:aceeeb47-06fe-4a3a-8c69-66fdfcf21805</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Thanks for the explanation. I agree on the part that we should read the byte out of the buffer before we start RX again. This was the change in the newer SDK as I mentioned above.
In the newer SDK we also do not read the number of bytes in the buffer inside app_uart_get() but we use a global variable that being set inside uart_event_handler(NRF_DRV_UART_EVT_RX_DONE)  and the fifo is full (m_rx_ovf).&lt;/p&gt;
&lt;p&gt;Doing this we avoid scheduling RX twice when we have only one slot as you described.&lt;/p&gt;
&lt;p&gt;However we may still have a race condition situation when m_rx_ovf is not set when we read it, but then it &amp;#39;s set when we are getting the byte from fifo out. This will result in that we don&amp;#39;t schedule RX when we should.  But, this can be solved if we keep calling app_uart_get() until the buffer is empty.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/thread/111741?ContentTypeID=1</link><pubDate>Thu, 14 Dec 2017 00:13:34 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:914b887a-f695-4475-94ba-e8bcca9589f6</guid><dc:creator>shadowncs</dc:creator><description>&lt;p&gt;Bui, sorry if what follows is not super-clear as I said it took me a few days to go thru this.&lt;/p&gt;
&lt;p&gt;I have source and examples to demonstrate each point if that helps.&lt;/p&gt;
&lt;p&gt;First, the condition to start a read is wrong in app_uart_get. I will prove with an example:
Let&amp;#39;s have a FIFO with N-2 elements. Another character arrives and uart_event_handler(NRF_DRV_UART_EVT_RX_DONE) gets called. Since it adds one element, FIFO now has N-1 elements, the ISR calls nrf_drv_uart_rx.&lt;/p&gt;
&lt;p&gt;app_uart_get gets called, FIFO_LENGTH(m_rx_fifo) == m_rx_fifo.buf_size_mask is true so app_uart_get also calls nrf_drv_uart_rx. Now, if the timing of next byte is just right, we will receive 2 characters and error out with APP_UART_FIFO_ERROR. This is pretty easy to reproduce with a short 32B RX queue and say 100 chars pasted at once into the serial terminal.&lt;/p&gt;
&lt;p&gt;I tried fixing app_uart_get by only starting a new RX when FIFO_LENGTH(m_rx_fifo) &amp;gt; m_rx_fifo.buf_size_mask but of course then we&amp;#39;re scheduling a RX before reading the full FIFO, potentially overflowing it before we get to read from it. There is no getting around the fact: we first must read the FIFO before we schedule RX.&lt;/p&gt;
&lt;p&gt;So I modified app_uart_get to read FIFO first and then check for length and schedule RX if length is N-1 (we just read the last element).&lt;/p&gt;
&lt;p&gt;However this does not fix the issue, as next example proves:&lt;/p&gt;
&lt;p&gt;Having a FIFO with N-1 elements. RX is active waiting for the next byte. app_uart_get gets called, dequeues 1B (we&amp;#39;re at N-2 bytes in FIFO) and execution is interrupted by ISR delivering the N-1&amp;#39;th byte. ISR also schedules the next RX. Execution is resumed however now FIFO_LENGTH = N-1 which makes it look like we just read the last element and app_uart_get schedules RX. Therefore we again have 2 RX&amp;#39;es scheduled and we may receive 2 bytes, errorin out on the FIFO overflow.&lt;/p&gt;
&lt;p&gt;Proposed solution is to make fifo read-and-test-if-it-was-full an atomic operation.&lt;/p&gt;
&lt;p&gt;Since reading now involves a critical section, I just made a get array for ehnhanced performance.&lt;/p&gt;
&lt;p&gt;PS this html editor is horrible - no newlines!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF51422 SDK11 app_uart_fifo race condition and fix</title><link>https://devzone.nordicsemi.com/thread/111740?ContentTypeID=1</link><pubDate>Wed, 13 Dec 2017 15:01:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ffa3affc-f070-488c-9835-da4b07a10df0</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi shadow,&lt;/p&gt;
&lt;p&gt;Could you elaborate a little bit more on how you detect the error ?
Please correct me if I&amp;#39;m wrong but in app_uart_get() we basically pop one byte out from the fifo and in uart_event_handler(NRF_DRV_UART_EVT_RX_DONE)  we add one byte into the fifo. So even if the event handler interrupt the app_uart_get() it shouldn&amp;#39;t cause a byte missing or duplicating bytes ? Not 100% sure there is a race condition here.&lt;/p&gt;
&lt;p&gt;One thing we tried to fix in the later SDK is to pop the byte out before checking if it&amp;#39;s full or not as we may end up receiving byte before we get the byte out at the end of the function.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>