Go to the documentation of this file.00001
00035
00036
00037
00038
00039
00040 #include <sys/timer.h>
00041 #include <dev/watchdog.h>
00042 #include <arch/avr32.h>
00043
00044 #include <avr32/io.h>
00045
00046
00047 #if !defined(AVR32_WDT_KEY_VALUE)
00048 #define AVR32_WDT_KEY_VALUE 0x00000055
00049 #endif
00050
00055
00056 static ureg_t nested;
00057
00058 static void wdt_set_ctrl(unsigned long ctrl)
00059 {
00060 AVR32_WDT.ctrl = ctrl | (AVR32_WDT_KEY_VALUE << AVR32_WDT_CTRL_KEY_OFFSET);
00061 AVR32_WDT.ctrl = ctrl | ((~AVR32_WDT_KEY_VALUE << AVR32_WDT_CTRL_KEY_OFFSET) & AVR32_WDT_CTRL_KEY_MASK);
00062 }
00063
00064 static long long wdt_get_us_timeout_period(void)
00065 {
00066 unsigned int slowclock = NutArchClockGet(NUT_HWCLK_SLOW_CLOCK);
00067
00068 return (AVR32_WDT.ctrl & AVR32_WDT_CTRL_EN_MASK) ?
00069 ((1ULL << (((AVR32_WDT.ctrl & AVR32_WDT_CTRL_PSEL_MASK) >> AVR32_WDT_CTRL_PSEL_OFFSET) + 1)) *
00070 1000000 + slowclock / 2) / slowclock : -1;
00071 }
00072
00079 uint32_t Avr32WatchDogStart(uint32_t ms)
00080 {
00081 unsigned long long int timeout = ms * 1000;
00082
00083 unsigned int slowclock = NutArchClockGet(NUT_HWCLK_SLOW_CLOCK);
00084
00085 Avr32WatchDogDisable();
00086
00087 #define MIN_US_TIMEOUT_PERIOD \
00088 (((1ULL << 1 ) * 1000000 + slowclock / 2) / slowclock)
00089 #define MAX_US_TIMEOUT_PERIOD \
00090 (((1ULL << (1 << AVR32_WDT_CTRL_PSEL_SIZE)) * 1000000 + slowclock / 2) / slowclock)
00091
00092
00093
00094 if (timeout < MIN_US_TIMEOUT_PERIOD)
00095 timeout = MIN_US_TIMEOUT_PERIOD;
00096 else if (timeout > MAX_US_TIMEOUT_PERIOD)
00097 timeout = MAX_US_TIMEOUT_PERIOD;
00098
00099 wdt_set_ctrl(AVR32_WDT_CTRL_EN_MASK |
00100 ((32 - __builtin_clz(((((timeout * slowclock + 500000) / 1000000) << 1) - 1) >> 1) -
00101 1) << AVR32_WDT_CTRL_PSEL_OFFSET));
00102
00103 Avr32WatchDogRestart();
00104 nested = 1;
00105
00106
00107 return wdt_get_us_timeout_period() / 1000;
00108 }
00109
00116 void Avr32WatchDogRestart(void)
00117 {
00118 wdt_set_ctrl(AVR32_WDT.ctrl | AVR32_WDT_CTRL_EN_MASK);
00119 AVR32_WDT.clr = 0;
00120 }
00121
00128 void Avr32WatchDogDisable(void)
00129 {
00130 if (nested) {
00131 nested++;
00132 }
00133 wdt_set_ctrl(AVR32_WDT.ctrl & ~AVR32_WDT_CTRL_EN_MASK);
00134 }
00135
00142 void Avr32WatchDogEnable(void)
00143 {
00144 if (nested > 1 && --nested == 1) {
00145 Avr32WatchDogRestart();
00146 }
00147 }
00148