This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Saving the location of Watchdog timeout

I am trying to save the address of program counter when a watchdog reset occurs. In order to do that I use gcc's __builtin_return_address(0) from within the SDK's nrf_drv_wdt.c:WDT_IRQHandler().

What this returns is 0xfffffff9. If I interpret the ARM spec correctly, this address is in the area reserved for the chip vendor.

  • What is at that address?

  • Can I extract the PC before WD reset using the gcc builtin? Another function?

  • What is the recommended way of getting the address when the watchdog timed out? I've seen people manually unpacking the stack, I'd be glad if I could do it in a less hacky way.

Parents
  • I've run into something I don't understand. In our firmware, your example doesn't work, but this does. The important difference is removing "dd r0, #8". I found it by chance when fiddling around, but I can't figure out WHY it works.

    static void wdt_timeout_handler(void)
    {
      // Store a pointer of type *stack_t in r0.
      uint32_t r0;
      __ASM ("   mrs r0, msp        \n");   
    
      const stack_t pStack = (stack_t *)r0;
      dump_stack(pStack);
    }

Reply
  • I've run into something I don't understand. In our firmware, your example doesn't work, but this does. The important difference is removing "dd r0, #8". I found it by chance when fiddling around, but I can't figure out WHY it works.

    static void wdt_timeout_handler(void)
    {
      // Store a pointer of type *stack_t in r0.
      uint32_t r0;
      __ASM ("   mrs r0, msp        \n");   
    
      const stack_t pStack = (stack_t *)r0;
      dump_stack(pStack);
    }

Children
  • Hello,

    "add r0, #8" was added to compensate for stack usage in the  WDT_IRQHandler() exception before the wdt_timeout_handler() was invoked. This is however only needed if you compile the driver code without code optimization. With optimization, there is no stack usage in the exception handler, and you can omit this line as the SP will remain unchanged.

    This was also noted in the snippet Sigurd posted above:

    //NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
    void wdt_timeout_handler()
    {
     /* Needed to unwind original stack frame from WDT_IRQHandler when code optimization is disabled. 
        Try to remove "add	r0, #8" line if compiling with -O3*/
    __ASM volatile(        
                     "   mrs r0, msp                             \n"
                     "   add	r0, #8                       \n"
                     "   ldr r3, =dump_stack                     \n"
                     "   bx r3                                   \n"
                  ); 
    } 

Related