<?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>Watchdog reset: determining cause</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/25692/watchdog-reset-determining-cause</link><description>Hi, 
 I&amp;#39;d like to determine the cause of a watchdog reset. I was hoping to utilize the WDT event handler (passed in to nrf_drv_wdt_init() ) to record the PC of the application code at the time the watchdog timeout occurred, and save that to a word in</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 14 Feb 2018 14:05:43 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/25692/watchdog-reset-determining-cause" /><item><title>RE: Watchdog reset: determining cause</title><link>https://devzone.nordicsemi.com/thread/120846?ContentTypeID=1</link><pubDate>Wed, 14 Feb 2018 14:05:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7ab1666c-0abf-4ec5-96e3-35fe968a8f36</guid><dc:creator>pabigot</dc:creator><description>&lt;p&gt;If you&amp;#39;re using gcc, aren&amp;#39;t deeply coupled to the nRF5 SDK WDT API, and if necessary translate this to plain C, the following also works:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;extern &amp;quot;C&amp;quot; {
  /* This little joy loads r0 with the main or process stack pointer then
   * jumps to the systemState watchdog IRQ handler, which will then
   * pull the exception return address out and use that as the value
   * of last_pc showing where the program was when the reset occurred.
   *
   * See https://stackoverflow.com/questions/38618440
   */
  __attribute__((__naked__))
  void WDT_IRQHandler ()
  {
    __ASM (
#if (NRF51 - 0) /* Cortex M0/M1 */
          &amp;quot;mrs r0, msp\n\t&amp;quot;
          &amp;quot;mov r1, lr\n\t&amp;quot;
          &amp;quot;mov r2, #4\n\t&amp;quot;
          &amp;quot;tst r1, r2\n\t&amp;quot;
          &amp;quot;beq 1f\n\t&amp;quot;
          &amp;quot;mrs r0, psp\n&amp;quot;
#else /* Cortex M3/M4 */
          &amp;quot;tst lr, #4\n\t&amp;quot;
          &amp;quot;ite eq\n\t&amp;quot;
          &amp;quot;mrseq r0, msp\n\t&amp;quot;
          &amp;quot;mrsne r0, psp\n\t&amp;quot;
#endif /* ARM Cortext Variant */
          &amp;quot;1:\tldr r1, =%0\n\t&amp;quot;
          &amp;quot;bx r1\n&amp;quot;
          : // no outputs
          : &amp;quot;i&amp;quot; (nrfcxx::systemState::wdt_irqhandler)
          );
  }
} // extern C

void
systemState::wdt_irqhandler (void * sp)
{
    auto statep = nrfcxx::systemState::statep_;
    if (statep) {
      struct exception_frame_type {
        uint32_t r0;
        uint32_t r1;
        uint32_t r2;
        uint32_t r3;
        uint32_t r12;
        uint32_t lr;
        uint32_t pc;
        uint32_t xpsr;
      } const * const efp = reinterpret_cast&amp;lt;const exception_frame_type *&amp;gt;(sp);

      statep-&amp;gt;wdt_status = NRF_WDT-&amp;gt;REQSTATUS;
      if (efp) {
        statep-&amp;gt;last_pc = efp-&amp;gt;lr;
        statep-&amp;gt;reset_reas_ = state_type::RESET_REAS_WDTBARKED;
      }
    }
    do_reset(false);
}
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Watchdog reset: determining cause</title><link>https://devzone.nordicsemi.com/thread/101213?ContentTypeID=1</link><pubDate>Thu, 05 Oct 2017 17:10:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c4ad7212-c3c1-4c2d-97ad-9ea680f77a5e</guid><dc:creator>Mike Voytovich</dc:creator><description>&lt;p&gt;Thanks for the suggestion RK!  I was able to successfully unwind the stack and find the PC at the time of the WDT timeout.  Here&amp;#39;s the code (posting as an answer since there&amp;#39;s not enough room as a comment):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* 
 * wdt_event_handler() - watchdog timeout event handler
 *
 * This handler is called from the ISR WDT_IRQHandler, which has previously 
 * pushed lr onto the interrupt stack, then subtracted 12 from the SP before
 * calling this routine.  So we&amp;#39;re adding 12 to get back to the lr
 * (which contains EXC_RETURN); then adding another 28 bytes to get back
 * to the stacked PC (since xPSR, PC, LR, R12, R3-R0 are pushed onto the 
 * interrupt stack in that order), and saving that address in the m_wdt_addr
 * variable.
 * 
 * NOTE: The max amount of time we can spend in WDT interrupt is two cycles 
 * of 32768[Hz] clock - after that, the WDT reset occurs.
*/

static void wdt_event_handler(void)
{
    __asm volatile (
                    &amp;quot;   ldr r0, [sp, #40]     \n&amp;quot; 
                    &amp;quot;   ldr r1, =m_wdt_addr   \n&amp;quot; 
                    &amp;quot;   str r0, [r1]          \n&amp;quot;
                );
}
&lt;/code&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Watchdog reset: determining cause</title><link>https://devzone.nordicsemi.com/thread/101212?ContentTypeID=1</link><pubDate>Wed, 04 Oct 2017 23:50:08 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b66fe97a-820f-44d7-acd2-f3bbb954faaa</guid><dc:creator>RK</dc:creator><description>&lt;p&gt;If you look at the code for the WDT driver it&amp;#39;s very simple, the function you pass in is called directly from the interrupt handler (it&amp;#39;s only 4 lines long) so the stack will be set up just as it was when the interrupt was taken (standard Cortex-M interrupt stack) plus whatever was stacked in that function before it called you. That should be quite simple to unwind although you&amp;#39;ll have to look at the actual generated assembly to see where on the stack you have to look (you could use the frame pointer but that&amp;#39;s usually omitted in release code).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>