<?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>Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/75420/infinite-loop-in-nrfx_uarte_uninit</link><description>nRF52840, SD140, SDK 17.0.2 
 
 We&amp;#39;re using UARTE to communicate with a peer MCU. We&amp;#39;re using hardware flow control (CTS and RTS are enabled) and the baudrate is 115200. The traces are less than 2cm. We do not control any firmware on the peer MCU; it</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 25 May 2021 13:48:49 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/75420/infinite-loop-in-nrfx_uarte_uninit" /><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311507?ContentTypeID=1</link><pubDate>Tue, 25 May 2021 13:48:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:22c0b574-2b28-4e0c-ba21-3b4b8eafa96f</guid><dc:creator>Susheel Nuguru</dc:creator><description>&lt;p&gt;Sounds like a plan. Good luck :)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311502?ContentTypeID=1</link><pubDate>Tue, 25 May 2021 13:46:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:48160ab9-d615-422d-b63c-654f07000a21</guid><dc:creator>wcauchois</dc:creator><description>&lt;p&gt;Ah, that&amp;#39;s very insightful, thanks for the suggestion! I&amp;#39;ll audit the uses of nrfx_uarte_tx() in our code and make sure we never send it in an interrupt (other than a UARTE interrupt, since that&amp;#39;s disabled before the uninit() loop)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311496?ContentTypeID=1</link><pubDate>Tue, 25 May 2021 13:40:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:232afb7f-d660-4183-8c1a-37378cc00c97</guid><dc:creator>Susheel Nuguru</dc:creator><description>&lt;p&gt;Yes, you are spot on to the text in the Low Power section which the developer also referred in his response. So the reason according to him to have wait states (forever loop was mistake, timeouts suits best) was that it is written in the PS to do so.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There could also be a race condition in your code, If you have this &lt;span&gt;NRFX_WAIT_FOR&amp;nbsp;&lt;/span&gt;interrupted with some interrupt context where you call&amp;nbsp;nrfx_uarte_tx, then this function will clear the TXSTOPPED event before it triggers TASKS_STARTTX. And after this when the context comes back to the NRFX_WAIT_FOR then it will never have this event coming as it is already cleared by nrfx_uarte_tx.&amp;nbsp; So I think we need to have a mutual exclusion between uninit and nrfx_uarte_tx so that there are no race conditions involved.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311485?ContentTypeID=1</link><pubDate>Tue, 25 May 2021 13:23:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9c61d801-e1f6-4e6e-93f2-bced817f6d07</guid><dc:creator>wcauchois</dc:creator><description>&lt;p&gt;I think the nRF52840 Product Specification v1.2 (&lt;a href="https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.2.pdf"&gt;https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.2.pdf&lt;/a&gt;) informs us here:&lt;/p&gt;
