XMEGA Application Note


sleepmgr.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
00049 /*============================ INCLUDES ======================================*/
00050 #include <stdint.h>
00051 //#include "assert.h"
00052 //#include "compiler.h"
00053 #include "avr_compiler.h"
00054 #include "sleepmgr.h"
00055 #include "config_sleepmgr.h"
00056 
00057 
00058 
00059 /*============================ PRIVATE VARIABLES AND CONSTANTS ===============*/
00060 
00061 // Use macro from "config_sleepmgr.h" to define sleep mode config values.
00062 SLEEPMGR_DEFINE_MODES;
00064 SLEEPMGR_lock_t SLEEPMGR_locks[SLEEPMGR_NUM_MODES];
00065 
00066 
00067 
00068 /*============================ IMPLEMENTATION (PUBLIC FUNCTIONS) =============*/
00069 
00074 void SLEEPMGR_Init( void )
00075 {
00076         // Set all mode locks to zero, except the last one, which is handled below.
00077         for (uint8_t index = 0; index < (SLEEPMGR_NUM_MODES - 1); ++index) {
00078                 SLEEPMGR_locks[index] = 0;
00079         }
00080         
00081         // Lock the deepest sleep mode once and for all, to ease the search
00082         // implementation in SLEEPMGR_Sleep() later.
00083         SLEEPMGR_locks[SLEEPMGR_NUM_MODES - 1] = 1;
00084 }
00085 
00086 
00102 void SLEEPMGR_Lock( SLEEPMGR_mode_t mode )
00103 {
00104         // The following must be an atomic operation, to avoid race conditions.
00105         ENTER_CRITICAL_REGION();
00106         
00107                 // Check that lock has not reached max value for its datatype.
00108                 // By casting "-1L" to the correct datatype, we always get max value.
00109 //              assert( SLEEPMGR_locks[mode] != (SLEEPMGR_mode_t) -1L );
00110                 // Now it's safe to increase the lock counter.
00111                 ++SLEEPMGR_locks[mode];
00112         
00113         LEAVE_CRITICAL_REGION();
00114 }
00115 
00116 
00132 void SLEEPMGR_Unlock( SLEEPMGR_mode_t mode )
00133 {
00134         // The following must be an atomic operation, to avoid race conditions.
00135         ENTER_CRITICAL_REGION();
00136         
00137                 // Check that lock is not already zero,
00138                 // which would mean lock/unlock has not been handle correctly.
00139 //              assert( SLEEPMGR_locks[mode] != 0 );
00140                 // Now it's safe to decrease the lock counter.
00141                 --SLEEPMGR_locks[mode];
00142         
00143         LEAVE_CRITICAL_REGION();
00144 }
00145 
00146 
00152 void SLEEPMGR_Sleep( void )
00153 {
00154         // The following must be an atomic operation, to avoid race conditions.
00155         // No need to save the interrupt state, as we must enable global interrupts
00156         // anyway to be able to wake up from sleep.
00157         cli();
00158         
00159         // Make sure the deepest sleep mode is actually locked, which should have
00160         // been done in SLEEPMGR_Init at least. This ensures that the search
00161         // below will succeed.
00162 //      assert( SLEEPMGR_locks[SLEEPMGR_NUM_MODES - 1] > 0 );
00163         
00164         // Search from shallowest sleep mode until a non-zero lock is found.
00165         SLEEPMGR_lock_t const * lockPtr = SLEEPMGR_locks;
00166         uint8_t PROGMEM_PTR_T modePtr = SLEEPMGR_modes;
00167         while (*lockPtr == 0) {
00168                 ++lockPtr;
00169                 ++modePtr;
00170         }
00171         
00172         // Prepare sleep configuration, not touching other fields in register.
00173         uint8_t modeConfig = PROGMEM_READ_BYTE( modePtr );
00174         SLEEPMGR_PREPARE_SLEEP( modeConfig );
00175 
00176         // Enable interrupts before sleeping, otherwise we won't wake up.
00177         sei();
00178 
00179         // Now, enter sleep mode. Any pending interrupts will cause the device
00180         // to instantaneously wake up.
00181         cpu_sleep();
00182         
00183         // After waking up, we disable sleep.
00184         SLEEPMGR_DISABLE_SLEEP();
00185 }
00186 
00187 
00196 void SLEEPMGR_CancelSleep( void )
00197 {
00198         // Disable sleep, so that any SLEEP instruction will fail.
00199         SLEEPMGR_DISABLE_SLEEP();
00200 }
00201 
00202 
00203 /* EOF */
@DOC_TITLE@
Generated on Mon Nov 9 13:44:26 2009 for XMEGA power consumption evaluation code by doxygen 1.5.9