<?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>nRF52840: How do I read the &amp;quot;Event Register&amp;quot;?</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/93235/nrf52840-how-do-i-read-the-event-register</link><description>nRF52840, SDK 17.0.2, SD140 v7.0.1 
 
 My firmware application is happily sleeping via calls to nrf_pwr_mgmt_run(), waking up to service interrupts and do work, then going to back to sleep. 
 
 Sometimes, something happens shortly after a BLE central</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 27 Oct 2022 13:55:22 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/93235/nrf52840-how-do-i-read-the-event-register" /><item><title>RE: nRF52840: How do I read the "Event Register"?</title><link>https://devzone.nordicsemi.com/thread/392862?ContentTypeID=1</link><pubDate>Thu, 27 Oct 2022 13:55:22 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:64918e04-3bce-4428-8fe9-39db112a4ac3</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Thanks, I don&amp;#39;t read assembly that well, but it makes sense now that you have explained it.&lt;/p&gt;
[quote userid="105441" url="~/f/nordic-q-a/93235/nrf52840-how-do-i-read-the-event-register/392846"]I&amp;#39;m actually planning on leaving this in our production firmware, so we can get IRQ histograms to better understand the system.[/quote]
&lt;p&gt;I guess the added interrupt latency should be minimal and that it&amp;#39;s is going to work fine. Still, I would have been more comfortable if it was only used for profiling in debug builds. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840: How do I read the "Event Register"?</title><link>https://devzone.nordicsemi.com/thread/392846?ContentTypeID=1</link><pubDate>Thu, 27 Oct 2022 13:16:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:20f14ad5-afc5-492b-a59e-720bf597a257</guid><dc:creator>charles_fi</dc:creator><description>&lt;p&gt;Ha, thanks :)&amp;nbsp;&lt;/p&gt;
&lt;p&gt;On line 29, the &amp;quot;r12&amp;quot; register is loaded up with the offset into a vector table that represents the ISR corresponding to the current IRQ.&lt;/p&gt;
&lt;p&gt;This function assumes that the &amp;quot;true&amp;quot; (SoftDevice) vector table lives at address 0, which means that the function we want to call lives at &amp;quot;0 + *r12&amp;quot;. Line 35 simply forces an unconditional branch to that ISR, so SoftDevice (and our application) get all of their respective interrupt handlers called.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m actually planning on leaving this in our production firmware, so we can get IRQ histograms to better understand the system.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840: How do I read the "Event Register"?</title><link>https://devzone.nordicsemi.com/thread/392830?ContentTypeID=1</link><pubDate>Thu, 27 Oct 2022 12:40:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e8c70f91-5512-47b9-94eb-5686fe0f1624</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;This looks like clever way to do it! Just curious, does the Softdevice IRQ vector get forwarded back to the softdevice again after it has been run through your &amp;#39;cpu_isr_shim&amp;#39;?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840: How do I read the "Event Register"?</title><link>https://devzone.nordicsemi.com/thread/392718?ContentTypeID=1</link><pubDate>Thu, 27 Oct 2022 01:04:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d6beafe6-c49d-4799-bc5c-3721b8f9284d</guid><dc:creator>charles_fi</dc:creator><description>&lt;p&gt;As an update for anyone searching for IRQ activity data, I wrote the following assembly function to capture all IRQ activity, including SoftDevice.&lt;/p&gt;
&lt;p&gt;In C, make a 65-element table of uint32_t containing `cpu_isr_shim` for every entry. Set SCB-&amp;gt;VTOR to the address of&amp;nbsp;this array (it&amp;#39;s a vector table), and the histogram will populate on every IRQ. Call cpu_isr_get_histogram to retrieve the histogram of uint32_t entries, one per IRQ #.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s cool to see the SoftDevice RADIO interrupt etc.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;.syntax unified

.section .data
.align 4
s_irq_histogram:
  .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

.section .text

.align 2
.globl cpu_isr_get_histogram
.thumb_func
cpu_isr_get_histogram:
  ldr r0, [pc, #0]
  bx lr
  .word s_irq_histogram

.globl cpu_isr_shim
.thumb_func
.align 2
cpu_isr_shim:             // preserves regs except r12, thunks to ISR
  push {r0, r1}           // store r0 + r1
  ldr r12, [pc, #32]      // r12 = SCB
  ldr r12, [r12, #4]      // r12 = SCB-&amp;gt;ICSR
  ubfx r12, r12, #0, #9   // r12 = (SCB-&amp;gt;ICSR &amp;amp; 0x1FF) &amp;lt;irqn in 1-64&amp;gt;
  lsl r12, r12, #2        // r12 = irqn * 4
  ldr r0, [pc, #20]       // r0 = s_irq_histogram
  ldr r1, [r0, r12]       // r1 = s_irq_histogram[irqn * 4]
  adds r1, #1             // ++r1
  str r1, [r0, r12]       // s_irq_histogram[irqn * 4] = r1
  pop {r0, r1}            // restore r0 and r1
  ldr pc, [r12]           // unconditional jump to VTOR[irqn * 4]
  .word 0xe000ed00        // Address of SCB in the memory map
  .word s_irq_histogram&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840: How do I read the "Event Register"?</title><link>https://devzone.nordicsemi.com/thread/392650?ContentTypeID=1</link><pubDate>Wed, 26 Oct 2022 13:38:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:53f58f57-17e8-4b5a-ab6e-8a3b0255c123</guid><dc:creator>charles_fi</dc:creator><description>&lt;p&gt;Thanks very much for the detailed and quick response, I appreciate it!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Best,&lt;/p&gt;
&lt;p&gt;Charles&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840: How do I read the "Event Register"?</title><link>https://devzone.nordicsemi.com/thread/392563?ContentTypeID=1</link><pubDate>Wed, 26 Oct 2022 10:12:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a5915e0b-d0f3-443a-adae-37e26510b4d1</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello Charles,&lt;/p&gt;
&lt;p&gt;Like the __WFE instruction, a single call to nrf_pwr_mgmt_run() will not make the device enter sleep if the event register has been set (e.g. after servicing an ISR). This is why you will see that this function is always placed within a loop in our code examples.&lt;/p&gt;
&lt;p&gt;In your case, could it be an option to place the nrf_pwr_mgmt_run() function in a spinlock loop? Something like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;do {
    nrf_pwr_mgmt_run();
} while (app_wakeup == false);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;where &amp;quot;app_wakeup&amp;quot; is a state flag set in your interrupt handler(s) to tell the program when to exit sleep.&lt;/p&gt;
[quote user=""]I&amp;#39;m trying to trace down the source of what&amp;#39;s immediately waking the nRF52840 back up, so I can fix it.[/quote]
&lt;p&gt;You can try to check which interrupt it was woken up by with this code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    uint8_t cnt; 
    /*Send Event on Pending interrupts*/
    SCB-&amp;gt;SCR |= SCB_SCR_SEVONPEND_Msk;

    // Enter main loop.
    for (;;)
    {
        while(NRF_LOG_PROCESS());
    
        cnt=0;

        CRITICAL_REGION_ENTER();
        /* Call nrf_pwr_mgmt_run() repeatedly as long as there are no pending interrupts */
        do {
          nrf_pwr_mgmt_run();
          cnt++;
        } while (0 == (NVIC-&amp;gt;ISPR[0] | NVIC-&amp;gt;ISPR[1]));
        
        /* Loop through the ISPR registers to check which IRQn woke the CPU */
        for (int irqn = POWER_CLOCK_IRQn; irqn &amp;lt;= SPIM3_IRQn; irqn++)
        {
            if (NVIC_GetPendingIRQ(irqn)) 
            {
                NRF_LOG_INFO(&amp;quot;IRQ pending %d&amp;quot;, irqn);
            }
        }

        CRITICAL_REGION_EXIT();
        NRF_LOG_INFO(&amp;quot;nrf_pwr_mgmt_run() was run %d times&amp;quot;, cnt);
    }
}&lt;/pre&gt;&lt;/p&gt;
[quote userid="105441" url="~/f/nordic-q-a/93235/nrf52840-how-do-i-read-the-event-register"]For logging purposes, how do I read the &amp;quot;Event Register&amp;quot; that WFE and SEV operate on? [/quote]
&lt;p&gt;The event register is not accessible to the CPU, unfortunately. &lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Vidar&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>