&lt;p&gt;6.34.7 Low Power (page 514)&lt;/p&gt;
&lt;p&gt;&amp;quot;The STOPTX and STOPRX tasks may not be always needed (the peripheral might already be stopped), but if STOPTX and/or STOPRX is sent, software shall wait until the TXSTOPPED and/or RXTO event is received in response, before disabling the peripheral through the ENABLE register.&amp;quot;&lt;/p&gt;
&lt;p&gt;The specification uses the word &amp;quot;shall&amp;quot;. The document doesn&amp;#39;t define what &amp;quot;shall&amp;quot; means, which is unfortunate, but it almost always means &amp;quot;if you don&amp;#39;t do this, really bad things will happen and it&amp;#39;s unclear&amp;nbsp;if the part will work correctly afterwards&amp;quot;.&lt;/p&gt;
&lt;p&gt;So, you&amp;#39;re suggesting that maybe we don&amp;#39;t need to wait for RXTO/TXSTOPPED before disabling via ENABLE, but the part specification clearly says that we &lt;strong&gt;shall&lt;/strong&gt; do that. Then at the same time, we see an infinite loop waiting for this condition, and discover that a not-yet-released newer version of the loop has a timeout.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m happy using the timeout because Nordic built it. I don&amp;#39;t even need to understand why, though I&amp;#39;d like to.&lt;/p&gt;
&lt;p&gt;If I had to boil this issue down to one question, it would be: &amp;quot;After timing out waiting for RXTO / TXSTOPPED in nrfx_uarte_uninit(), is it safe to later re-initialize and resume use of that same UARTE block?&amp;quot;&lt;/p&gt;
&lt;p&gt;Do we need to wait for some amount of time before initializing it again, etc?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311413?ContentTypeID=1</link><pubDate>Tue, 25 May 2021 10:59:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5ce5c1a0-a029-4304-89d5-fc2b48051140</guid><dc:creator>Susheel Nuguru</dc:creator><description>&lt;p&gt;I have requested the developer to shed some light on this. But my feeling is that we do not need this check or wait state. But lets wait for the answer from the expert. I will comeback to you as soon as I hear something from him.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311267?ContentTypeID=1</link><pubDate>Mon, 24 May 2021 18:57:55 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:85cb1641-3d24-4b25-a096-237c07fe9d1f</guid><dc:creator>wcauchois</dc:creator><description>&lt;p&gt;That said, in our specific case, p_cb-&amp;gt;rx_buffer_length is always set to 1. We use the receive data event (ISR) to&amp;nbsp;re-engage receiver with another 1-byte buffer, so there&amp;#39;s no main-context scenario after we&amp;#39;ve enabled our receiver where rx_buffer_length is 0.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311266?ContentTypeID=1</link><pubDate>Mon, 24 May 2021 18:56:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:48315f46-1802-4d94-81a3-62f337e720ec</guid><dc:creator>wcauchois</dc:creator><description>&lt;p&gt;I think these questions could all be answered by the author of the latest change to the NRFX library I linked above, where the infinite loop was changed to have a timeout. Since that code looks like a fix for my exact issue, and it was written by a Nordic engineer, my preference is to hear the answer rather then help explore the problem :)&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311265?ContentTypeID=1</link><pubDate>Mon, 24 May 2021 18:48:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1066538e-df86-4556-aaa2-d2e8ee1eca83</guid><dc:creator>Susheel Nuguru</dc:creator><description>[quote user=""]1. Will the UARTE ever generate the&amp;nbsp;&lt;span&gt;NRF_UARTE_EVENT_RXTO event if the peer&amp;nbsp;is not asserting RTS? That would cause an infinite loop in nrfx_uarte_uninit, since the peer is long-gone and is not asserting TX/RX/CTS/RTS at this point&lt;/span&gt;[/quote]
&lt;p&gt;&amp;nbsp;I am curious to know if you still have&amp;nbsp;p_cb-&amp;gt;rx_buffer_length non zero (ongoing transaction) while the peer sets signals of power off? In my opinion after triggering STOPTX and STOPRX tasks, the events should arrive nevertheless, but I might have to dig a more into the hardare internals if there are any conditions for this events not to arrive. Atleast there seems to be no blockers for these events from the product specification.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311258?ContentTypeID=1</link><pubDate>Mon, 24 May 2021 15:57:57 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:010ac738-6ff2-4068-a0f8-f8b844e22809</guid><dc:creator>wcauchois</dc:creator><description>&lt;p&gt;Update 2: I see that the latest version of NRFX also adds a timeout to nrfx_uarte_uninit():&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L332"&gt;https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L332&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void nrfx_uarte_uninit(nrfx_uarte_t const * p_instance)
{
    uarte_control_block_t * p_cb = &amp;amp;m_cb[p_instance-&amp;gt;drv_inst_idx];
    NRF_UARTE_Type * p_reg = p_instance-&amp;gt;p_reg;

    if (p_cb-&amp;gt;handler)
    {
        interrupts_disable(p_instance);
    }
    // Make sure all transfers are finished before UARTE is disabled
    // to achieve the lowest power consumption.
    nrf_uarte_shorts_disable(p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX);

    // Check if there is any ongoing reception.
    if (p_cb-&amp;gt;rx_buffer_length)
    {
        nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_RXTO);
        nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPRX);
    }

    nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_TXSTOPPED);
    nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPTX);

    // Wait for TXSTOPPED event and for RXTO event, provided that there was ongoing reception.
    bool stopped;

    // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
    // On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
    // (resulting in 12 bits per data byte sent), this may take up to 40 ms.
    NRFX_WAIT_FOR((nrf_uarte_event_check(p_reg, NRF_UARTE_EVENT_TXSTOPPED) &amp;amp;&amp;amp;
                  (!p_cb-&amp;gt;rx_buffer_length || nrf_uarte_event_check(p_reg, NRF_UARTE_EVENT_RXTO))),
                  40000, 1, stopped);
    if (!stopped)
    {
        NRFX_LOG_ERROR(&amp;quot;Failed to stop instance with base address: %p.&amp;quot;, (void *)p_instance-&amp;gt;p_reg);
    }

    nrf_uarte_disable(p_reg);
    pins_to_default(p_instance);

