<?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>Long interrupt latency</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/38997/long-interrupt-latency</link><description>This is almost certainly a noob (to nRF52840) programming question. 
 I have modified the peripheral/gpiote example to invoke an ISR on the falling edge of a pin signal. In the ISR I toggle another pin. 
 On a scope I see about 22 microseconds between</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 06 Dec 2018 22:12:34 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/38997/long-interrupt-latency" /><item><title>RE: Long interrupt latency</title><link>https://devzone.nordicsemi.com/thread/160643?ContentTypeID=1</link><pubDate>Thu, 06 Dec 2018 22:12:34 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c2fdd49e-1fe0-45cd-b48f-e8a374f13868</guid><dc:creator>Knud</dc:creator><description>&lt;p&gt;Thanks again for the answer a couple of months ago.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve had a chance to get back to this and dig into it further. As I suggested in the initial query, lack of experience and knowledge was the source of my problem. I may not be all that much wiser, but have learned that the main problem I was seeing with the `nrf_drv_gpiote` approach (now `nrfx_gpiote`) is that I did not understand that the irq handler was iterating through all possible events. Looking at the source code it&amp;#39;s clear that there are a few loops (corresponding to the number of channels) that eat up the time.&lt;/p&gt;
&lt;p&gt;It also did not help that I was running in full debug mode.&lt;/p&gt;
&lt;p&gt;The observed latency dependence&amp;nbsp;is easy to test by changing the value of GPIOTE_NUM_CHAN and observing the delay between the triggering pin transition and the output pin change.&lt;/p&gt;
&lt;p&gt;With a nRF528420-DK and compiling with -O3, the latency is&lt;/p&gt;
&lt;p&gt;~ 5.5 us with GPIOTE_NUM_CHAN 8&lt;/p&gt;
&lt;p&gt;~ 3.6 us with GPIOTE_NUM_CHAN 1&lt;/p&gt;
&lt;p&gt;That makes a lot more sense to me. I will want to keep the number of channels at 8 as my HW has several interrupt signals. Only one is used for something timing critical and 5.5 us is well within my margin of comfort.&lt;/p&gt;
&lt;p&gt;Again, thanks for helping me the first time and, in effect, pointing me to&amp;nbsp; better understanding.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Long interrupt latency</title><link>https://devzone.nordicsemi.com/thread/150847?ContentTypeID=1</link><pubDate>Sat, 29 Sep 2018 04:01:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7c28bc97-ca26-4f94-a50a-fb46a367e571</guid><dc:creator>Knud</dc:creator><description>&lt;p&gt;Hey, thanks so much for taking time on a Friday to educate me. Not only does this work (of course!), but it&amp;#39;s in line with my shared preference to rely on register-level programming. The only real change I had to make was to be sure to make sure the Makefile was not including the gpiote, ppi, and timer sources.&lt;/p&gt;
&lt;p&gt;Many thanks!&lt;/p&gt;
&lt;p&gt;steven&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Long interrupt latency</title><link>https://devzone.nordicsemi.com/thread/150840?ContentTypeID=1</link><pubDate>Fri, 28 Sep 2018 22:33:55 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:38ad41b7-b664-47fd-9b50-8f558daf1b80</guid><dc:creator>AmbystomaLabs</dc:creator><description>&lt;p&gt;I noticed no one had responded and it was Friday so good time to do some fun coding.&lt;/p&gt;
&lt;p&gt;I implemented what you specified but did it directly with the registers as I normally don&amp;#39;t use most drivers to keep the code efficient. Since I mainly do RF, I didn&amp;#39;t have a function generator but I did have some code that implemented two square wave generators on the nRF.&amp;nbsp; So, basically you connect p0.4 with p1.12 on the DK and presto p1.8 is a duplicate of the signal after passing through an IRQ.&lt;/p&gt;
&lt;p&gt;I should point out that servicing this in an IRQ isn&amp;#39;t the best approach but I assume you have your reasons.&amp;nbsp; If you do it directly in PPI/GPIOTE then there will be only 1 or 2 Pclk latency.&lt;/p&gt;
&lt;p&gt;However even with the IRQ servicing time, the latency was only about 728nsec which corresponds to about 46 opcodes to get there.&amp;nbsp; Not bad in my opinion.&lt;/p&gt;
&lt;p&gt;Let me know if you have questions. I just shoved the code into the blinky example.&amp;nbsp; But you need to fix up the C pathways so it finds all the #includes.&lt;/p&gt;
&lt;p&gt;Here is the code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;stdbool.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;quot;nrf.h&amp;quot;
#include &amp;quot;nrf_gpiote.h&amp;quot;
#include &amp;quot;nrf_gpio.h&amp;quot;
#include &amp;quot;boards.h&amp;quot;
//#include &amp;quot;nrf_drv_ppi.h&amp;quot;
//#include &amp;quot;nrf_drv_timer.h&amp;quot;
//#include &amp;quot;nrf_drv_gpiote.h&amp;quot;
#include &amp;quot;app_error.h&amp;quot;



