#include "common.h" #include 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"); }