121 lines
3.3 KiB
C
121 lines
3.3 KiB
C
#include "common.h"
|
||
|
||
#include <util/atomic.h>
|
||
|
||
void WDT_Enable(void)
|
||
{
|
||
Info("Enabling watchdog timer...");
|
||
|
||
// WDTCR: Watchdog Timer Control Register
|
||
|
||
// 7 6 5 4 3 2 1 0
|
||
// – – - WDTOE WDE WDP2 WDP1 WDP0
|
||
|
||
// When the WDE is written to logic one, the
|
||
// Watchdog Timer is enabled, and if the WDE is
|
||
// written to logic zero, the Watchdog Timer
|
||
// function is disabled.
|
||
|
||
// WDP2, WDP1, WDP0: Watchdog Timer Prescaler
|
||
// The WDP2, WDP1, and WDP0 bits determine the
|
||
// Watchdog Timer prescaling when the Watchdog
|
||
// Timer is enabled. The different prescaling
|
||
// values and their corresponding Timeout
|
||
// Periods are:
|
||
|
||
// WDP2 WDP1 WDP0 Cycles Timeout3V Timeout5V
|
||
// 0 0 0 16K 17.10ms 16.30ms
|
||
// 0 0 1 32K 34.30ms 32.50ms
|
||
// 0 1 0 64K 68.50ms 65.00ms
|
||
// 0 1 1 128K 0.14s 0.13s
|
||
// 1 0 0 256K 0.27s 0.26s
|
||
// 1 0 1 512K 0.55s 0.52s
|
||
// 1 1 0 1,024K 1.10s 1.00s
|
||
// 1 1 1 2,048K 2.20s 2.10s
|
||
|
||
// WDTOE: Watchdog Turn-off Enable This bit must
|
||
// be set when the WDE bit is written to logic zero.
|
||
// Otherwise, the Watchdog will not be disabled.
|
||
// Once written to one, hardware will clear this
|
||
// bit after four clock cycles.
|
||
|
||
// 00001111: Watchdog enabled, 2sec timeout
|
||
WDTCR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0);
|
||
}
|
||
|
||
void WDT_SetTimeoutFlag(byte flag)
|
||
{
|
||
flag = CLAMP(flag, 7, 0);
|
||
|
||
Info("Setting watchdog prescalar to %02X...", flag);
|
||
|
||
// Clear timer prescalar flags
|
||
WDTCR &= 0xF8; // 11111000
|
||
|
||
WDTCR |= flag;
|
||
}
|
||
|
||
bool WDT_HasTriggered(void)
|
||
{
|
||
bool isreset;
|
||
|
||
// To make use of the Reset Flags to identify a reset
|
||
// condition, the user should read and then reset the
|
||
// MCUCSR as early as possible in the program. If the
|
||
// register is cleared before another reset occurs,
|
||
// the source of the reset can be found by examining
|
||
// the Reset Flags.
|
||
|
||
// MCUCSR: MCU Control and Status Register
|
||
// The MCU Control and Status Register provides
|
||
// information on which reset source caused an MCU
|
||
// Reset.
|
||
|
||
// 7 6 5 4 3 2 1 0
|
||
// JTD ISC2 – JTRF WDRF BORF EXTRF PORF
|
||
|
||
// Is watchdog reset flag set?
|
||
isreset = ((MCUCSR & BIT(3)) == 1);
|
||
|
||
// XXX: Reset flag detection should be a separate
|
||
// module to handle the different types.
|
||
|
||
MCUCSR = 0;
|
||
|
||
return isreset;
|
||
}
|
||
|
||
void WDT_Disable(void)
|
||
{
|
||
// WDE can only be cleared if the WDTOE bit has
|
||
// logic level one. To disable an enabled watchdog
|
||
// timer, the following procedure must be followed:
|
||
|
||
// 1. In the same operation, write a logic one to
|
||
// WDTOE and WDE. A logic one must be written to WDE
|
||
// even though it is set to one before the disable
|
||
// operation starts.
|
||
|
||
// 2. Within the next four clock cycles, write a
|
||
// logic 0 to WDE. This disables the watchdog.
|
||
|
||
// No interrupts while we set WDTCR;
|
||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||
WDTCR = BIT(WDTOE) | BIT(WDE);
|
||
WDTCR = 0;
|
||
}
|
||
}
|
||
|
||
void WDT_Reset(void)
|
||
{
|
||
// The WDR – Watchdog Reset – instruction resets the
|
||
// watchdog timer. The Watchdog Timer is also reset
|
||
// when it is disabled and when a chip reset occurs.
|
||
|
||
// If the reset period expires without another
|
||
// watchdog reset, the chip resets and executes from
|
||
// the Reset Vector.
|
||
|
||
__asm__("WDR");
|
||
}
|