<?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>SPI double buffering on TX</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/36431/spi-double-buffering-on-tx</link><description>I have a use case where I need to send a sequence of 2 byte bursts as SPI master. The data is generated on the fly and the algorithm would be able to saturate the 8Mbit/s SPI on nRF52832, so I&amp;#39;d like to optimize the throughput and latency by interleaving</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 10 Aug 2018 04:55:26 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/36431/spi-double-buffering-on-tx" /><item><title>RE: SPI double buffering on TX</title><link>https://devzone.nordicsemi.com/thread/143651?ContentTypeID=1</link><pubDate>Fri, 10 Aug 2018 04:55:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:60935aa6-666b-47e4-aa2f-a4281af4221a</guid><dc:creator>Nenik</dc:creator><description>&lt;p&gt;So this is the best code I could get working reliably:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;      if (first) {
        // blindly fill the double buffered output
        NRF_SPI0-&amp;gt;TXD = col &amp;gt;&amp;gt; 8;
        NRF_SPI0-&amp;gt;TXD = (uint8_t)col;
        first = false;
      }  else {
        while(!NRF_SPI0-&amp;gt;EVENTS_READY);
        NRF_SPI0-&amp;gt;EVENTS_READY = 0;
        (void)NRF_SPI0-&amp;gt;RXD;

        NRF_SPI0-&amp;gt;TXD = col &amp;gt;&amp;gt; 8;

        while(!NRF_SPI0-&amp;gt;EVENTS_READY);
        NRF_SPI0-&amp;gt;EVENTS_READY = 0;
        (void)NRF_SPI0-&amp;gt;RXD;
        NRF_SPI0-&amp;gt;TXD = (uint8_t)col;        
      }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I.e. I have to both reset the READY flag &lt;strong&gt;and&lt;/strong&gt; read the RDX register. And do so in that particular order, including the TXD write. It still improves the throughput from 5.7Mbps to about 7Mbps.&lt;/p&gt;
&lt;p&gt;Interestingly enough, my application still works if I comment out the second EVENTS_READY clearing, which improves the performance further, up to 7.5-7.7Mbps, though I am not comfortable going there w/o understanding &lt;strong&gt;why&lt;/strong&gt; that still works.&lt;/p&gt;
&lt;p&gt;I might investigate the EasyDMA approach later, in case it has low-enough overhead when used for back-to-back 2B-only transactions, though I am fine with 7Mbps already.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SPI double buffering on TX</title><link>https://devzone.nordicsemi.com/thread/142298?ContentTypeID=1</link><pubDate>Wed, 01 Aug 2018 06:51:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8d760ec4-3a21-4172-98e9-b8fbb513f424</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;Sorry. I forgot that. Yes, you do have to clear the ready event.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Reading from the text after the figure:&lt;br /&gt;&amp;quot;...Therefore, it is important that you always clear the READY event, even if the RXD register and the data that is being received is not used.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Edvin&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SPI double buffering on TX</title><link>https://devzone.nordicsemi.com/thread/142289?ContentTypeID=1</link><pubDate>Wed, 01 Aug 2018 04:52:00 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:267dd5db-32d1-4fcf-aa47-dae61a4b23de</guid><dc:creator>Nenik</dc:creator><description>&lt;p&gt;Ah, so I always need to be one byte ahead? I&amp;#39;ll try that, though I&amp;#39;d expect to be able to let the pipeline drain. Also, don&amp;#39;t I need to clear the READY flag between the bytes?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SPI double buffering on TX</title><link>https://devzone.nordicsemi.com/thread/142192?ContentTypeID=1</link><pubDate>Tue, 31 Jul 2018 13:29:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:37d0fe2d-15a1-4cfe-8f40-44bd35d15391</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;The chapter that you linked to (&lt;a href="http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fspi.html&amp;amp;cp=2_1_0_47_0_2&amp;amp;anchor=concept_ov2_f54_sr" target="_blank" rel="noopener noreferrer"&gt;here&lt;/a&gt;),&amp;nbsp;if you look at the diagram beneath the text bolk, you can see the events that appear. As you see you will get a READY event for each byte. This means that you can queue one byte on each READY event. If you need to queue two at the time, you must wait for two.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Something like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;produce();
TXD = data &amp;gt;&amp;gt; 8;
TXD = (uint8_t)data;

while(true)
{
    produce();
    while(!READY){};
    TXD = data &amp;gt;&amp;gt; 8;
    while(!READY){};
    TXD = (uint8_t)data;
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SPI double buffering on TX</title><link>https://devzone.nordicsemi.com/thread/141261?ContentTypeID=1</link><pubDate>Wed, 25 Jul 2018 07:26:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6d7cad11-421e-4309-b94d-57be6991244d</guid><dc:creator>Nenik</dc:creator><description>&lt;p&gt;No, but I am not using interrupts either. Do I need to enable the interrupts to get EVENTS_READY properly delivered?&lt;/p&gt;
&lt;p&gt;I doubt, since the sequence of sendByte(); waitForReady(); sendByte(); waitForReady(); (as descrubed in my first code snippet in OP) works reliably and EVENTS_READY is delivered just fine each time.&lt;/p&gt;
&lt;p&gt;The only thing that doesn&amp;#39;t work for me is to use the double-buffering, sending two bytes in a row (as suggested by PS, section 48.1.3), and only then checking for finished transaction...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SPI double buffering on TX</title><link>https://devzone.nordicsemi.com/thread/140422?ContentTypeID=1</link><pubDate>Tue, 17 Jul 2018 15:14:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:93fb5295-4245-4ef7-a1e4-3c7f9aba32ba</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Have you set the SPI&amp;#39;s INTENSET register to enable the EVENTS_READY event properly? Please see &lt;a href="http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fspi.html&amp;amp;anchor=register.INTENSET" target="_blank" rel="noopener noreferrer"&gt;this page on infocenter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&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></channel></rss>