$extrastylesheet
avr-libc
2.0.0
Standard C library for AVR-GCC
|
AVR Libc Home Page |
![]() |
AVR Libc Development Pages |
|||
Main Page |
User Manual |
Library Reference |
FAQ |
Example Projects |
00001 /* Copyright (c) 2002, 2004 Theodore A. Roth 00002 Copyright (c) 2004, 2007, 2008 Eric B. Weddington 00003 Copyright (c) 2005, 2006, 2007 Joerg Wunsch 00004 All rights reserved. 00005 00006 Redistribution and use in source and binary forms, with or without 00007 modification, are permitted provided that the following conditions are met: 00008 00009 * Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in 00014 the documentation and/or other materials provided with the 00015 distribution. 00016 00017 * Neither the name of the copyright holders nor the names of 00018 contributors may be used to endorse or promote products derived 00019 from this software without specific prior written permission. 00020 00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00022 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00023 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00024 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00025 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00026 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00027 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00030 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 POSSIBILITY OF SUCH DAMAGE. */ 00032 00033 /* $Id: sleep.h 2503 2016-02-07 22:59:47Z joerg_wunsch $ */ 00034 00035 #ifndef _AVR_SLEEP_H_ 00036 #define _AVR_SLEEP_H_ 1 00037 00038 #include <avr/io.h> 00039 #include <stdint.h> 00040 00041 00042 /** \file */ 00043 00044 /** \defgroup avr_sleep <avr/sleep.h>: Power Management and Sleep Modes 00045 00046 \code #include <avr/sleep.h>\endcode 00047 00048 Use of the \c SLEEP instruction can allow an application to reduce its 00049 power comsumption considerably. AVR devices can be put into different 00050 sleep modes. Refer to the datasheet for the details relating to the device 00051 you are using. 00052 00053 There are several macros provided in this header file to actually 00054 put the device into sleep mode. The simplest way is to optionally 00055 set the desired sleep mode using \c set_sleep_mode() (it usually 00056 defaults to idle mode where the CPU is put on sleep but all 00057 peripheral clocks are still running), and then call 00058 \c sleep_mode(). This macro automatically sets the sleep enable bit, goes 00059 to sleep, and clears the sleep enable bit. 00060 00061 Example: 00062 \code 00063 #include <avr/sleep.h> 00064 00065 ... 00066 set_sleep_mode(<mode>); 00067 sleep_mode(); 00068 \endcode 00069 00070 Note that unless your purpose is to completely lock the CPU (until a 00071 hardware reset), interrupts need to be enabled before going to sleep. 00072 00073 As the \c sleep_mode() macro might cause race conditions in some 00074 situations, the individual steps of manipulating the sleep enable 00075 (SE) bit, and actually issuing the \c SLEEP instruction, are provided 00076 in the macros \c sleep_enable(), \c sleep_disable(), and 00077 \c sleep_cpu(). This also allows for test-and-sleep scenarios that 00078 take care of not missing the interrupt that will awake the device 00079 from sleep. 00080 00081 Example: 00082 \code 00083 #include <avr/interrupt.h> 00084 #include <avr/sleep.h> 00085 00086 ... 00087 set_sleep_mode(<mode>); 00088 cli(); 00089 if (some_condition) 00090 { 00091 sleep_enable(); 00092 sei(); 00093 sleep_cpu(); 00094 sleep_disable(); 00095 } 00096 sei(); 00097 \endcode 00098 00099 This sequence ensures an atomic test of \c some_condition with 00100 interrupts being disabled. If the condition is met, sleep mode 00101 will be prepared, and the \c SLEEP instruction will be scheduled 00102 immediately after an \c SEI instruction. As the intruction right 00103 after the \c SEI is guaranteed to be executed before an interrupt 00104 could trigger, it is sure the device will really be put to sleep. 00105 00106 Some devices have the ability to disable the Brown Out Detector (BOD) before 00107 going to sleep. This will also reduce power while sleeping. If the 00108 specific AVR device has this ability then an additional macro is defined: 00109 \c sleep_bod_disable(). This macro generates inlined assembly code 00110 that will correctly implement the timed sequence for disabling the BOD 00111 before sleeping. However, there is a limited number of cycles after the 00112 BOD has been disabled that the device can be put into sleep mode, otherwise 00113 the BOD will not truly be disabled. Recommended practice is to disable 00114 the BOD (\c sleep_bod_disable()), set the interrupts (\c sei()), and then 00115 put the device to sleep (\c sleep_cpu()), like so: 00116 00117 \code 00118 #include <avr/interrupt.h> 00119 #include <avr/sleep.h> 00120 00121 ... 00122 set_sleep_mode(<mode>); 00123 cli(); 00124 if (some_condition) 00125 { 00126 sleep_enable(); 00127 sleep_bod_disable(); 00128 sei(); 00129 sleep_cpu(); 00130 sleep_disable(); 00131 } 00132 sei(); 00133 \endcode 00134 */ 00135 00136 00137 /* Define an internal sleep control register and an internal sleep enable bit mask. */ 00138 #if defined(SLEEP_CTRL) 00139 00140 /* XMEGA devices */ 00141 #define _SLEEP_CONTROL_REG SLEEP_CTRL 00142 #define _SLEEP_ENABLE_MASK SLEEP_SEN_bm 00143 00144 #elif defined(SMCR) 00145 00146 #define _SLEEP_CONTROL_REG SMCR 00147 #define _SLEEP_ENABLE_MASK _BV(SE) 00148 00149 #elif defined(__AVR_AT94K__) 00150 00151 #define _SLEEP_CONTROL_REG MCUR 00152 #define _SLEEP_ENABLE_MASK _BV(SE) 00153 00154 #elif !defined(__DOXYGEN__) 00155 00156 #define _SLEEP_CONTROL_REG MCUCR 00157 #define _SLEEP_ENABLE_MASK _BV(SE) 00158 00159 #endif 00160 00161 00162 /* Special casing these three devices - they are the 00163 only ones that need to write to more than one register. */ 00164 #if defined(__AVR_ATmega161__) 00165 00166 #define set_sleep_mode(mode) \ 00167 do { \ 00168 MCUCR = ((MCUCR & ~_BV(SM1)) | ((mode) == SLEEP_MODE_PWR_DOWN || (mode) == SLEEP_MODE_PWR_SAVE ? _BV(SM1) : 0)); \ 00169 EMCUCR = ((EMCUCR & ~_BV(SM0)) | ((mode) == SLEEP_MODE_PWR_SAVE ? _BV(SM0) : 0)); \ 00170 } while(0) 00171 00172 00173 #elif defined(__AVR_ATmega162__) \ 00174 || defined(__AVR_ATmega8515__) 00175 00176 #define set_sleep_mode(mode) \ 00177 do { \ 00178 MCUCR = ((MCUCR & ~_BV(SM1)) | ((mode) == SLEEP_MODE_IDLE ? 0 : _BV(SM1))); \ 00179 MCUCSR = ((MCUCSR & ~_BV(SM2)) | ((mode) == SLEEP_MODE_STANDBY || (mode) == SLEEP_MODE_EXT_STANDBY ? _BV(SM2) : 0)); \ 00180 EMCUCR = ((EMCUCR & ~_BV(SM0)) | ((mode) == SLEEP_MODE_PWR_SAVE || (mode) == SLEEP_MODE_EXT_STANDBY ? _BV(SM0) : 0)); \ 00181 } while(0) 00182 00183 /* For xmegas, check presence of SLEEP_SMODE<n>_bm and define set_sleep_mode accordingly. */ 00184 #elif defined(__AVR_XMEGA__) 00185 #if defined(SLEEP_SMODE2_bm) 00186 00187 #define set_sleep_mode(mode) \ 00188 do { \ 00189 _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~(SLEEP_SMODE2_bm | SLEEP_SMODE1_bm | SLEEP_SMODE0_bm)) | (mode)); \ 00190 } while(0) 00191 00192 #elif defined(SLEEP_SMODE1_bm) 00193 00194 #define set_sleep_mode(mode) \ 00195 do { \ 00196 _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~(SLEEP_SMODE1_bm | SLEEP_SMODE0_bm)) | (mode)); \ 00197 } while(0) 00198 00199 #else 00200 00201 #define set_sleep_mode(mode) \ 00202 do { \ 00203 _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~( SLEEP_SMODE0_bm)) | (mode)); \ 00204 } while(0) 00205 00206 00207 #endif /* #if defined(SLEEP_SMODE2_bm) */ 00208 00209 /* For everything else, check for presence of SM<n> and define set_sleep_mode accordingly. */ 00210 #else 00211 #if defined(SM2) 00212 00213 #define set_sleep_mode(mode) \ 00214 do { \ 00215 _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~(_BV(SM0) | _BV(SM1) | _BV(SM2))) | (mode)); \ 00216 } while(0) 00217 00218 #elif defined(SM1) 00219 00220 #define set_sleep_mode(mode) \ 00221 do { \ 00222 _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~(_BV(SM0) | _BV(SM1))) | (mode)); \ 00223 } while(0) 00224 00225 #elif defined(SM) 00226 00227 #define set_sleep_mode(mode) \ 00228 do { \ 00229 _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~_BV(SM)) | (mode)); \ 00230 } while(0) 00231 00232 #else 00233 00234 #error "No SLEEP mode defined for this device." 00235 00236 #endif /* if defined(SM2) */ 00237 #endif /* #if defined(__AVR_ATmega161__) */ 00238 00239 00240 00241 /** \ingroup avr_sleep 00242 00243 Put the device in sleep mode. How the device is brought out of sleep mode 00244 depends on the specific mode selected with the set_sleep_mode() function. 00245 See the data sheet for your device for more details. */ 00246 00247 00248 #if defined(__DOXYGEN__) 00249 00250 /** \ingroup avr_sleep 00251 00252 Set the SE (sleep enable) bit. 00253 */ 00254 extern void sleep_enable (void); 00255 00256 #else 00257 00258 #define sleep_enable() \ 00259 do { \ 00260 _SLEEP_CONTROL_REG |= (uint8_t)_SLEEP_ENABLE_MASK; \ 00261 } while(0) 00262 00263 #endif 00264 00265 00266 #if defined(__DOXYGEN__) 00267 00268 /** \ingroup avr_sleep 00269 00270 Clear the SE (sleep enable) bit. 00271 */ 00272 extern void sleep_disable (void); 00273 00274 #else 00275 00276 #define sleep_disable() \ 00277 do { \ 00278 _SLEEP_CONTROL_REG &= (uint8_t)(~_SLEEP_ENABLE_MASK); \ 00279 } while(0) 00280 00281 #endif 00282 00283 00284 /** \ingroup avr_sleep 00285 00286 Put the device into sleep mode. The SE bit must be set 00287 beforehand, and it is recommended to clear it afterwards. 00288 */ 00289 #if defined(__DOXYGEN__) 00290 00291 extern void sleep_cpu (void); 00292 00293 #else 00294 00295 #define sleep_cpu() \ 00296 do { \ 00297 __asm__ __volatile__ ( "sleep" "\n\t" :: ); \ 00298 } while(0) 00299 00300 #endif 00301 00302 00303 #if defined(__DOXYGEN__) 00304 00305 /** \ingroup avr_sleep 00306 00307 Put the device into sleep mode, taking care of setting 00308 the SE bit before, and clearing it afterwards. */ 00309 extern void sleep_mode (void); 00310 00311 #else 00312 00313 #define sleep_mode() \ 00314 do { \ 00315 sleep_enable(); \ 00316 sleep_cpu(); \ 00317 sleep_disable(); \ 00318 } while (0) 00319 00320 #endif 00321 00322 00323 #if defined(__DOXYGEN__) 00324 00325 /** \ingroup avr_sleep 00326 00327 Disable BOD before going to sleep. 00328 Not available on all devices. 00329 */ 00330 extern void sleep_bod_disable (void); 00331 00332 #else 00333 00334 #if defined(BODS) && defined(BODSE) 00335 00336 #ifdef BODCR 00337 00338 #define BOD_CONTROL_REG BODCR 00339 00340 #else 00341 00342 #define BOD_CONTROL_REG MCUCR 00343 00344 #endif 00345 00346 #define sleep_bod_disable() \ 00347 do { \ 00348 uint8_t tempreg; \ 00349 __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \ 00350 "ori %[tempreg], %[bods_bodse]" "\n\t" \ 00351 "out %[mcucr], %[tempreg]" "\n\t" \ 00352 "andi %[tempreg], %[not_bodse]" "\n\t" \ 00353 "out %[mcucr], %[tempreg]" \ 00354 : [tempreg] "=&d" (tempreg) \ 00355 : [mcucr] "I" _SFR_IO_ADDR(BOD_CONTROL_REG), \ 00356 [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \ 00357 [not_bodse] "i" (~_BV(BODSE))); \ 00358 } while (0) 00359 00360 #endif 00361 00362 #endif 00363 00364 00365 /*@}*/ 00366 00367 #endif /* _AVR_SLEEP_H_ */