summaryrefslogtreecommitdiff
path: root/include/avr/wdt.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/avr/wdt.h')
-rw-r--r--include/avr/wdt.h420
1 files changed, 420 insertions, 0 deletions
diff --git a/include/avr/wdt.h b/include/avr/wdt.h
new file mode 100644
index 0000000000..7337e273b3
--- /dev/null
+++ b/include/avr/wdt.h
@@ -0,0 +1,420 @@
+/**
+ * @file
+ *
+ * @brief Watchdog Timer Handling
+ */
+/* Copyright (c) 2002, 2004 Marek Michalkiewicz
+ Copyright (c) 2005, 2006, 2007 Eric B. Weddington
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE. */
+
+
+/*
+ avr/wdt.h - macros for AVR watchdog timer
+ */
+
+#ifndef _AVR_WDT_H_
+#define _AVR_WDT_H_
+
+#include <avr/io.h>
+#include <stdint.h>
+
+/**
+ * @defgroup avr_watchdog Watchdog Timer Handling
+ *
+ * This header file declares the interface to some inline macros
+ * handling the watchdog timer present in many AVR devices. In order
+ * to prevent the watchdog timer configuration from being
+ * accidentally altered by a crashing application, a special timed
+ * equence is required in order to change it. The macros within
+ * this header file handle the required sequence automatically
+ * before changing any value. Interrupts will be disabled during
+ * the manipulation.
+ *
+ * Note: Depending on the fuse configuration of the particular
+ * device, further restrictions might apply, in particular it might
+ * be disallowed to turn off the watchdog timer.
+ *
+ * Note that for newer devices (ATmega88 and newer, effectively any
+ * AVR that has the option to also generate interrupts), the watchdog
+ * timer remains active even after a system reset (except a power-on
+ * condition), using the fastest prescaler value (approximately 15
+ * ms). It is therefore required to turn off the watchdog early
+ * during program startup, the datasheet recommends a sequence like
+ * the following:
+ *
+ * @code{.c}
+ * #include <stdint.h>
+ * #include <avr/wdt.h>
+ *
+ * uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
+ *
+ * void get_mcusr(void) \
+ * __attribute__((naked)) \
+ * __attribute__((section(".init3")));
+ * void get_mcusr(void)
+ * {
+ * mcusr_mirror = MCUSR;
+ * MCUSR = 0;
+ * wdt_disable();
+ * }
+ * @endcode
+ *
+ * Saving the value of MCUSR in @c mcusr_mirror is only needed if the
+ * application later wants to examine the reset source, but in particular,
+ * clearing the watchdog reset flag before disabling the
+ * watchdog is required, according to the datasheet.
+ * @{
+*/
+
+/**
+ * @brief Watchdog Timer Reset
+ *
+ * Reset the watchdog timer. When the watchdog timer is enabled,
+ * a call to this instruction is required before the timer expires,
+ * otherwise a watchdog-initiated device reset will occur.
+*/
+
+#define wdt_reset() __asm__ __volatile__ ("wdr")
+
+
+#if defined(WDP3)
+# define _WD_PS3_MASK _BV(WDP3)
+#else
+# define _WD_PS3_MASK 0x00
+#endif
+
+#if defined(WDTCSR)
+# define _WD_CONTROL_REG WDTCSR
+#else
+# define _WD_CONTROL_REG WDTCR
+#endif
+
+#if defined(WDTOE)
+#define _WD_CHANGE_BIT WDTOE
+#else
+#define _WD_CHANGE_BIT WDCE
+#endif
+
+
+/**
+ * Enable the watchdog timer, configuring it for expiry after
+ * @c timeout (which is a combination of the @c WDP0 through
+ * @c WDP2 bits to write into the @c WDTCR register; For those devices
+ * that have a @c WDTCSR register, it uses the combination of the @c WDP0
+ * through @c WDP3 bits).
+ *
+ * See also the symbolic constants @c WDTO_15MS et al.
+*/
+
+
+#if defined(__AVR_ATxmega16A4__) \
+|| defined(__AVR_ATxmega16D4__) \
+|| defined(__AVR_ATxmega32A4__) \
+|| defined(__AVR_ATxmega32D4__) \
+|| defined(__AVR_ATxmega64A1__) \
+|| defined(__AVR_ATxmega64A3__) \
+|| defined(__AVR_ATxmega64D3__) \
+|| defined(__AVR_ATxmega128A1__) \
+|| defined(__AVR_ATxmega128A3__) \
+|| defined(__AVR_ATxmega128D3__) \
+|| defined(__AVR_ATxmega192A3__) \
+|| defined(__AVR_ATxmega192D3__) \
+|| defined(__AVR_ATxmega256A3__) \
+|| defined(__AVR_ATxmega256D3__) \
+|| defined(__AVR_ATxmega256A3B__)
+
+/*
+ wdt_enable(WDT_PER_8KCLK_gc);
+*/
+#define wdt_enable(value) \
+__asm__ __volatile__ ( \
+ "in __tmp_reg__, %0" "\n\t" \
+ "out %1, %3" "\n\t" \
+ "sts %2, %4" "\n\t" \
+ "wdr" "\n\t" \
+ "out %0, __tmp_reg__" "\n\t" \
+ : \
+ : "M" (_SFR_MEM_ADDR(RAMPD)), \
+ "M" (_SFR_MEM_ADDR(CCP)), \
+ "M" (_SFR_MEM_ADDR(WDT_CTRL)), \
+ "r" ((uint8_t)0xD8), \
+ "r" ((uint8_t)(WDT_CEN_bm | WDT_ENABLE_bm | value)) \
+ : "r0" \
+)
+
+
+#elif defined(__AVR_AT90CAN32__) \
+|| defined(__AVR_AT90CAN64__) \
+|| defined(__AVR_AT90CAN128__) \
+|| defined(__AVR_AT90PWM1__) \
+|| defined(__AVR_AT90PWM2__) \
+|| defined(__AVR_AT90PWM216__) \
+|| defined(__AVR_AT90PWM2B__) \
+|| defined(__AVR_AT90PWM3__) \
+|| defined(__AVR_AT90PWM316__) \
+|| defined(__AVR_AT90PWM3B__) \
+|| defined(__AVR_AT90PWM81__) \
+|| defined(__AVR_AT90USB1286__) \
+|| defined(__AVR_AT90USB1287__) \
+|| defined(__AVR_AT90USB162__) \
+|| defined(__AVR_AT90USB646__) \
+|| defined(__AVR_AT90USB647__) \
+|| defined(__AVR_AT90USB82__) \
+|| defined(__AVR_ATmega1280__) \
+|| defined(__AVR_ATmega1281__) \
+|| defined(__AVR_ATmega1284P__) \
+|| defined(__AVR_ATmega128RFA1__) \
+|| defined(__AVR_ATmega164__) \
+|| defined(__AVR_ATmega164A__) \
+|| defined(__AVR_ATmega164P__) \
+|| defined(__AVR_ATmega165__) \
+|| defined(__AVR_ATmega165A__) \
+|| defined(__AVR_ATmega165P__) \
+|| defined(__AVR_ATmega168__) \
+|| defined(__AVR_ATmega168A__) \
+|| defined(__AVR_ATmega168P__) \
+|| defined(__AVR_ATmega169__) \
+|| defined(__AVR_ATmega169A__) \
+|| defined(__AVR_ATmega169P__) \
+|| defined(__AVR_ATmega169PA__) \
+|| defined(__AVR_ATmega16HVA__) \
+|| defined(__AVR_ATmega16HVA2__) \
+|| defined(__AVR_ATmega16HVB__) \
+|| defined(__AVR_ATmega16M1__) \
+|| defined(__AVR_ATmega16U2__) \
+|| defined(__AVR_ATmega16U4__) \
+|| defined(__AVR_ATmega2560__) \
+|| defined(__AVR_ATmega2561__) \
+|| defined(__AVR_ATmega324__) \
+|| defined(__AVR_ATmega324A__) \
+|| defined(__AVR_ATmega324P__) \
+|| defined(__AVR_ATmega324PA__) \
+|| defined(__AVR_ATmega325__) \
+|| defined(__AVR_ATmega3250__) \
+|| defined(__AVR_ATmega328__) \
+|| defined(__AVR_ATmega328P__) \
+|| defined(__AVR_ATmega329__) \
+|| defined(__AVR_ATmega329P__) \
+|| defined(__AVR_ATmega329PA__) \
+|| defined(__AVR_ATmega3290__) \
+|| defined(__AVR_ATmega3290P__) \
+|| defined(__AVR_ATmega32C1__) \
+|| defined(__AVR_ATmega32HVB__) \
+|| defined(__AVR_ATmega32M1__) \
+|| defined(__AVR_ATmega32U2__) \
+|| defined(__AVR_ATmega32U4__) \
+|| defined(__AVR_ATmega32U6__) \
+|| defined(__AVR_ATmega406__) \
+|| defined(__AVR_ATmega48__) \
+|| defined(__AVR_ATmega48A__) \
+|| defined(__AVR_ATmega48P__) \
+|| defined(__AVR_ATmega640__) \
+|| defined(__AVR_ATmega644__) \
+|| defined(__AVR_ATmega644A__) \
+|| defined(__AVR_ATmega644P__) \
+|| defined(__AVR_ATmega644PA__) \
+|| defined(__AVR_ATmega645__) \
+|| defined(__AVR_ATmega645A__) \
+|| defined(__AVR_ATmega645P__) \
+|| defined(__AVR_ATmega6450__) \
+|| defined(__AVR_ATmega6450A__) \
+|| defined(__AVR_ATmega6450P__) \
+|| defined(__AVR_ATmega649__) \
+|| defined(__AVR_ATmega649A__) \
+|| defined(__AVR_ATmega6490__) \
+|| defined(__AVR_ATmega6490A__) \
+|| defined(__AVR_ATmega6490P__) \
+|| defined(__AVR_ATmega649P__) \
+|| defined(__AVR_ATmega64C1__) \
+|| defined(__AVR_ATmega64HVE__) \
+|| defined(__AVR_ATmega64M1__) \
+|| defined(__AVR_ATmega88__) \
+|| defined(__AVR_ATmega88A__) \
+|| defined(__AVR_ATmega88P__) \
+|| defined(__AVR_ATmega88PA__) \
+|| defined(__AVR_ATmega8HVA__) \
+|| defined(__AVR_ATmega8U2__) \
+|| defined(__AVR_ATtiny48__) \
+|| defined(__AVR_ATtiny88__) \
+|| defined(__AVR_ATtiny87__) \
+|| defined(__AVR_ATtiny167__) \
+|| defined(__AVR_AT90SCR100__) \
+|| defined(__AVR_ATA6289__)
+
+/* Use STS instruction. */
+
+#define wdt_enable(value) \
+__asm__ __volatile__ ( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "wdr" "\n\t" \
+ "sts %0,%1" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ "sts %0,%2" "\n\t" \
+ : /* no outputs */ \
+ : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
+ "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
+ "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
+ _BV(WDE) | (value & 0x07)) ) \
+ : "r0" \
+)
+
+#define wdt_disable() \
+__asm__ __volatile__ ( \
+ "in __tmp_reg__, __SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "sts %0, %1" "\n\t" \
+ "sts %0, __zero_reg__" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ : /* no outputs */ \
+ : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
+ "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))) \
+ : "r0" \
+)
+
+
+
+#else
+
+/* Use OUT instruction. */
+
+#define wdt_enable(value) \
+ __asm__ __volatile__ ( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "wdr" "\n\t" \
+ "out %0,%1" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ "out %0,%2" \
+ : /* no outputs */ \
+ : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), \
+ "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
+ "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
+ _BV(WDE) | (value & 0x07)) ) \
+ : "r0" \
+ )
+
+/**
+ * Disable the watchdog timer, if possible. This attempts to turn off the
+ * Enable bit in the watchdog control register. See the datasheet for
+ * details.
+*/
+#define wdt_disable() \
+__asm__ __volatile__ ( \
+ "in __tmp_reg__, __SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "out %0, %1" "\n\t" \
+ "out %0, __zero_reg__" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ : /* no outputs */ \
+ : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), \
+ "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))) \
+ : "r0" \
+)
+
+#endif
+
+
+
+/**
+ * Symbolic constants for the watchdog timeout. Since the watchdog
+ * timer is based on a free-running RC oscillator, the times are
+ * approximate only and apply to a supply voltage of 5 V. At lower
+ * supply voltages, the times will increase. For older devices, the
+ * times will be as large as three times when operating at Vcc = 3 V,
+ * while the newer devices (e. g. ATmega128, ATmega8) only experience
+ * a negligible change.
+ *
+ * Possible timeout values are: 15 ms, 30 ms, 60 ms, 120 ms, 250 ms,
+ * 500 ms, 1 s, 2 s. (Some devices also allow for 4 s and 8 s.)
+ * Symbolic constants are formed by the prefix
+ * @c WDTO_, followed by the time.
+ *
+ * Example that would select a watchdog timer expiry of approximately
+ * 500 ms:
+ *
+ * @code{.c}
+ * wdt_enable(WDTO_500MS);
+ * @endcode
+*/
+#define WDTO_15MS 0
+
+/** @see WDT0_15MS */
+#define WDTO_30MS 1
+
+/** @see WDT0_15MS */
+#define WDTO_60MS 2
+
+/** @see WDT0_15MS */
+#define WDTO_120MS 3
+
+/** @see WDT0_15MS */
+#define WDTO_250MS 4
+
+/** @see WDT0_15MS */
+#define WDTO_500MS 5
+
+/** @see WDT0_15MS */
+#define WDTO_1S 6
+
+/** @see WDT0_15MS */
+#define WDTO_2S 7
+
+#if defined(__DOXYGEN__) || defined(WDP3)
+
+/**
+ * @see WDT0_15MS
+ *
+ * Note: This is only available on:
+ * ATtiny2313,
+ * ATtiny24, ATtiny44, ATtiny84,
+ * ATtiny25, ATtiny45, ATtiny85,
+ * ATtiny261, ATtiny461, ATtiny861,
+ * ATmega48, ATmega88, ATmega168,
+ * ATmega48P, ATmega88P, ATmega168P, ATmega328P,
+ * ATmega164P, ATmega324P, ATmega644P, ATmega644,
+ * ATmega640, ATmega1280, ATmega1281, ATmega2560, ATmega2561,
+ * ATmega8HVA, ATmega16HVA, ATmega32HVB,
+ * ATmega406, ATmega1284P,
+ * AT90PWM1, AT90PWM2, AT90PWM2B, AT90PWM3, AT90PWM3B, AT90PWM216, AT90PWM316,
+ * AT90PWM81,
+ * AT90USB82, AT90USB162,
+ * AT90USB646, AT90USB647, AT90USB1286, AT90USB1287,
+ * ATtiny48, ATtiny88.
+ */
+#define WDTO_4S 8
+
+/** @see WDTO_4S */
+#define WDTO_8S 9
+
+#endif /* defined(__DOXYGEN__) || defined(WDP3) */
+/** @} */
+
+#endif /* _AVR_WDT_H_ */