XMEGA Application Note | |||||
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 */
Generated on Mon Nov 9 13:44:26 2009 for XMEGA power consumption evaluation code by ![]() |