#define MODE2 0
#define PSEL 8
#define PORT 13
#define POLARITY 16
#define OUTINIT 20
#define DIR 0
#define PULL 2
#define DRIVE 8
#define SENSE 16

void GPIOTE_IRQHandler(void)
{  
if (NRF_P1-&amp;gt;OUT&amp;amp;(0x1&amp;lt;&amp;lt;8))
{NRF_P1-&amp;gt;OUTCLR = (0x1&amp;lt;&amp;lt;8);}
else
{NRF_P1-&amp;gt;OUTSET = (0x1&amp;lt;&amp;lt;8);}

//  //RESET EVENTS
  NRF_GPIOTE-&amp;gt;EVENTS_IN[2] = 0;  
NVIC_ClearPendingIRQ(GPIOTE_IRQn);


}


/**
 * @brief Function for application main entry.
 */
int main(void)
{
    /* Configure board. */
    NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK-&amp;gt;TASKS_HFCLKSTART    = 1;

/* Wait for the external oscillator to start up */
while (NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED == 0)
{
    // Do nothing.
}

        NRF_TIMER1-&amp;gt;TASKS_STOP        = 1;                      // Stop timer, if it was running
NRF_TIMER1-&amp;gt;TASKS_CLEAR       = 1;
NRF_TIMER1-&amp;gt;MODE              = TIMER_MODE_MODE_Timer;  // Timer mode (not counter)
NRF_TIMER1-&amp;gt;EVENTS_COMPARE[0] = 0;                      // clean up possible old events
NRF_TIMER1-&amp;gt;EVENTS_COMPARE[1] = 0;
NRF_TIMER1-&amp;gt;EVENTS_COMPARE[2] = 0;
NRF_TIMER1-&amp;gt;EVENTS_COMPARE[3] = 0;

        NRF_TIMER2-&amp;gt;TASKS_STOP        = 1;                      // Stop timer, if it was running
NRF_TIMER2-&amp;gt;TASKS_CLEAR       = 1;
NRF_TIMER2-&amp;gt;MODE              = TIMER_MODE_MODE_Counter;  // Timer mode (not counter)
NRF_TIMER2-&amp;gt;EVENTS_COMPARE[0] = 0;                      // clean up possible old events
NRF_TIMER2-&amp;gt;EVENTS_COMPARE[1] = 0;
NRF_TIMER2-&amp;gt;EVENTS_COMPARE[2] = 0;
NRF_TIMER2-&amp;gt;EVENTS_COMPARE[3] = 0;


    NRF_GPIOTE-&amp;gt;CONFIG[0] =((GPIOTE_CONFIG_MODE_Task       &amp;lt;&amp;lt; GPIOTE_CONFIG_MODE_Pos)
                            |(4                         &amp;lt;&amp;lt; GPIOTE_CONFIG_PSEL_Pos)
														|(0                         &amp;lt;&amp;lt; GPIOTE_CONFIG_PORT_Pos)
                            |(GPIOTE_CONFIG_POLARITY_Toggle &amp;lt;&amp;lt; GPIOTE_CONFIG_POLARITY_Pos)
                            |(GPIOTE_CONFIG_OUTINIT_Low     &amp;lt;&amp;lt; GPIOTE_CONFIG_OUTINIT_Pos));

    NRF_GPIOTE-&amp;gt;CONFIG[1] =((GPIOTE_CONFIG_MODE_Task       &amp;lt;&amp;lt; GPIOTE_CONFIG_MODE_Pos)
                            |(7                         &amp;lt;&amp;lt; GPIOTE_CONFIG_PSEL_Pos)
														|(0                         &amp;lt;&amp;lt; GPIOTE_CONFIG_PORT_Pos)
                            |(GPIOTE_CONFIG_POLARITY_Toggle &amp;lt;&amp;lt; GPIOTE_CONFIG_POLARITY_Pos)
                            |(GPIOTE_CONFIG_OUTINIT_Low     &amp;lt;&amp;lt; GPIOTE_CONFIG_OUTINIT_Pos));


    NRF_PPI-&amp;gt;CH[0].EEP  = (uint32_t)&amp;amp;NRF_TIMER1-&amp;gt;EVENTS_COMPARE[0];
    NRF_PPI-&amp;gt;CH[0].TEP  = (uint32_t)&amp;amp;NRF_GPIOTE-&amp;gt;TASKS_OUT[0];
		NRF_PPI-&amp;gt;FORK[0].TEP = (uint32_t)&amp;amp;NRF_TIMER2-&amp;gt;TASKS_COUNT;
		
		NRF_PPI-&amp;gt;CH[1].EEP  = (uint32_t)&amp;amp;NRF_TIMER2-&amp;gt;EVENTS_COMPARE[0];
    NRF_PPI-&amp;gt;CH[1].TEP  = (uint32_t)&amp;amp;NRF_GPIOTE-&amp;gt;TASKS_OUT[1];


    NRF_PPI-&amp;gt;CHEN       = (PPI_CHEN_CH0_Enabled &amp;lt;&amp;lt; PPI_CHEN_CH0_Pos)|(PPI_CHEN_CH1_Enabled &amp;lt;&amp;lt; PPI_CHEN_CH1_Pos);

    NRF_TIMER1-&amp;gt;SHORTS      = (1 &amp;lt;&amp;lt; TIMER_SHORTS_COMPARE0_CLEAR_Pos); 
    NRF_TIMER1-&amp;gt;PRESCALER   = 0; 
    NRF_TIMER1-&amp;gt;CC[0]       = 16;   
		
		NRF_TIMER2-&amp;gt;SHORTS      = (1 &amp;lt;&amp;lt; TIMER_SHORTS_COMPARE0_CLEAR_Pos); 
    NRF_TIMER2-&amp;gt;PRESCALER   = 0; 
    NRF_TIMER2-&amp;gt;CC[0]       = 400;   
		
    NRF_TIMER2-&amp;gt;TASKS_START = 1;
		NRF_TIMER1-&amp;gt;TASKS_START = 1;
		




//NRF_P1-&amp;gt;PIN_CNF[12]=(0x3000C);


		
  NRF_P1-&amp;gt;PIN_CNF[12] = (0x00 &amp;lt;&amp;lt; DIR) | (0x03 &amp;lt;&amp;lt; PULL) | (0x00 &amp;lt;&amp;lt; DRIVE) | (0x00 &amp;lt;&amp;lt; SENSE);
//  
//PPI OUTPUT
NRF_P1-&amp;gt;PIN_CNF[8] = (0x01 &amp;lt;&amp;lt; 0x00);
//
//  //input config
  NRF_GPIOTE-&amp;gt;CONFIG[2] = (0x01 &amp;lt;&amp;lt; MODE2) | (0x0C &amp;lt;&amp;lt; PSEL) | (0x01 &amp;lt;&amp;lt; PORT) | (0x03 &amp;lt;&amp;lt; POLARITY);
//  


//  
//  //RESET EVENTS
  NRF_GPIOTE-&amp;gt;EVENTS_IN[2] = 0;  
	
NVIC_DisableIRQ(GPIOTE_IRQn);
NVIC_ClearPendingIRQ(GPIOTE_IRQn);

NRF_GPIOTE-&amp;gt;INTENSET = GPIOTE_INTENSET_IN2_Msk;

NVIC_SetPriority(GPIOTE_IRQn, 3); //optional: set priority of interrupt
NVIC_EnableIRQ(GPIOTE_IRQn);


		
		while (1)
{
    // Do nothing.
}

}

/**
 *@}
 **/&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Long interrupt latency</title><link>https://devzone.nordicsemi.com/thread/150780?ContentTypeID=1</link><pubDate>Thu, 27 Sep 2018 23:41:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:25a724e3-e65f-4b95-887b-1c6b08bea7ab</guid><dc:creator>Knud</dc:creator><description>&lt;p&gt;Oops, should say no softdevice.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>