$treeview $search $mathjax $extrastylesheet
avr-libc  2.0.0
$projectbrief
$projectbrief
$searchbox

AVR Libc Home Page

AVRs

AVR Libc Development Pages

Main Page

User Manual

Library Reference

FAQ

Example Projects

sleep.h

Go to the documentation of this file.
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$ */
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     #define _SLEEP_SMODE_GROUP_MASK  SLEEP_SMODE_gm
00144 
00145 #elif defined(SLPCTRL)
00146 
00147     /* New xmega devices */
00148     #define _SLEEP_CONTROL_REG  SLPCTRL_CTRLA
00149     #define _SLEEP_ENABLE_MASK  SLPCTRL_SEN_bm
00150     #define _SLEEP_SMODE_GROUP_MASK  SLPCTRL_SMODE_gm
00151 
00152 #elif defined(SMCR)
00153 
00154     #define _SLEEP_CONTROL_REG  SMCR
00155     #define _SLEEP_ENABLE_MASK  _BV(SE)
00156 
00157 #elif defined(__AVR_AT94K__)
00158 
00159     #define _SLEEP_CONTROL_REG  MCUR
00160     #define _SLEEP_ENABLE_MASK  _BV(SE)
00161 
00162 #elif !defined(__DOXYGEN__)
00163 
00164     #define _SLEEP_CONTROL_REG  MCUCR
00165     #define _SLEEP_ENABLE_MASK  _BV(SE)
00166 
00167 #endif
00168 
00169 
00170 /* Special casing these three devices - they are the
00171    only ones that need to write to more than one register. */
00172 #if defined(__AVR_ATmega161__)
00173 
00174     #define set_sleep_mode(mode) \
00175     do { \
00176         MCUCR = ((MCUCR & ~_BV(SM1)) | ((mode) == SLEEP_MODE_PWR_DOWN || (mode) == SLEEP_MODE_PWR_SAVE ? _BV(SM1) : 0)); \
00177         EMCUCR = ((EMCUCR & ~_BV(SM0)) | ((mode) == SLEEP_MODE_PWR_SAVE ? _BV(SM0) : 0)); \
00178     } while(0)
00179 
00180 
00181 #elif defined(__AVR_ATmega162__) \
00182 || defined(__AVR_ATmega8515__)
00183 
00184     #define set_sleep_mode(mode) \
00185     do { \
00186         MCUCR = ((MCUCR & ~_BV(SM1)) | ((mode) == SLEEP_MODE_IDLE ? 0 : _BV(SM1))); \
00187         MCUCSR = ((MCUCSR & ~_BV(SM2)) | ((mode) == SLEEP_MODE_STANDBY  || (mode) == SLEEP_MODE_EXT_STANDBY ? _BV(SM2) : 0)); \
00188         EMCUCR = ((EMCUCR & ~_BV(SM0)) | ((mode) == SLEEP_MODE_PWR_SAVE || (mode) == SLEEP_MODE_EXT_STANDBY ? _BV(SM0) : 0)); \
00189     } while(0)
00190 
00191 /* For xmegas, check presence of SLEEP_SMODE<n>_bm and define set_sleep_mode accordingly. */
00192 #elif defined(__AVR_XMEGA__)
00193 
00194 #define set_sleep_mode(mode) \
00195   do { \
00196     _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~(_SLEEP_SMODE_GROUP_MASK)) | (mode)); \
00197   } while(0)
00198 
00199 /* For everything else, check for presence of SM<n> and define set_sleep_mode accordingly. */
00200 #else
00201 #if defined(SM2)
00202 
00203     #define set_sleep_mode(mode) \
00204     do { \
00205         _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~(_BV(SM0) | _BV(SM1) | _BV(SM2))) | (mode)); \
00206     } while(0)
00207 
00208 #elif defined(SM1)
00209 
00210     #define set_sleep_mode(mode) \
00211     do { \
00212         _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~(_BV(SM0) | _BV(SM1))) | (mode)); \
00213     } while(0)
00214 
00215 #elif defined(SM)
00216 
00217     #define set_sleep_mode(mode) \
00218     do { \
00219         _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~_BV(SM)) | (mode)); \
00220     } while(0)
00221 
00222 #else
00223 
00224     #error "No SLEEP mode defined for this device."
00225 
00226 #endif /* if defined(SM2) */
00227 #endif /* #if defined(__AVR_ATmega161__) */
00228 
00229 
00230 
00231 /** \ingroup avr_sleep
00232 
00233     Put the device in sleep mode. How the device is brought out of sleep mode
00234     depends on the specific mode selected with the set_sleep_mode() function.
00235     See the data sheet for your device for more details. */
00236 
00237 
00238 #if defined(__DOXYGEN__)
00239 
00240 /** \ingroup avr_sleep
00241 
00242     Set the SE (sleep enable) bit.
00243 */
00244 extern void sleep_enable (void);
00245 
00246 #else
00247 
00248 #define sleep_enable()             \
00249 do {                               \
00250   _SLEEP_CONTROL_REG |= (uint8_t)_SLEEP_ENABLE_MASK;   \
00251 } while(0)
00252 
00253 #endif
00254 
00255 
00256 #if defined(__DOXYGEN__)
00257 
00258 /** \ingroup avr_sleep
00259 
00260     Clear the SE (sleep enable) bit.
00261 */
00262 extern void sleep_disable (void);
00263 
00264 #else
00265 
00266 #define sleep_disable()            \
00267 do {                               \
00268   _SLEEP_CONTROL_REG &= (uint8_t)(~_SLEEP_ENABLE_MASK);  \
00269 } while(0)
00270 
00271 #endif
00272 
00273 
00274 /** \ingroup avr_sleep
00275 
00276     Put the device into sleep mode.  The SE bit must be set
00277     beforehand, and it is recommended to clear it afterwards.
00278 */
00279 #if defined(__DOXYGEN__)
00280 
00281 extern void sleep_cpu (void);
00282 
00283 #else
00284 
00285 #define sleep_cpu()                              \
00286 do {                                             \
00287   __asm__ __volatile__ ( "sleep" "\n\t" :: );    \
00288 } while(0)
00289 
00290 #endif
00291 
00292 
00293 #if defined(__DOXYGEN__)
00294 
00295 /** \ingroup avr_sleep
00296 
00297     Put the device into sleep mode, taking care of setting
00298     the SE bit before, and clearing it afterwards. */
00299 extern void sleep_mode (void);
00300 
00301 #else
00302 
00303 #define sleep_mode() \
00304 do {                 \
00305     sleep_enable();  \
00306     sleep_cpu();     \
00307     sleep_disable(); \
00308 } while (0)
00309 
00310 #endif
00311 
00312 
00313 #if defined(__DOXYGEN__)
00314 
00315 /** \ingroup avr_sleep
00316 
00317     Disable BOD before going to sleep.
00318     Not available on all devices.
00319 */
00320 extern void sleep_bod_disable (void);
00321 
00322 #else
00323 
00324 #if defined(BODS) && defined(BODSE)
00325 
00326 #ifdef BODCR
00327 
00328 #define BOD_CONTROL_REG BODCR
00329 
00330 #else
00331 
00332 #define BOD_CONTROL_REG MCUCR
00333 
00334 #endif
00335 
00336 #define sleep_bod_disable() \
00337 do { \
00338   uint8_t tempreg; \
00339   __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
00340                        "ori %[tempreg], %[bods_bodse]" "\n\t" \
00341                        "out %[mcucr], %[tempreg]" "\n\t" \
00342                        "andi %[tempreg], %[not_bodse]" "\n\t" \
00343                        "out %[mcucr], %[tempreg]" \
00344                        : [tempreg] "=&d" (tempreg) \
00345                        : [mcucr] "I" _SFR_IO_ADDR(BOD_CONTROL_REG), \
00346                          [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
00347                          [not_bodse] "i" (~_BV(BODSE))); \
00348 } while (0)
00349 
00350 #endif
00351 
00352 #endif
00353 
00354 
00355 /*@}*/
00356 
00357 #endif /* _AVR_SLEEP_H_ */
 All Data Structures Files Functions Variables Typedefs Enumerations Defines