<?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>BUG: Race condition in SPI driver</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/8694/bug-race-condition-in-spi-driver</link><description>Hi, 
 I noticed that I&amp;#39;d occasionally hit an error when calling into nrf_drv_spi_transfer using the SPIM driver (SPI0_USE_EASY_DMA set). nrf_drv_spi_transfer was returning NRF_ERROR_BUSY : 
 if (p_cb-&amp;gt;transfer_in_progress)
{
 return NRF_ERROR_BUSY;</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 17 Nov 2015 01:12:49 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/8694/bug-race-condition-in-spi-driver" /><item><title>RE: BUG: Race condition in SPI driver</title><link>https://devzone.nordicsemi.com/thread/31877?ContentTypeID=1</link><pubDate>Tue, 17 Nov 2015 01:12:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9ceff138-92da-4a48-97ce-cc44be2ca171</guid><dc:creator>Philip Odom</dc:creator><description>&lt;p&gt;Your patch looks good for the SPIM code (probably that&amp;#39;s what you&amp;#39;re using, @mikevoyt). I found that a similar fix is needed for the SPI code as well. This may be the problem you&amp;#39;re having, @papyrus.&lt;/p&gt;
&lt;p&gt;Fixed code for SPI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CODE_FOR_SPI
(
    NRF_SPI_Type * p_spi = p_instance-&amp;gt;p_registers;

    p_cb-&amp;gt;p_tx_buffer       = p_tx_buffer;
    p_cb-&amp;gt;tx_buffer_length  = tx_buffer_length;
    p_cb-&amp;gt;p_rx_buffer       = p_rx_buffer;
    p_cb-&amp;gt;rx_buffer_length  = rx_buffer_length;
    p_cb-&amp;gt;bytes_transferred = 0;

			//set transfer_in_progress before doing anything to events
			//fixes a race condition that was causing issues with transfer
			//completing before flag being set.
			//see: &lt;a href="https://devzone.nordicsemi.com/question/48244/bug-race-condition-in-spi-driver/"&gt;devzone.nordicsemi.com/.../&lt;/a&gt;
    if (p_cb-&amp;gt;handler)
    {
        p_cb-&amp;gt;transfer_in_progress = true;
    }

    nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);

    // Start the transfer by writing some byte to the TXD register;
    // if TX buffer is not empty, take the first byte from this buffer,
    // otherwise - use over-run character.
    nrf_spi_txd_set(p_spi,
        (tx_buffer_length &amp;gt; 0 ?  p_tx_buffer[0] : p_cb-&amp;gt;orc));
    // TXD register is double buffered, so next byte to be transmitted can
    // be written immediately, if needed, i.e. if TX or RX transfer is to
    // be more that 1 byte long. Again - if there is something more in TX
    // buffer send it, otherwise use over-run character.
    if (tx_buffer_length &amp;gt; 1)
    {
        nrf_spi_txd_set(p_spi, p_tx_buffer[1]);
    }
    else if (rx_buffer_length &amp;gt; 1)
    {
        nrf_spi_txd_set(p_spi, p_cb-&amp;gt;orc);
    }

    // For blocking mode (user handler not provided) wait here for READY
    // events (indicating that the byte from TXD register was transmitted
    // and a new incoming byte was moved to the RXD register) and continue
    // transaction until all requested bytes are transferred.
    // In non-blocking mode - IRQ service routine will do this stuff.
    if (!p_cb-&amp;gt;handler)
    {
        do {
            while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
            nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
        } while (transfer_byte(p_spi, p_cb));
    }
)
&lt;/code&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: BUG: Race condition in SPI driver</title><link>https://devzone.nordicsemi.com/thread/31876?ContentTypeID=1</link><pubDate>Mon, 28 Sep 2015 18:32:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0e5d56e9-dc90-46dc-ad99-a7737187c8f8</guid><dc:creator>Mike Voytovich</dc:creator><description>&lt;p&gt;The patch in your first comment looks correct to me.
Note that if you&amp;#39;re not setting &lt;code&gt;p_cb-&amp;gt;transfer_in_progress = true;&lt;/code&gt; before triggering the event, the driver and your application will never know when the SPIM transfer is actually in progress, so I don&amp;#39;t believe that&amp;#39;s a legitimate patch...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: BUG: Race condition in SPI driver</title><link>https://devzone.nordicsemi.com/thread/31875?ContentTypeID=1</link><pubDate>Sat, 26 Sep 2015 03:32:15 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9a70910c-ee4f-4655-bdf9-24153ca1c3c3</guid><dc:creator>Papyrus</dc:creator><description>&lt;p&gt;So, as per my comment to the other answer,  The patch did not solve this for me, albeit it&amp;#39;s possible I did not apply it correctly.  (see comment above).&lt;/p&gt;
&lt;p&gt;BUT, I did discover a &lt;strong&gt;simpler fix that solved this for me&lt;/strong&gt;, and that&amp;#39;s simply inserting one line of code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;p_cb-&amp;gt;transfer_in_progress = false;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Right before the last line of &lt;code&gt;nrf_drv_spi_transfer&lt;/code&gt; as shown below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ret_code_t nrf_drv_spi_transfer(nrf_drv_spi_t const * const p_instance,
                                uint8_t const * p_tx_buffer,
                                uint8_t         tx_buffer_length,
                                uint8_t       * p_rx_buffer,
                                uint8_t         rx_buffer_length)

    //SPI stuff...
    //SPI stuff...
    //SPI stuff...
    
    p_cb-&amp;gt;transfer_in_progress = false; 
    return NRF_SUCCESS;
}
&lt;/code&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: BUG: Race condition in SPI driver</title><link>https://devzone.nordicsemi.com/thread/31874?ContentTypeID=1</link><pubDate>Sat, 26 Sep 2015 03:27:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9c89cbaf-c8b9-4d4b-9521-e2e7962c890e</guid><dc:creator>Papyrus</dc:creator><description>&lt;p&gt;I have also observed this, and tried to apply this patch to nrf_drv_spi.c, in v0.9.1 SDK, and I found that error was still there.  Both compiler optimization, -O0 and -O3, produce this error.&lt;/p&gt;
&lt;p&gt;It would be good if someone could verify that I applied the patch correctly.  Please observe my code below for &lt;code&gt;nrf_drv_spi_transfer&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ret_code_t nrf_drv_spi_transfer(nrf_drv_spi_t const * const p_instance,
                                uint8_t const * p_tx_buffer,
                                uint8_t         tx_buffer_length,
                                uint8_t       * p_rx_buffer,
                                uint8_t         rx_buffer_length)
{
    spi_control_block_t * p_cb  = &amp;amp;m_cb[p_instance-&amp;gt;drv_inst_idx];
    ASSERT(p_cb-&amp;gt;state == NRF_DRV_STATE_POWERED_ON);
    ASSERT(p_tx_buffer != NULL || tx_buffer_length == 0);
    ASSERT(p_rx_buffer != NULL || rx_buffer_length == 0);

    if (p_cb-&amp;gt;transfer_in_progress)
    {
        return NRF_ERROR_BUSY;
    }

    // Finish zero-length transfers immediately.
    if (tx_buffer_length == 0 &amp;amp;&amp;amp; rx_buffer_length == 0)
    {
        return NRF_SUCCESS;
    }

    // Activate Slave Select signal, if it is to be used.
    if (p_cb-&amp;gt;ss_pin != NRF_DRV_SPI_PIN_NOT_USED)
    {
        nrf_gpio_pin_clear(p_cb-&amp;gt;ss_pin);
    }

    CODE_FOR_SPIM
    (
        // EasyDMA requires that transfer buffers are placed in Data RAM region;
        // signal error if they are not.
        if ((p_tx_buffer != NULL &amp;amp;&amp;amp; !nrf_drv_is_in_RAM(p_tx_buffer)) ||
            (p_rx_buffer != NULL &amp;amp;&amp;amp; !nrf_drv_is_in_RAM(p_rx_buffer)))
        {
            return NRF_ERROR_INVALID_ADDR;
        }

        NRF_SPIM_Type * p_spim = p_instance-&amp;gt;p_registers;

        nrf_spim_tx_buffer_set(p_spim, p_tx_buffer, tx_buffer_length);
        nrf_spim_rx_buffer_set(p_spim, p_rx_buffer, rx_buffer_length);

        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_ENDTX);
        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_ENDRX);
        p_cb-&amp;gt;tx_done = false;
        p_cb-&amp;gt;rx_done = false;
				// Patch as per: &lt;a href="https://devzone.nordicsemi.com/question/48244/bug-race-condition-in-spi-driver/"&gt;devzone.nordicsemi.com/.../&lt;/a&gt; 
//        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STOPPED); // Removed as per patch 

//        nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START); // Removed as per patch 

        if (p_cb-&amp;gt;handler)
        {
            p_cb-&amp;gt;transfer_in_progress = true;
        }
   //     else  // Removed as per patch 
				nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STOPPED); // Added as per patch 
				nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START); // Added as per patch 
				
				if (!p_cb-&amp;gt;handler)// Added as per patch 
        {
            while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_ENDTX) ||
                   !nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_ENDRX)) {}

            // Stop the peripheral after transaction is finished.
            nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_STOP);
            while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STOPPED)) {}
        }
    )
....
....
....
....
&lt;/code&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: BUG: Race condition in SPI driver</title><link>https://devzone.nordicsemi.com/thread/31873?ContentTypeID=1</link><pubDate>Thu, 13 Aug 2015 11:18:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:be0eeda9-c41f-40bf-81a1-f134713f5ae7</guid><dc:creator>Krzysztof Chruscinski</dc:creator><description>&lt;p&gt;hi,&lt;/p&gt;
&lt;p&gt;Thank you for reporting the bug, we will fix it in next release. Patch looks reasonable.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>