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 ;
)
}
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 ;
)
}