]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/iwrap/wd.h
Merge branch 'master' of https://github.com/jackhumbert/qmk_firmware
[qmk_firmware.git] / tmk_core / protocol / iwrap / wd.h
1 /* This is from http://www.mtcnet.net/~henryvm/wdt/ */
2 #ifndef _AVR_WD_H_
3 #define _AVR_WD_H_
4
5 #include <avr/io.h>
6
7 /*
8 Copyright (c) 2009, Curt Van Maanen
9
10 Permission to use, copy, modify, and/or distribute this software for any
11 purpose with or without fee is hereby granted, provided that the above
12 copyright notice and this permission notice appear in all copies.
13
14 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
22
23 include usage-
24     #include "wd.h"             //if in same directory as project
25     #include <avr/wd.h>         //if wd.h is in avr directory
26
27 set watchdog modes and prescale
28
29 usage-
30     WD_SET(mode,[timeout]);     //prescale always set
31
32 modes-
33     WD_OFF                      disabled
34     WD_RST                      normal reset mode
35     WD_IRQ                      interrupt only mode (if supported)
36     WD_RST_IRQ                  interrupt+reset mode (if supported)
37
38 timeout-
39     WDTO_15MS                   default if no timeout provided
40     WDTO_30MS
41     WDTO_60MS
42     WDTO_120MS
43     WDTO_250MS
44     WDTO_500MS
45     WDTO_1S
46     WDTO_2S
47     WDTO_4S                     (if supported)
48     WDTO_8S                     (if supported)
49
50 examples-
51     WD_SET(WD_RST,WDTO_1S);     //reset mode, 1s timeout
52     WD_SET(WD_OFF);             //watchdog disabled (if not fused on)
53     WD_SET(WD_RST);             //reset mode, 15ms (default timeout)
54     WD_SET(WD_IRQ,WDTO_120MS);  //interrupt only mode, 120ms timeout
55     WD_SET(WD_RST_IRQ,WDTO_2S); //interrupt+reset mode, 2S timeout
56
57
58 for enhanced watchdogs, if the watchdog is not being used WDRF should be
59 cleared on every power up or reset, along with disabling the watchdog-
60     WD_DISABLE();               //clear WDRF, then turn off watchdog
61
62 */
63
64 //reset registers to the same name (MCUCSR)
65 #if !defined(MCUCSR)
66 #define MCUCSR                  MCUSR
67 #endif
68
69 //watchdog registers to the same name (WDTCSR)
70 #if !defined(WDTCSR)
71 #define WDTCSR                  WDTCR
72 #endif
73
74 //if enhanced watchdog, define irq values, create disable macro
75 #if defined(WDIF)
76 #define WD_IRQ                  0xC0
77 #define WD_RST_IRQ              0xC8
78 #define WD_DISABLE()            do{                       \
79                                     MCUCSR &= ~(1<<WDRF); \
80                                     WD_SET(WD_OFF);       \
81                                 }while(0)
82 #endif
83
84 //all watchdogs
85 #define WD_RST                  8
86 #define WD_OFF                  0
87
88 //prescale values
89 #define WDTO_15MS               0
90 #define WDTO_30MS               1
91 #define WDTO_60MS               2
92 #define WDTO_120MS              3
93 #define WDTO_250MS              4
94 #define WDTO_500MS              5
95 #define WDTO_1S                 6
96 #define WDTO_2S                 7
97
98 //prescale values for avrs with WDP3
99 #if defined(WDP3)
100 #define WDTO_4S                 0x20
101 #define WDTO_8S                 0x21
102 #endif
103
104 //watchdog reset
105 #define WDR()                   __asm__ __volatile__("wdr")
106
107 //avr reset using watchdog
108 #define WD_AVR_RESET()          do{                              \
109                                     __asm__ __volatile__("cli"); \
110                                     WD_SET_UNSAFE(WD_RST);       \
111                                     while(1);                    \
112                                 }while(0)
113
114 /*set the watchdog-
115 1. save SREG
116 2. turn off irq's
117 3. reset watchdog timer
118 4. enable watchdog change
119 5. write watchdog value
120 6. restore SREG (restoring irq status)
121 */
122 #define WD_SET(val,...)                                 \
123     __asm__ __volatile__(                               \
124         "in __tmp_reg__,__SREG__"           "\n\t"      \
125         "cli"                               "\n\t"      \
126         "wdr"                               "\n\t"      \
127         "sts %[wdreg],%[wden]"              "\n\t"      \
128         "sts %[wdreg],%[wdval]"             "\n\t"      \
129         "out __SREG__,__tmp_reg__"          "\n\t"      \
130         :                                               \
131         : [wdreg] "M" (&WDTCSR),                        \
132           [wden]  "r" ((uint8_t)(0x18)),                \
133           [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0)))  \
134         : "r0"                                          \
135 )
136
137 /*set the watchdog when I bit in SREG known to be clear-
138 1. reset watchdog timer
139 2. enable watchdog change
140 5. write watchdog value
141 */
142 #define WD_SET_UNSAFE(val,...)                          \
143     __asm__ __volatile__(                               \
144         "wdr"                               "\n\t"      \
145         "sts %[wdreg],%[wden]"              "\n\t"      \
146         "sts %[wdreg],%[wdval]"             "\n\t"      \
147         :                                               \
148         : [wdreg] "M" (&WDTCSR),                        \
149           [wden]  "r" ((uint8_t)(0x18)),                \
150           [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0)))  \
151 )
152
153
154 //for compatibility with avr/wdt.h
155 #define wdt_enable(val) WD_SET(WD_RST,val)
156 #define wdt_disable()   WD_SET(WD_OFF)
157
158
159 #endif /* _AVR_WD_H_ */