HW Reset works weird after first watchdog reset

05 Apr 2010

Hi All,

I just finished implementing a simple watchdog library that allows me to enable the watchdog and force a watchdog reset by simply timing out.  I am seeing strange behavior on the LPC1768 MBED target where after the first watchdog timeout, the hardware reset fails to work correctly.

Once the watchdog has reset the CPU due to a timeout, whenever I press the reset button, multiple resets are generated.

My test code starts up with the watcdog in the disabled state (default on powerup) and prints a simple message on UART-0 (polled-mode).  If I press RESET, the CPU resets correctly and I again see my simple message.  I then enable the watchdog and it times out, reseting the CPU.

Note: The watchdog timeout appears to work correctly as I see a reset and get one copy of my simple message.  However, if  I now press reset, the CPU will appear to reset from one to three times and repeat my message.

At first I thought it might be a sw bug, but this reset behavior  continues until I physically power down the mbed unit (remove USB) and the plug it back in.  Now, so long as I don't enable the watchdog timer, the HW reset works ok (one message per press).

I have checked the device errata for the '-' device and there is nothing there related to the watchdog, so I cannot confirm that it is a device error.

Note: I am using the RC clock to drive the watchdog and the mbed firmware is the latest.

The 'ATOMIC_ALL' macro invocations set/restore PRIMASK in order to ensure interrupts cannot interfere.

If anyone can shed some light on this, that would great!

Cheers!

Daniel Quinz, Eng.

Code:


namespace Wdog
{
  enum Mode
    {
      MODE_IRQ   = 1 ,
      MODE_RESET = 3 ,
    } ;
}

----------------------------------------------------------------------------------------------------------------------------

void Wdog :: init (Mode mode , UInt32 period_ms)
{
  // Actual WDOG period = 4 x Twdog x (N - 1) with Twdog = 250 ns \\\

  if      (period_ms == 0)
    {
      period_ms = 0x000000FF ; // Minimum legal value (256 us)
    }
  else if (period_ms > 4294967)
    {
      period_ms = 0xFFFFFFFF ; // Maximum legel value (4294.967 sec)
    }
  else
    {
      period_ms *= 1000 ;      // Calculate divider value
      period_ms -= 1    ;      // Adjust for register value
    }

  ATOMIC_ALL
    (
      feed () ;                       // Must feed to enable change

      LPC_WDT->WDMOD    = mode      ;
      LPC_WDT->WDTC     = period_ms ;
      LPC_WDT->WDCLKSEL = 0         ; // Use RC clock (4 MHz)
   
      feed () ;                       // Feed starts watchdog
    )
}

void Wdog :: reset_cpu (void)
{
  ATOMIC_ALL
    (
      feed () ;                             // Must feed to enable change

      LPC_WDT->WDMOD    = MODE_RESET ;      // Force WDOG enable
      LPC_WDT->WDTC     = 255        ;
      LPC_WDT->WDCLKSEL = 0          ;      // Use RC clock (4 MHz)

      feed () ;                             // Start watchdog if not already started

      for (;;) ;                            // Wait for timeout (256 us) to reset
    )
}


void Wdog :: feed (void)
{
  ATOMIC_ALL
    (
      LPC_WDT->WDFEED = 0xAA ;
      LPC_WDT->WDFEED = 0x55 ;
    )
}

 

 

 

 

08 Apr 2010

Hi Daniel,

If I read your steps and observed behaviour correctly, in particular the behaviour you are trying to determine is:

Note: The watchdog timeout appears to work correctly as I see a reset and get one copy of my simple message.  However, if  I now press reset, the CPU will appear to reset from one to three times and repeat my message.

...I think this can be explained. Here is the interaction I think you are seeing:

When the mbed starts up, the interface attaches itself to the target as a debugger via JTAG (as you would if you were connecting it to a toolchain on your PC via a JTAG wiggler). This allows us to do things like program the target's FLASH, implement semihosting (when a target asks the "host" to do things, like access files on the host), etc.

On the LPC1768 implementation, the only way to access the debug logic (as far as we know) is to have the core running; i.e. you can't have the chip in reset but not the debug logic. Therefore, to attach the debug hooks and register breakpoints you actually need to set the core running, do the stuff and then reset again. We confirmed this is how some other debuggers do it too, so we're not alone. Whilst not ideal, it is the best we could come up on this hardware.

I think this would explain the behaviour you are seeing, and it'd be great if you confirm this to be the case.

Simon

17 Nov 2010

I just came across the same behaviour, which led me to search the forum and hence to this post.  In summary, what I am seeing is:

  • Before the watchdog is triggered, resets behave normally.  That is, the startup code is invoked once each time the Reset button is pressed (or Alt-B in TeraTerm)
  • If the watchdog reset is triggered, the watchdog reset itself is normal (the startup code is invoked once, and the WDTR bit is set in the RSID register)
  • Any further reset (whether by the reset button or Alt-B) causes the target processor to be reset twice -- with some delay between the two (at least 30ms -- enough to write a couple of lines to the terminal).   The RSID register no longer shows WDTR, as expected, so there would seem to be no state in the target anywhere that indicates there had been a previous watchdog reset
  • The only way to stop the continuing multiple resets is power off/on (unplug the USB).

The double reset mentioned above sounds to be related, but why is it only apparent (with the long delay) after a watchdog reset?

Thanks -- Mike