$treeview $search $mathjax $extrastylesheet
avr-libc
2.0.0
$projectbrief
|
$projectbrief
|
$searchbox |
AVR Libc Home Page |
AVR Libc Development Pages |
||||
Main Page |
User Manual |
Library Reference |
FAQ |
Example Projects |
00001 /* Copyright (c) 2002, 2004 Marek Michalkiewicz 00002 Copyright (c) 2005, 2006, 2007 Eric B. Weddington 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright 00009 notice, this list of conditions and the following disclaimer. 00010 00011 * Redistributions in binary form must reproduce the above copyright 00012 notice, this list of conditions and the following disclaimer in 00013 the documentation and/or other materials provided with the 00014 distribution. 00015 00016 * Neither the name of the copyright holders nor the names of 00017 contributors may be used to endorse or promote products derived 00018 from this software without specific prior written permission. 00019 00020 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 POSSIBILITY OF SUCH DAMAGE. */ 00031 00032 /* $Id$ */ 00033 00034 /* 00035 avr/wdt.h - macros for AVR watchdog timer 00036 */ 00037 00038 #ifndef _AVR_WDT_H_ 00039 #define _AVR_WDT_H_ 00040 00041 #include <avr/io.h> 00042 #include <stdint.h> 00043 00044 /** \file */ 00045 /** \defgroup avr_watchdog <avr/wdt.h>: Watchdog timer handling 00046 \code #include <avr/wdt.h> \endcode 00047 00048 This header file declares the interface to some inline macros 00049 handling the watchdog timer present in many AVR devices. In order 00050 to prevent the watchdog timer configuration from being 00051 accidentally altered by a crashing application, a special timed 00052 sequence is required in order to change it. The macros within 00053 this header file handle the required sequence automatically 00054 before changing any value. Interrupts will be disabled during 00055 the manipulation. 00056 00057 \note Depending on the fuse configuration of the particular 00058 device, further restrictions might apply, in particular it might 00059 be disallowed to turn off the watchdog timer. 00060 00061 Note that for newer devices (ATmega88 and newer, effectively any 00062 AVR that has the option to also generate interrupts), the watchdog 00063 timer remains active even after a system reset (except a power-on 00064 condition), using the fastest prescaler value (approximately 15 00065 ms). It is therefore required to turn off the watchdog early 00066 during program startup, the datasheet recommends a sequence like 00067 the following: 00068 00069 \code 00070 #include <stdint.h> 00071 #include <avr/wdt.h> 00072 00073 uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); 00074 00075 void get_mcusr(void) \ 00076 __attribute__((naked)) \ 00077 __attribute__((section(".init3"))); 00078 void get_mcusr(void) 00079 { 00080 mcusr_mirror = MCUSR; 00081 MCUSR = 0; 00082 wdt_disable(); 00083 } 00084 \endcode 00085 00086 Saving the value of MCUSR in \c mcusr_mirror is only needed if the 00087 application later wants to examine the reset source, but in particular, 00088 clearing the watchdog reset flag before disabling the 00089 watchdog is required, according to the datasheet. 00090 */ 00091 00092 /** 00093 \ingroup avr_watchdog 00094 Reset the watchdog timer. When the watchdog timer is enabled, 00095 a call to this instruction is required before the timer expires, 00096 otherwise a watchdog-initiated device reset will occur. 00097 */ 00098 00099 #define wdt_reset() __asm__ __volatile__ ("wdr") 00100 00101 #ifndef __DOXYGEN__ 00102 00103 #if defined(WDP3) 00104 # define _WD_PS3_MASK _BV(WDP3) 00105 #else 00106 # define _WD_PS3_MASK 0x00 00107 #endif 00108 00109 #if defined(WDTCSR) 00110 # define _WD_CONTROL_REG WDTCSR 00111 #elif defined(WDTCR) 00112 # define _WD_CONTROL_REG WDTCR 00113 #else 00114 # define _WD_CONTROL_REG WDT 00115 #endif 00116 00117 #if defined(WDTOE) 00118 #define _WD_CHANGE_BIT WDTOE 00119 #else 00120 #define _WD_CHANGE_BIT WDCE 00121 #endif 00122 00123 #endif /* !__DOXYGEN__ */ 00124 00125 00126 /** 00127 \ingroup avr_watchdog 00128 Enable the watchdog timer, configuring it for expiry after 00129 \c timeout (which is a combination of the \c WDP0 through 00130 \c WDP2 bits to write into the \c WDTCR register; For those devices 00131 that have a \c WDTCSR register, it uses the combination of the \c WDP0 00132 through \c WDP3 bits). 00133 00134 See also the symbolic constants \c WDTO_15MS et al. 00135 */ 00136 00137 00138 #if defined(__AVR_XMEGA__) 00139 00140 #if defined (WDT_CTRLA) && !defined(RAMPD) 00141 00142 #define wdt_enable(timeout) \ 00143 do { \ 00144 uint8_t temp; \ 00145 __asm__ __volatile__ ( \ 00146 "wdr" "\n\t" \ 00147 "out %[ccp_reg], %[ioreg_cen_mask]" "\n\t" \ 00148 "lds %[tmp], %[wdt_reg]" "\n\t" \ 00149 "sbr %[tmp], %[wdt_enable_timeout]" "\n\t" \ 00150 "sts %[wdt_reg], %[tmp]" "\n\t" \ 00151 "1:lds %[tmp], %[wdt_status_reg]" "\n\t" \ 00152 "sbrc %[tmp], %[wdt_syncbusy_bit]" "\n\t" \ 00153 "rjmp 1b" "\n\t" \ 00154 : [tmp] "=r" (temp) \ 00155 : [ccp_reg] "I" (_SFR_IO_ADDR(CCP)), \ 00156 [ioreg_cen_mask] "r" ((uint8_t)CCP_IOREG_gc), \ 00157 [wdt_reg] "n" (_SFR_MEM_ADDR(WDT_CTRLA)), \ 00158 [wdt_enable_timeout] "M" (timeout), \ 00159 [wdt_status_reg] "n" (_SFR_MEM_ADDR(WDT_STATUS)), \ 00160 [wdt_syncbusy_bit] "I" (WDT_SYNCBUSY_bm) \ 00161 ); \ 00162 } while(0) 00163 00164 #define wdt_disable() \ 00165 do { \ 00166 uint8_t temp; \ 00167 __asm__ __volatile__ ( \ 00168 "wdr" "\n\t" \ 00169 "out %[ccp_reg], %[ioreg_cen_mask]" "\n\t" \ 00170 "lds %[tmp], %[wdt_reg]" "\n\t" \ 00171 "cbr %[tmp], %[timeout_mask]" "\n\t" \ 00172 "sts %[wdt_reg], %[tmp]" "\n\t" \ 00173 : [tmp] "=r" (temp) \ 00174 : [ccp_reg] "I" (_SFR_IO_ADDR(CCP)), \ 00175 [ioreg_cen_mask] "r" ((uint8_t)CCP_IOREG_gc), \ 00176 [wdt_reg] "n" (_SFR_MEM_ADDR(WDT_CTRLA)),\ 00177 [timeout_mask] "I" (WDT_PERIOD_gm) \ 00178 ); \ 00179 } while(0) 00180 00181 #else // defined (WDT_CTRLA) && !defined(RAMPD) 00182 00183 /* 00184 wdt_enable(timeout) for xmega devices 00185 ** write signature (CCP_IOREG_gc) that enables change of protected I/O 00186 registers to the CCP register 00187 ** At the same time, 00188 1) set WDT change enable (WDT_CEN_bm) 00189 2) enable WDT (WDT_ENABLE_bm) 00190 3) set timeout (timeout) 00191 ** Synchronization starts when ENABLE bit of WDT is set. So, wait till it 00192 finishes (SYNCBUSY of STATUS register is automatically cleared after the 00193 sync is finished). 00194 */ 00195 #define wdt_enable(timeout) \ 00196 do { \ 00197 uint8_t temp; \ 00198 __asm__ __volatile__ ( \ 00199 "in __tmp_reg__, %[rampd]" "\n\t" \ 00200 "out %[rampd], __zero_reg__" "\n\t" \ 00201 "out %[ccp_reg], %[ioreg_cen_mask]" "\n\t" \ 00202 "sts %[wdt_reg], %[wdt_enable_timeout]" "\n\t" \ 00203 "1:lds %[tmp], %[wdt_status_reg]" "\n\t" \ 00204 "sbrc %[tmp], %[wdt_syncbusy_bit]" "\n\t" \ 00205 "rjmp 1b" "\n\t" \ 00206 "out %[rampd], __tmp_reg__" "\n\t" \ 00207 : [tmp] "=r" (temp) \ 00208 : [rampd] "I" (_SFR_IO_ADDR(RAMPD)), \ 00209 [ccp_reg] "I" (_SFR_IO_ADDR(CCP)), \ 00210 [ioreg_cen_mask] "r" ((uint8_t)CCP_IOREG_gc), \ 00211 [wdt_reg] "n" (_SFR_MEM_ADDR(WDT_CTRL)), \ 00212 [wdt_enable_timeout] "r" ((uint8_t)(WDT_CEN_bm | WDT_ENABLE_bm | timeout)), \ 00213 [wdt_status_reg] "n" (_SFR_MEM_ADDR(WDT_STATUS)), \ 00214 [wdt_syncbusy_bit] "I" (WDT_SYNCBUSY_bm) \ 00215 : "r0" \ 00216 ); \ 00217 } while(0) 00218 00219 #define wdt_disable() \ 00220 __asm__ __volatile__ ( \ 00221 "in __tmp_reg__, %[rampd]" "\n\t" \ 00222 "out %[rampd], __zero_reg__" "\n\t" \ 00223 "out %[ccp_reg], %[ioreg_cen_mask]" "\n\t" \ 00224 "sts %[wdt_reg], %[disable_mask]" "\n\t" \ 00225 "out %[rampd], __tmp_reg__" "\n\t" \ 00226 : \ 00227 : [rampd] "I" (_SFR_IO_ADDR(RAMPD)), \ 00228 [ccp_reg] "I" (_SFR_IO_ADDR(CCP)), \ 00229 [ioreg_cen_mask] "r" ((uint8_t)CCP_IOREG_gc), \ 00230 [wdt_reg] "n" (_SFR_MEM_ADDR(WDT_CTRL)), \ 00231 [disable_mask] "r" ((uint8_t)((~WDT_ENABLE_bm) | WDT_CEN_bm)) \ 00232 : "r0" \ 00233 ); 00234 00235 #endif // defined (WDT_CTRLA) && !defined(RAMPD) 00236 00237 #elif defined(__AVR_TINY__) 00238 00239 #define wdt_enable(value) \ 00240 __asm__ __volatile__ ( \ 00241 "in __tmp_reg__,__SREG__" "\n\t" \ 00242 "cli" "\n\t" \ 00243 "wdr" "\n\t" \ 00244 "out %[CCPADDRESS],%[SIGNATURE]" "\n\t" \ 00245 "out %[WDTREG],%[WDVALUE]" "\n\t" \ 00246 "out __SREG__,__tmp_reg__" "\n\t" \ 00247 : /* no outputs */ \ 00248 : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), \ 00249 [SIGNATURE] "r" ((uint8_t)0xD8), \ 00250 [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), \ 00251 [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) \ 00252 | _BV(WDE) | (value & 0x07) )) \ 00253 : "r16" \ 00254 ) 00255 00256 #define wdt_disable() \ 00257 do { \ 00258 uint8_t temp_wd; \ 00259 __asm__ __volatile__ ( \ 00260 "in __tmp_reg__,__SREG__" "\n\t" \ 00261 "cli" "\n\t" \ 00262 "wdr" "\n\t" \ 00263 "out %[CCPADDRESS],%[SIGNATURE]" "\n\t" \ 00264 "in %[TEMP_WD],%[WDTREG]" "\n\t" \ 00265 "cbr %[TEMP_WD],%[WDVALUE]" "\n\t" \ 00266 "out %[WDTREG],%[TEMP_WD]" "\n\t" \ 00267 "out __SREG__,__tmp_reg__" "\n\t" \ 00268 : /*no output */ \ 00269 : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), \ 00270 [SIGNATURE] "r" ((uint8_t)0xD8), \ 00271 [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), \ 00272 [TEMP_WD] "d" (temp_wd), \ 00273 [WDVALUE] "n" (1 << WDE) \ 00274 : "r16" \ 00275 ); \ 00276 }while(0) 00277 00278 #elif defined(CCP) 00279 00280 static __inline__ 00281 __attribute__ ((__always_inline__)) 00282 void wdt_enable (const uint8_t value) 00283 { 00284 if (!_SFR_IO_REG_P (CCP) && !_SFR_IO_REG_P (_WD_CONTROL_REG)) 00285 { 00286 __asm__ __volatile__ ( 00287 "in __tmp_reg__,__SREG__" "\n\t" 00288 "cli" "\n\t" 00289 "wdr" "\n\t" 00290 "sts %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00291 "sts %[WDTREG],%[WDVALUE]" "\n\t" 00292 "out __SREG__,__tmp_reg__" "\n\t" 00293 : /* no outputs */ 00294 : [CCPADDRESS] "n" (_SFR_MEM_ADDR(CCP)), 00295 [SIGNATURE] "r" ((uint8_t)0xD8), 00296 [WDTREG] "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), 00297 [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) 00298 | _BV(WDE) | (value & 0x07) )) 00299 : "r0" 00300 ); 00301 } 00302 else if (!_SFR_IO_REG_P (CCP) && _SFR_IO_REG_P (_WD_CONTROL_REG)) 00303 { 00304 __asm__ __volatile__ ( 00305 "in __tmp_reg__,__SREG__" "\n\t" 00306 "cli" "\n\t" 00307 "wdr" "\n\t" 00308 "sts %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00309 "out %[WDTREG],%[WDVALUE]" "\n\t" 00310 "out __SREG__,__tmp_reg__" "\n\t" 00311 : /* no outputs */ 00312 : [CCPADDRESS] "n" (_SFR_MEM_ADDR(CCP)), 00313 [SIGNATURE] "r" ((uint8_t)0xD8), 00314 [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), 00315 [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) 00316 | _BV(WDE) | (value & 0x07) )) 00317 : "r0" 00318 ); 00319 } 00320 else if (_SFR_IO_REG_P (CCP) && !_SFR_IO_REG_P (_WD_CONTROL_REG)) 00321 { 00322 __asm__ __volatile__ ( 00323 "in __tmp_reg__,__SREG__" "\n\t" 00324 "cli" "\n\t" 00325 "wdr" "\n\t" 00326 "out %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00327 "sts %[WDTREG],%[WDVALUE]" "\n\t" 00328 "out __SREG__,__tmp_reg__" "\n\t" 00329 : /* no outputs */ 00330 : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), 00331 [SIGNATURE] "r" ((uint8_t)0xD8), 00332 [WDTREG] "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), 00333 [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) 00334 | _BV(WDE) | (value & 0x07) )) 00335 : "r0" 00336 ); 00337 } 00338 else 00339 { 00340 __asm__ __volatile__ ( 00341 "in __tmp_reg__,__SREG__" "\n\t" 00342 "cli" "\n\t" 00343 "wdr" "\n\t" 00344 "out %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00345 "out %[WDTREG],%[WDVALUE]" "\n\t" 00346 "out __SREG__,__tmp_reg__" "\n\t" 00347 : /* no outputs */ 00348 : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), 00349 [SIGNATURE] "r" ((uint8_t)0xD8), 00350 [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), 00351 [WDVALUE] "r" ((uint8_t)((value & 0x08 ? _WD_PS3_MASK : 0x00) 00352 | _BV(WDE) | (value & 0x07) )) 00353 : "r0" 00354 ); 00355 } 00356 } 00357 00358 static __inline__ 00359 __attribute__ ((__always_inline__)) 00360 void wdt_disable (void) 00361 { 00362 if (!_SFR_IO_REG_P (CCP) && !_SFR_IO_REG_P(_WD_CONTROL_REG)) 00363 { 00364 uint8_t temp_wd; 00365 __asm__ __volatile__ ( 00366 "in __tmp_reg__,__SREG__" "\n\t" 00367 "cli" "\n\t" 00368 "wdr" "\n\t" 00369 "sts %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00370 "lds %[TEMP_WD],%[WDTREG]" "\n\t" 00371 "cbr %[TEMP_WD],%[WDVALUE]" "\n\t" 00372 "sts %[WDTREG],%[TEMP_WD]" "\n\t" 00373 "out __SREG__,__tmp_reg__" "\n\t" 00374 : /*no output */ 00375 : [CCPADDRESS] "n" (_SFR_MEM_ADDR(CCP)), 00376 [SIGNATURE] "r" ((uint8_t)0xD8), 00377 [WDTREG] "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), 00378 [TEMP_WD] "d" (temp_wd), 00379 [WDVALUE] "n" (1 << WDE) 00380 : "r0" 00381 ); 00382 } 00383 else if (!_SFR_IO_REG_P (CCP) && _SFR_IO_REG_P(_WD_CONTROL_REG)) 00384 { 00385 uint8_t temp_wd; 00386 __asm__ __volatile__ ( 00387 "in __tmp_reg__,__SREG__" "\n\t" 00388 "cli" "\n\t" 00389 "wdr" "\n\t" 00390 "sts %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00391 "in %[TEMP_WD],%[WDTREG]" "\n\t" 00392 "cbr %[TEMP_WD],%[WDVALUE]" "\n\t" 00393 "out %[WDTREG],%[TEMP_WD]" "\n\t" 00394 "out __SREG__,__tmp_reg__" "\n\t" 00395 : /*no output */ 00396 : [CCPADDRESS] "n" (_SFR_MEM_ADDR(CCP)), 00397 [SIGNATURE] "r" ((uint8_t)0xD8), 00398 [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), 00399 [TEMP_WD] "d" (temp_wd), 00400 [WDVALUE] "n" (1 << WDE) 00401 : "r0" 00402 ); 00403 } 00404 else if (_SFR_IO_REG_P (CCP) && !_SFR_IO_REG_P(_WD_CONTROL_REG)) 00405 { 00406 uint8_t temp_wd; 00407 __asm__ __volatile__ ( 00408 "in __tmp_reg__,__SREG__" "\n\t" 00409 "cli" "\n\t" 00410 "wdr" "\n\t" 00411 "out %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00412 "lds %[TEMP_WD],%[WDTREG]" "\n\t" 00413 "cbr %[TEMP_WD],%[WDVALUE]" "\n\t" 00414 "sts %[WDTREG],%[TEMP_WD]" "\n\t" 00415 "out __SREG__,__tmp_reg__" "\n\t" 00416 : /*no output */ 00417 : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), 00418 [SIGNATURE] "r" ((uint8_t)0xD8), 00419 [WDTREG] "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), 00420 [TEMP_WD] "d" (temp_wd), 00421 [WDVALUE] "n" (1 << WDE) 00422 : "r0" 00423 ); 00424 } 00425 else 00426 { 00427 uint8_t temp_wd; 00428 __asm__ __volatile__ ( 00429 "in __tmp_reg__,__SREG__" "\n\t" 00430 "cli" "\n\t" 00431 "wdr" "\n\t" 00432 "out %[CCPADDRESS],%[SIGNATURE]" "\n\t" 00433 "in %[TEMP_WD],%[WDTREG]" "\n\t" 00434 "cbr %[TEMP_WD],%[WDVALUE]" "\n\t" 00435 "out %[WDTREG],%[TEMP_WD]" "\n\t" 00436 "out __SREG__,__tmp_reg__" "\n\t" 00437 : /*no output */ 00438 : [CCPADDRESS] "I" (_SFR_IO_ADDR(CCP)), 00439 [SIGNATURE] "r" ((uint8_t)0xD8), 00440 [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), 00441 [TEMP_WD] "d" (temp_wd), 00442 [WDVALUE] "n" (1 << WDE) 00443 : "r0" 00444 ); 00445 } 00446 } 00447 00448 #else 00449 00450 static __inline__ 00451 __attribute__ ((__always_inline__)) 00452 void wdt_enable (const uint8_t value) 00453 { 00454 if (_SFR_IO_REG_P (_WD_CONTROL_REG)) 00455 { 00456 __asm__ __volatile__ ( 00457 "in __tmp_reg__,__SREG__" "\n\t" 00458 "cli" "\n\t" 00459 "wdr" "\n\t" 00460 "out %0, %1" "\n\t" 00461 "out __SREG__,__tmp_reg__" "\n\t" 00462 "out %0, %2" "\n \t" 00463 : /* no outputs */ 00464 : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), 00465 "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))), 00466 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | 00467 _BV(WDE) | (value & 0x07)) ) 00468 : "r0" 00469 ); 00470 } 00471 else 00472 { 00473 __asm__ __volatile__ ( 00474 "in __tmp_reg__,__SREG__" "\n\t" 00475 "cli" "\n\t" 00476 "wdr" "\n\t" 00477 "sts %0, %1" "\n\t" 00478 "out __SREG__,__tmp_reg__" "\n\t" 00479 "sts %0, %2" "\n \t" 00480 : /* no outputs */ 00481 : "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), 00482 "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))), 00483 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | 00484 _BV(WDE) | (value & 0x07)) ) 00485 : "r0" 00486 ); 00487 } 00488 } 00489 00490 static __inline__ 00491 __attribute__ ((__always_inline__)) 00492 void wdt_disable (void) 00493 { 00494 if (_SFR_IO_REG_P (_WD_CONTROL_REG)) 00495 { 00496 uint8_t register temp_reg; 00497 __asm__ __volatile__ ( 00498 "in __tmp_reg__,__SREG__" "\n\t" 00499 "cli" "\n\t" 00500 "wdr" "\n\t" 00501 "in %[TEMPREG],%[WDTREG]" "\n\t" 00502 "ori %[TEMPREG],%[WDCE_WDE]" "\n\t" 00503 "out %[WDTREG],%[TEMPREG]" "\n\t" 00504 "out %[WDTREG],__zero_reg__" "\n\t" 00505 "out __SREG__,__tmp_reg__" "\n\t" 00506 : [TEMPREG] "=d" (temp_reg) 00507 : [WDTREG] "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)), 00508 [WDCE_WDE] "n" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))) 00509 : "r0" 00510 ); 00511 } 00512 else 00513 { 00514 uint8_t register temp_reg; 00515 __asm__ __volatile__ ( 00516 "in __tmp_reg__,__SREG__" "\n\t" 00517 "cli" "\n\t" 00518 "wdr" "\n\t" 00519 "lds %[TEMPREG],%[WDTREG]" "\n\t" 00520 "ori %[TEMPREG],%[WDCE_WDE]" "\n\t" 00521 "sts %[WDTREG],%[TEMPREG]" "\n\t" 00522 "sts %[WDTREG],__zero_reg__" "\n\t" 00523 "out __SREG__,__tmp_reg__" "\n\t" 00524 : [TEMPREG] "=d" (temp_reg) 00525 : [WDTREG] "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), 00526 [WDCE_WDE] "n" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))) 00527 : "r0" 00528 ); 00529 } 00530 } 00531 00532 #endif 00533 00534 00535 /** 00536 \ingroup avr_watchdog 00537 Symbolic constants for the watchdog timeout. Since the watchdog 00538 timer is based on a free-running RC oscillator, the times are 00539 approximate only and apply to a supply voltage of 5 V. At lower 00540 supply voltages, the times will increase. For older devices, the 00541 times will be as large as three times when operating at Vcc = 3 V, 00542 while the newer devices (e. g. ATmega128, ATmega8) only experience 00543 a negligible change. 00544 00545 Possible timeout values are: 15 ms, 30 ms, 60 ms, 120 ms, 250 ms, 00546 500 ms, 1 s, 2 s. (Some devices also allow for 4 s and 8 s.) 00547 Symbolic constants are formed by the prefix 00548 \c WDTO_, followed by the time. 00549 00550 Example that would select a watchdog timer expiry of approximately 00551 500 ms: 00552 \code 00553 wdt_enable(WDTO_500MS); 00554 \endcode 00555 */ 00556 #define WDTO_15MS 0 00557 00558 /** \ingroup avr_watchdog 00559 See \c WDTO_15MS */ 00560 #define WDTO_30MS 1 00561 00562 /** \ingroup avr_watchdog 00563 See \c WDTO_15MS */ 00564 #define WDTO_60MS 2 00565 00566 /** \ingroup avr_watchdog 00567 See \c WDTO_15MS */ 00568 #define WDTO_120MS 3 00569 00570 /** \ingroup avr_watchdog 00571 See \c WDTO_15MS */ 00572 #define WDTO_250MS 4 00573 00574 /** \ingroup avr_watchdog 00575 See \c WDTO_15MS */ 00576 #define WDTO_500MS 5 00577 00578 /** \ingroup avr_watchdog 00579 See \c WDTO_15MS */ 00580 #define WDTO_1S 6 00581 00582 /** \ingroup avr_watchdog 00583 See \c WDTO_15MS */ 00584 #define WDTO_2S 7 00585 00586 #if defined(__DOXYGEN__) || defined(WDP3) 00587 00588 /** \ingroup avr_watchdog 00589 See \c WDTO_15MS 00590 Note: This is only available on the 00591 ATtiny2313, 00592 ATtiny24, ATtiny44, ATtiny84, ATtiny84A, 00593 ATtiny25, ATtiny45, ATtiny85, 00594 ATtiny261, ATtiny461, ATtiny861, 00595 ATmega48, ATmega88, ATmega168, 00596 ATmega48P, ATmega88P, ATmega168P, ATmega328P, 00597 ATmega164P, ATmega324P, ATmega644P, ATmega644, 00598 ATmega640, ATmega1280, ATmega1281, ATmega2560, ATmega2561, 00599 ATmega8HVA, ATmega16HVA, ATmega32HVB, 00600 ATmega406, ATmega1284P, 00601 AT90PWM1, AT90PWM2, AT90PWM2B, AT90PWM3, AT90PWM3B, AT90PWM216, AT90PWM316, 00602 AT90PWM81, AT90PWM161, 00603 AT90USB82, AT90USB162, 00604 AT90USB646, AT90USB647, AT90USB1286, AT90USB1287, 00605 ATtiny48, ATtiny88. 00606 00607 Note: This value does <em>not</em> match the bit pattern of the 00608 respective control register. It is solely meant to be used together 00609 with wdt_enable(). 00610 */ 00611 #define WDTO_4S 8 00612 00613 /** \ingroup avr_watchdog 00614 See \c WDTO_15MS 00615 Note: This is only available on the 00616 ATtiny2313, 00617 ATtiny24, ATtiny44, ATtiny84, ATtiny84A, 00618 ATtiny25, ATtiny45, ATtiny85, 00619 ATtiny261, ATtiny461, ATtiny861, 00620 ATmega48, ATmega48A, ATmega48PA, ATmega88, ATmega168, 00621 ATmega48P, ATmega88P, ATmega168P, ATmega328P, 00622 ATmega164P, ATmega324P, ATmega644P, ATmega644, 00623 ATmega640, ATmega1280, ATmega1281, ATmega2560, ATmega2561, 00624 ATmega8HVA, ATmega16HVA, ATmega32HVB, 00625 ATmega406, ATmega1284P, 00626 ATmega2564RFR2, ATmega256RFR2, ATmega1284RFR2, ATmega128RFR2, ATmega644RFR2, ATmega64RFR2 00627 AT90PWM1, AT90PWM2, AT90PWM2B, AT90PWM3, AT90PWM3B, AT90PWM216, AT90PWM316, 00628 AT90PWM81, AT90PWM161, 00629 AT90USB82, AT90USB162, 00630 AT90USB646, AT90USB647, AT90USB1286, AT90USB1287, 00631 ATtiny48, ATtiny88, 00632 ATxmega16a4u, ATxmega32a4u, 00633 ATxmega16c4, ATxmega32c4, 00634 ATxmega128c3, ATxmega192c3, ATxmega256c3. 00635 00636 Note: This value does <em>not</em> match the bit pattern of the 00637 respective control register. It is solely meant to be used together 00638 with wdt_enable(). 00639 */ 00640 #define WDTO_8S 9 00641 00642 #endif /* defined(__DOXYGEN__) || defined(WDP3) */ 00643 00644 00645 #endif /* _AVR_WDT_H_ */