#if NRFX_CHECK(NRFX_PRS_ENABLED)
    nrfx_prs_release(p_reg);
#endif

    p_cb-&amp;gt;state   = NRFX_DRV_STATE_UNINITIALIZED;
    p_cb-&amp;gt;handler = NULL;
    NRFX_LOG_INFO(&amp;quot;Instance uninitialized: %d.&amp;quot;, p_instance-&amp;gt;drv_inst_idx);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Please also provide the details of this discovery: what exact scenarios cause this loop to exit via the timeout?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Infinite loop in nrfx_uarte_uninit()</title><link>https://devzone.nordicsemi.com/thread/311191?ContentTypeID=1</link><pubDate>Sun, 23 May 2021 20:18:07 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4854a87b-e330-4062-8608-c542634a667f</guid><dc:creator>wcauchois</dc:creator><description>&lt;p&gt;Update: I added a hacked-up second version of nrfx_uarte_uninit() that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void nrfx_uarte_uninit_2(nrfx_uarte_t const * p_instance)
{
    uarte_control_block_t * p_cb = &amp;amp;m_cb[p_instance-&amp;gt;drv_inst_idx];
    NRF_UARTE_Type * p_reg = p_instance-&amp;gt;p_reg;

    if (p_cb-&amp;gt;handler)
    {
        interrupts_disable(p_instance);
    }
    // Make sure all transfers are finished before UARTE is disabled
    // to achieve the lowest power consumption.
    nrf_uarte_shorts_disable(p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX);

    // Check if there is any ongoing reception.
    if (p_cb-&amp;gt;rx_buffer_length)
    {
        nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_RXTO);
        nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPRX);
    }

    nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_TXSTOPPED);
    nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPTX);

    nrf_delay_ms(10); // CHANGE: enough time for RXTO, don&amp;#39;t loop

    nrf_uarte_disable(p_reg);
    pins_to_default(p_instance);

#if NRFX_CHECK(NRFX_PRS_ENABLED)
    nrfx_prs_release(p_reg);
#endif

    p_cb-&amp;gt;state   = NRFX_DRV_STATE_UNINITIALIZED;
    p_cb-&amp;gt;handler = NULL;
    NRFX_LOG_INFO(&amp;quot;Instance uninitialized: %d.&amp;quot;, p_instance-&amp;gt;drv_inst_idx);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note the loop has been replaced with a 10-msec busy wait. This of course fixes the watchdog loop, but I really need guidance from a Nordic support engineer to learn if it&amp;#39;s safe or not, in addition to answers from my original post.&lt;/p&gt;
&lt;p&gt;I noted that in the SDK v15 version of this function, there is no loop. If anyone has an explanation for why that approach wasn&amp;#39;t sufficient I&amp;#39;d also like to understand that.&lt;/p&gt;
&lt;p&gt;Thanks,&lt;/p&gt;
&lt;p&gt;Bill&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>