00001 /** @file hal/micro/cortexm3/sleep.c 00002 * 00003 * @brief STM32W108 micro specific sleep functions. 00004 * 00005 * <!--(C) COPYRIGHT 2010 STMicroelectronics. All rights reserved. --> 00006 */ 00007 00008 #include PLATFORM_HEADER 00009 #include "hal/micro/micro-common.h" 00010 #include "hal/micro/cortexm3/micro-common.h" 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026 00027 00028 00029 00030 00031 00032 00033 00034 00035 00036 00037 00038 00039 00040 00041 00042 00043 00044 00045 00046 00047 00048 00049 00050 00051 00052 00053 00054 00055 00056 00057 00058 00059 00060 00061 00062 00063 00064 00065 00066 00067 00068 00069 00070 00071 00072 00073 00074 00075 00076 00077 00078 00079 00080 00081 00082 00083 00084 00085 00086 00087 00088 00089 00090 00091 00092 00093 00094 00095 00096 //We don't have a real register to hold this composite information. 00097 //Pretend we do so halGetWakeInfo can operate like halGetResetInfo. 00098 //This "register" is only ever set by halInternalSleep. 00099 // [31] = WakeInfoValid 00100 // [30] = SleepSkipped 00101 // [29] = CSYSPWRUPREQ 00102 // [28] = CDBGPWRUPREQ 00103 // [27] = WAKE_CORE 00104 // [26] = TIMER_WAKE_WRAP 00105 // [25] = TIMER_WAKE_COMPB 00106 // [24] = TIMER_WAKE_COMPA 00107 // [23:0] = corresponding GPIO activity 00108 #define WAKEINFOVALID_INTERNAL_WAKE_EVENT_BIT 31 00109 #define SLEEPSKIPPED_INTERNAL_WAKE_EVENT_BIT 30 00110 #define CSYSPWRUPREQ_INTERNAL_WAKE_EVENT_BIT 29 00111 #define CDBGPWRUPREQ_INTERNAL_WAKE_EVENT_BIT 28 00112 #define WAKE_CORE_INTERNAL_WAKE_EVENT_BIT 27 00113 #define WRAP_INTERNAL_WAKE_EVENT_BIT 26 00114 #define CMPB_INTERNAL_WAKE_EVENT_BIT 25 00115 #define CMPA_INTERNAL_WAKE_EVENT_BIT 24 00116 //This define shifts events from the PWRUP_EVENT register into the proper 00117 //place in the halInternalWakeEvent variable 00118 #define INTERNAL_WAKE_EVENT_BIT_SHIFT 20 00119 00120 static int32u halInternalWakeEvent=0; 00121 00122 int32u halGetWakeInfo(void) 00123 { 00124 return halInternalWakeEvent; 00125 } 00126 00127 void halInternalSleep(SleepModes sleepMode) 00128 { 00129 //Timer restoring always takes place during the wakeup sequence. We save 00130 //the state here in case SLEEPMODE_NOTIMER is invoked, which would disable 00131 //the clocks. 00132 int32u SLEEPTMR_CLKEN_SAVED = SLEEPTMR_CLKEN; 00133 00134 //This code assumes all wake source registers are properly configured. 00135 //As such, it should be called from halSleepWithOptions() or from 00136 // halSleepForQsWithOptions() which configues the wake sources. 00137 00138 //The parameter gpioWakeSel is a bitfield composite of the GPIO wake 00139 //sources derived from the 3 ports, indicating which of the 24 GPIO 00140 //are configured as a wake source. 00141 int32u gpioWakeSel = (GPIO_PAWAKE<<0); 00142 gpioWakeSel |= (GPIO_PBWAKE<<8); 00143 gpioWakeSel |= (GPIO_PCWAKE<<16); 00144 00145 //PB2 is also WAKE_SC1. Set this wake source if PB2's GPIO wake is set. 00146 if(GPIO_PBWAKE & PB2) { 00147 WAKE_SEL |= WAKE_SC1; 00148 } 00149 00150 //PA2 is also WAKE_SC2. Set this wake source if PA2's GPIO wake is set. 00151 if(GPIO_PAWAKE & PA2) { 00152 WAKE_SEL |= WAKE_SC2; 00153 } 00154 00155 //The WAKE_IRQD source can come from any pin based on IRQD's sel register. 00156 if(gpioWakeSel & BIT(GPIO_IRQDSEL)) { 00157 WAKE_SEL |= WAKE_IRQD; 00158 } 00159 00160 halInternalWakeEvent = 0; //clear old wake events 00161 00162 switch(sleepMode) 00163 { 00164 case SLEEPMODE_NOTIMER: 00165 //The sleep timer clock sources (both RC and XTAL) are turned off. 00166 //Wakeup is possible from only GPIO. System time is lost. 00167 //NOTE: Timer restoring always takes place during the wakeup sequence. 00168 SLEEPTMR_CLKEN = 0; 00169 goto deepSleepCore; 00170 00171 case SLEEPMODE_WAKETIMER: 00172 //The sleep timer clock sources remain running. The RC is always 00173 //running and the 32kHz XTAL depends on the board header. Wakeup 00174 //is possible from both GPIO and the sleep timer. System time 00175 //is maintained. The sleep timer is assumed to be configured 00176 //properly for wake events. 00177 //NOTE: This mode assumes the caller has configured the *entire* 00178 // sleep timer properly. 00179 00180 if(INT_SLEEPTMRCFG&INT_SLEEPTMRWRAP) { 00181 WAKE_SEL |= WAKE_SLEEPTMRWRAP; 00182 } 00183 if(INT_SLEEPTMRCFG&INT_SLEEPTMRCMPB) { 00184 WAKE_SEL |= WAKE_SLEEPTMRCMPB; 00185 } 00186 if(INT_SLEEPTMRCFG&INT_SLEEPTMRCMPA) { 00187 WAKE_SEL |= WAKE_SLEEPTMRCMPA; 00188 } 00189 //fall into SLEEPMODE_MAINTAINTIMER's sleep code: 00190 00191 case SLEEPMODE_MAINTAINTIMER: 00192 //The sleep timer clock sources remain running. The RC is always 00193 //running and the 32kHz XTAL depends on the board header. Wakeup 00194 //is possible from only GPIO. System time is maintained. 00195 //NOTE: System time is maintained without any sleep timer interrupts 00196 // because the hardware sleep timer counter is large enough 00197 // to hold the entire count value and not need a RAM counter. 00198 00199 //////////////////////////////////////////////////////////////////////////// 00200 // Core deep sleep code 00201 //////////////////////////////////////////////////////////////////////////// 00202 deepSleepCore: 00203 // Interrupts *must* be/stay disabled for DEEP SLEEP operation 00204 // INTERRUPTS_OFF will use BASEPRI to disable all interrupts except 00205 // fault handlers and PendSV. 00206 INTERRUPTS_OFF(); 00207 // This is the point of no return. From here on out, only the interrupt 00208 // sources available in WAKE_SEL will be captured and propagated across 00209 // deep sleep. 00210 //stick all our saved info onto stack since it's only temporary 00211 { 00212 boolean restoreWatchdog = halInternalWatchDogEnabled(); 00213 boolean skipSleep = FALSE; 00214 00215 // Only three register blocks keep power across deep sleep: 00216 // CM_HV, GPIO, SLOW_TIMERS 00217 // 00218 // All other register blocks lose their state across deep sleep: 00219 // BASEBAND, MAC, SECURITY, SERIAL, TMR1, TMR2, EVENT, CM_LV, RAM_CTRL, 00220 // AUX_ADC, CAL_ADC, FLASH_CONTROL, ITM, DWT, FPB, NVIC, TPIU 00221 // 00222 // The sleep code will only save and restore registers where it is 00223 // meaningful and necessary to do so. In most cases, there must still 00224 // be a powerup function to restore proper state. 00225 // 00226 // NOTE: halPowerUp() and halPowerDown() will always be called before 00227 // and after this function. halPowerDown and halPowerUp should leave 00228 // the modules in a safe state and then restart the modules. 00229 // (For example, shutting down and restarting Timer1) 00230 // 00231 //----BASEBAND 00232 // reinitialized by stStackPowerUp() 00233 //----MAC 00234 // reinitialized by stStackPowerUp() 00235 //----SECURITY 00236 // reinitialized by stStackPowerUp() 00237 //----SERIAL 00238 // reinitialized by halPowerUp() or similar 00239 //----TMR1 00240 // reinitialized by halPowerUp() or similar 00241 //----TMR2 00242 // reinitialized by halPowerUp() or similar 00243 //----EVENT 00244 //SRC or FLAG interrupts are not saved or restored 00245 //MISS interrupts are not saved or restored 00246 //MAC_RX_INT_MASK - reinitialized by stStackPowerUp() 00247 //MAC_TX_INT_MASK - reinitialized by stStackPowerUp() 00248 //MAC_TIMER_INT_MASK - reinitialized by stStackPowerUp() 00249 //BB_INT_MASK - reinitialized by stStackPowerUp() 00250 //SEC_INT_MASK - reinitialized by stStackPowerUp() 00251 int32u INT_SLEEPTMRCFG_SAVED = INT_SLEEPTMRCFG_REG; 00252 int32u INT_MGMTCFG_SAVED = INT_MGMTCFG_REG; 00253 //INT_TIM1CFG - reinitialized by halPowerUp() or similar 00254 //INT_TIM2CFG - reinitialized by halPowerUp() or similar 00255 //INT_SC1CFG - reinitialized by halPowerUp() or similar 00256 //INT_SC2CFG - reinitialized by halPowerUp() or similar 00257 //INT_ADCCFG - reinitialized by halPowerUp() or similar 00258 int32u GPIO_INTCFGA_SAVED = GPIO_INTCFGA_REG; 00259 int32u GPIO_INTCFGB_SAVED = GPIO_INTCFGB_REG; 00260 int32u GPIO_INTCFGC_SAVED = GPIO_INTCFGC_REG; 00261 int32u GPIO_INTCFGD_SAVED = GPIO_INTCFGD_REG; 00262 //SC1_INTMODE - reinitialized by halPowerUp() or similar 00263 //SC2_INTMODE - reinitialized by halPowerUp() or similar 00264 //----CM_LV 00265 int32u OSC24M_BIASTRIM_SAVED = OSC24M_BIASTRIM_REG; 00266 int32u OSCHF_TUNE_SAVED = OSCHF_TUNE_REG; 00267 int32u DITHER_DIS_SAVED = DITHER_DIS_REG; 00268 //OSC24M_CTRL - reinitialized by halPowerUp() or similar 00269 //CPU_CLKSEL - reinitialized by halPowerUp() or similar 00270 //TMR1_CLK_SEL - reinitialized by halPowerUp() or similar 00271 //TMR2_CLK_SEL - reinitialized by halPowerUp() or similar 00272 int32u PCTRACE_SEL_SAVED = PCTRACE_SEL_REG; 00273 //----RAM_CTRL 00274 int32u MEM_PROT_0_SAVED = MEM_PROT_0_REG; 00275 int32u MEM_PROT_1_SAVED = MEM_PROT_1_REG; 00276 int32u MEM_PROT_2_SAVED = MEM_PROT_2_REG; 00277 int32u MEM_PROT_3_SAVED = MEM_PROT_3_REG; 00278 int32u MEM_PROT_4_SAVED = MEM_PROT_4_REG; 00279 int32u MEM_PROT_5_SAVED = MEM_PROT_5_REG; 00280 int32u MEM_PROT_6_SAVED = MEM_PROT_6_REG; 00281 int32u MEM_PROT_7_SAVED = MEM_PROT_7_REG; 00282 int32u MEM_PROT_EN_SAVED = MEM_PROT_EN_REG; 00283 //----AUX_ADC 00284 // reinitialized by halPowerUp() or similar 00285 //----CAL_ADC 00286 // reinitialized by stStackPowerUp() 00287 //----FLASH_CONTROL 00288 // configured on the fly by the flash library 00289 //----ITM 00290 // reinitialized by halPowerUp() or similar 00291 //----DWT 00292 // not used by software on chip 00293 //----FPB 00294 // not used by software on chip 00295 //----NVIC 00296 //ST_CSR - fixed, restored by cstartup when exiting deep sleep 00297 //ST_RVR - fixed, restored by cstartup when exiting deep sleep 00298 int32u INT_CFGSET_SAVED = INT_CFGSET_REG; //mask against wake sources 00299 //INT_PENDSET - used below when overlapping interrupts and wake sources 00300 //NVIC_IPR_3to0 - fixed, restored by cstartup when exiting deep sleep 00301 //NVIC_IPR_7to4 - fixed, restored by cstartup when exiting deep sleep 00302 //NVIC_IPR_11to8 - fixed, restored by cstartup when exiting deep sleep 00303 //NVIC_IPR_15to12 - fixed, restored by cstartup when exiting deep sleep 00304 //NVIC_IPR_19to16 - fixed, restored by cstartup when exiting deep sleep 00305 int32u SCS_VTOR_SAVED = SCS_VTOR_REG; 00306 //SCS_CCR - fixed, restored by cstartup when exiting deep sleep 00307 //SCS_SHPR_7to4 - fixed, restored by cstartup when exiting deep sleep 00308 //SCS_SHPR_11to8 - fixed, restored by cstartup when exiting deep sleep 00309 //SCS_SHPR_15to12 - fixed, restored by cstartup when exiting deep sleep 00310 //SCS_SHCSR - fixed, restored by cstartup when exiting deep sleep 00311 //----TPIU 00312 // reinitialized by halPowerUp() or similar 00313 00314 //stmDebugPowerDown() should have shutdown the DWT/ITM/TPIU already. 00315 00316 //freeze input to the GPIO from LV (alternate output functions freeze) 00317 EVENT_CTRL = LV_FREEZE; 00318 //record GPIO state for wake monitoring purposes 00319 //By having a snapshot of GPIO state, we can figure out after waking 00320 //up exactly which GPIO could have woken us up. 00321 //Reading the three IN registers is done separately to avoid warnings 00322 //about undefined order of volatile access. 00323 int32u GPIO_IN_SAVED = GPIO_PAIN; 00324 GPIO_IN_SAVED |= (GPIO_PBIN<<8); 00325 GPIO_IN_SAVED |= (GPIO_PCIN<<16); 00326 //reset the power up events by writing 1 to all bits. 00327 PWRUP_EVENT = 0xFFFFFFFF; 00328 00329 00330 00331 //By clearing the events, the wake up event capturing is activated. 00332 //At this point we can safely check our interrupt flags since event 00333 //capturing is now overlapped. Up to now, interrupts indicate 00334 //activity, after this point, powerup events indicate activity. 00335 //If any of the interrupt flags are set, that means we saw a wake event 00336 //sometime while entering sleep, so we need to skip over sleeping 00337 // 00338 //--possible interrupt sources for waking: 00339 // IRQA, IRQB, IRQC, IRQD 00340 // SleepTMR CMPA, CMPB, Wrap 00341 // WAKE_CORE (DebugIsr) 00342 // 00343 //check for IRQA interrupt and if IRQA (PB0) is wake source 00344 if((INT_PENDSET&INT_IRQA) && 00345 (GPIO_PBWAKE&PB0) && 00346 (WAKE_SEL&GPIO_WAKE)) { 00347 skipSleep = TRUE; 00348 //log IRQA as a wake event 00349 halInternalWakeEvent |= BIT(PORTB_PIN(0)); 00350 00351 00352 00353 } 00354 //check for IRQB interrupt and if IRQB (PB6) is wake source 00355 if((INT_PENDSET&INT_IRQB) && 00356 (GPIO_PBWAKE&PB6) && 00357 (WAKE_SEL&GPIO_WAKE)) { 00358 skipSleep = TRUE; 00359 //log IRQB as a wake event 00360 halInternalWakeEvent |= BIT(PORTB_PIN(6)); 00361 00362 00363 00364 } 00365 //check for IRQC interrupt and if IRQC (GPIO_IRQCSEL) is wake source 00366 if((INT_PENDSET&INT_IRQC) && 00367 (gpioWakeSel&BIT(GPIO_IRQCSEL)) && 00368 (WAKE_SEL&GPIO_WAKE)) { 00369 skipSleep = TRUE; 00370 //log IRQC as a wake event 00371 halInternalWakeEvent |= BIT(GPIO_IRQCSEL); 00372 00373 00374 00375 } 00376 //check for IRQD interrupt and if IRQD (GPIO_IRQDSEL) is wake source 00377 if((INT_PENDSET&INT_IRQD) && 00378 (gpioWakeSel&BIT(GPIO_IRQDSEL)) && 00379 ((WAKE_SEL&GPIO_WAKE) || 00380 (WAKE_SEL&WAKE_IRQD))) { 00381 skipSleep = TRUE; 00382 //log IRQD as a wake event 00383 halInternalWakeEvent |= BIT(GPIO_IRQDSEL); 00384 00385 00386 00387 } 00388 //check for SleepTMR CMPA interrupt and if SleepTMR CMPA is wake source 00389 if((INT_SLEEPTMR&INT_SLEEPTMRCMPA) && (WAKE_SEL&WAKE_SLEEPTMRCMPA)) { 00390 skipSleep = TRUE; 00391 //log SleepTMR CMPA as a wake event 00392 halInternalWakeEvent |= BIT32(CMPA_INTERNAL_WAKE_EVENT_BIT); 00393 00394 00395 00396 } 00397 //check for SleepTMR CMPB interrupt and if SleepTMR CMPB is wake source 00398 if((INT_SLEEPTMR&INT_SLEEPTMRCMPB) && (WAKE_SEL&WAKE_SLEEPTMRCMPB)) { 00399 skipSleep = TRUE; 00400 //log SleepTMR CMPB as a wake event 00401 halInternalWakeEvent |= BIT32(CMPB_INTERNAL_WAKE_EVENT_BIT); 00402 00403 00404 00405 } 00406 //check for SleepTMR WRAP interrupt and if SleepTMR WRAP is wake source 00407 if((INT_SLEEPTMR&INT_SLEEPTMRWRAP) && (WAKE_SEL&WAKE_SLEEPTMRWRAP)) { 00408 skipSleep = TRUE; 00409 //log SleepTMR WRAP as a wake event 00410 halInternalWakeEvent |= BIT32(WRAP_INTERNAL_WAKE_EVENT_BIT); 00411 00412 00413 00414 } 00415 //check for Debug interrupt and if WAKE_CORE is wake source 00416 if((INT_PENDSET&INT_DEBUG) && (WAKE_SEL&WAKE_WAKE_CORE)) { 00417 skipSleep = TRUE; 00418 //log WAKE_CORE as a wake event 00419 halInternalWakeEvent |= BIT32(WAKE_CORE_INTERNAL_WAKE_EVENT_BIT); 00420 00421 00422 00423 } 00424 00425 //only propagate across deep sleep the interrupts that are both 00426 //enabled and possible wake sources 00427 { 00428 int32u wakeSourceInterruptMask = 0; 00429 00430 if(GPIO_PBWAKE&PB0) { 00431 wakeSourceInterruptMask |= INT_IRQA; 00432 00433 00434 00435 } 00436 if(GPIO_PBWAKE&PB6) { 00437 wakeSourceInterruptMask |= INT_IRQB; 00438 00439 00440 00441 } 00442 if(gpioWakeSel&BIT(GPIO_IRQCSEL)) { 00443 wakeSourceInterruptMask |= INT_IRQC; 00444 00445 00446 00447 } 00448 if(gpioWakeSel&BIT(GPIO_IRQDSEL)) { 00449 wakeSourceInterruptMask |= INT_IRQD; 00450 00451 00452 00453 } 00454 if( (WAKE_SEL&WAKE_SLEEPTMRCMPA) || 00455 (WAKE_SEL&WAKE_SLEEPTMRCMPB) || 00456 (WAKE_SEL&WAKE_SLEEPTMRWRAP) ) { 00457 wakeSourceInterruptMask |= INT_SLEEPTMR; 00458 00459 00460 00461 } 00462 if(WAKE_SEL&WAKE_WAKE_CORE) { 00463 wakeSourceInterruptMask |= INT_DEBUG; 00464 00465 00466 00467 } 00468 00469 INT_CFGSET_SAVED &= wakeSourceInterruptMask; 00470 } 00471 00472 00473 00474 00475 00476 00477 00478 00479 00480 00481 00482 00483 00484 00485 00486 00487 00488 //disable watchdog while sleeping (since we can't reset it asleep) 00489 halInternalDisableWatchDog(MICRO_DISABLE_WATCH_DOG_KEY); 00490 00491 //The chip is not allowed to enter a deep sleep mode (which could 00492 //cause a core reset cycle) while CSYSPWRUPREQ is set. CSYSPWRUPREQ 00493 //indicates that the debugger is trying to access sections of the 00494 //chip that would get reset during deep sleep. Therefore, a reset 00495 //cycle could very easily cause the debugger to error and we don't 00496 //want that. While the power management state machine will stall 00497 //if CSYSPWRUPREQ is set (to avoid the situation just described), 00498 //in this stalled state the chip will not be responsive to wake 00499 //events. To be sensitive to wake events, we must handle them in 00500 //software instead. To accomplish this, we request that the 00501 //CSYSPWRUPACK be inhibited (which will indicate the debugger is not 00502 //connected). But, we cannot induce deep sleep until CSYSPWRUPREQ/ACK 00503 //go low and these are under the debuggers control, so we must stall 00504 //and wait here. If there is a wake event during this time, break 00505 //out and wake like normal. If the ACK eventually clears, 00506 //we can proceed into deep sleep. The CSYSPWRUPACK_INHIBIT 00507 //functionality will hold off the debugger (by holding off the ACK) 00508 //until we are safely past and out of deep sleep. The power management 00509 //state machine then becomes responsible for clearing 00510 //CSYSPWRUPACK_INHIBIT and responding to a CSYSPWRUPREQ with a 00511 //CSYSPWRUPACK at the right/safe time. 00512 CSYSPWRUPACK_INHIBIT = CSYSPWRUPACK_INHIBIT_CSYSPWRUPACK_INHIBIT; 00513 { 00514 //Use a local copy of WAKE_SEL to avoid warnings from the compiler 00515 //about order of volatile accesses 00516 int32u wakeSel = WAKE_SEL; 00517 //stall until a wake event or CSYSPWRUPREQ/ACK clears 00518 while( (CSYSPWRUPACK_STATUS) && (!(PWRUP_EVENT&wakeSel)) ) {} 00519 //if there was a wake event, allow CSYSPWRUPACK and skip sleep 00520 if(PWRUP_EVENT&wakeSel) { 00521 CSYSPWRUPACK_INHIBIT = CSYSPWRUPACK_INHIBIT_RESET; 00522 skipSleep = TRUE; 00523 } 00524 } 00525 00526 00527 00528 00529 00530 if(!skipSleep) { 00531 00532 00533 00534 //FogBugz 7283 states that we must switch to the OSCHF when entering 00535 //deep sleep since using the 24MHz XTAL could result in RAM 00536 //corruption. This switch must occur at least 2*24MHz cycles before 00537 //sleeping. 00538 //FogBugz 8858 states that we cannot go into deep-sleep when the 00539 //chip is clocked with the 24MHz XTAL with a duty cycle as low as 00540 //70/30 since this causes power_down generation timing to fail. 00541 OSC24M_CTRL &= ~OSC24M_CTRL_OSC24M_SEL; 00542 //If DS12 needs to be forced regardless of state, clear 00543 //REGEN_DSLEEP here. This is hugely dangerous and 00544 //should only be done in very controlled chip tests. 00545 SCS_SCR |= SCS_SCR_SLEEPDEEP; //enable deep sleep 00546 extern volatile boolean halPendSvSaveContext; 00547 halPendSvSaveContext = 1; //1 means save context 00548 //The INTERRUPTS_OFF used at the beginning of this function set 00549 //BASEPRI such that the only interrupts that will fire are faults 00550 //and PendSV. Trigger PendSV now to induce a context save. 00551 SCS_ICSR |= SCS_ICSR_PENDSVSET; //pend the context save and Dsleep 00552 //Since the interrupt will not fire immediately it is possible to 00553 //execute a few lines of code. To stay halted in this spot until the 00554 //WFI instruction, spin on the context flag (which will get cleared 00555 //during the startup sequence when restoring context). 00556 while(halPendSvSaveContext) {} 00557 //I AM ASLEEP. WHEN EXECUTION RESUMES, CSTARTUP WILL RESTORE TO HERE 00558 } else { 00559 //Record the fact that we skipped sleep 00560 halInternalWakeEvent |= BIT32(SLEEPSKIPPED_INTERNAL_WAKE_EVENT_BIT); 00561 //If this was a true deep sleep, we would have executed cstartup and 00562 //PRIMASK would be set right now. If we skipped sleep, PRIMASK is not 00563 //set so we explicitely set it to guarantee the powerup sequence 00564 //works cleanly and consistently with respect to interrupt 00565 //dispatching and enabling. 00566 _setPriMask(); 00567 } 00568 00569 00570 00571 00572 00573 00574 00575 00576 //Clear the interrupt flags for all wake sources. This 00577 //is necessary because if we don't execute an actual deep sleep cycle 00578 //the interrupt flags will never be cleared. By clearing the flags, 00579 //we always mimick a real deep sleep as closely as possible and 00580 //guard against any accidental interrupt triggering coming out 00581 //of deep sleep. (The interrupt dispatch code coming out of sleep 00582 //is responsible for translating wake events into interrupt events, 00583 //and if we don't clear interrupt flags here it's possible for an 00584 //interrupt to trigger even if it wasn't the true wake event.) 00585 INT_SLEEPTMRFLAG = (INT_SLEEPTMRCMPA | 00586 INT_SLEEPTMRCMPB | 00587 INT_SLEEPTMRWRAP); 00588 INT_GPIOFLAG = (INT_IRQAFLAG | 00589 INT_IRQBFLAG | 00590 INT_IRQCFLAG | 00591 INT_IRQDFLAG); 00592 00593 //immediately restore the registers we saved before sleeping 00594 //so IRQ and SleepTMR capture can be reenabled as quickly as possible 00595 //this is safe because our global interrupts are still disabled 00596 //other registers will be restored later 00597 00598 00599 00600 00601 00602 00603 00604 SLEEPTMR_CLKEN_REG = SLEEPTMR_CLKEN_SAVED; 00605 INT_SLEEPTMRCFG_REG = INT_SLEEPTMRCFG_SAVED; 00606 INT_MGMTCFG_REG = INT_MGMTCFG_SAVED; 00607 GPIO_INTCFGA_REG = GPIO_INTCFGA_SAVED; 00608 GPIO_INTCFGB_REG = GPIO_INTCFGB_SAVED; 00609 GPIO_INTCFGC_REG = GPIO_INTCFGC_SAVED; 00610 GPIO_INTCFGD_REG = GPIO_INTCFGD_SAVED; 00611 OSC24M_BIASTRIM_REG = OSC24M_BIASTRIM_SAVED; 00612 OSCHF_TUNE_REG = OSCHF_TUNE_SAVED; 00613 DITHER_DIS_REG = DITHER_DIS_SAVED; 00614 PCTRACE_SEL_REG = PCTRACE_SEL_SAVED; 00615 MEM_PROT_0_REG = MEM_PROT_0_SAVED; 00616 MEM_PROT_1_REG = MEM_PROT_1_SAVED; 00617 MEM_PROT_2_REG = MEM_PROT_2_SAVED; 00618 MEM_PROT_3_REG = MEM_PROT_3_SAVED; 00619 MEM_PROT_4_REG = MEM_PROT_4_SAVED; 00620 MEM_PROT_5_REG = MEM_PROT_5_SAVED; 00621 MEM_PROT_6_REG = MEM_PROT_6_SAVED; 00622 MEM_PROT_7_REG = MEM_PROT_7_SAVED; 00623 MEM_PROT_EN_REG = MEM_PROT_EN_SAVED; 00624 INT_CFGSET_REG = INT_CFGSET_SAVED; 00625 SCS_VTOR_REG = SCS_VTOR_SAVED; 00626 00627 //WAKE_CORE/INT_DEBUG and INT_IRQx is cleared by INT_PENDCLR below 00628 INT_PENDCLR = 0xFFFFFFFF; 00629 00630 //Now that we're awake, normal interrupts are operational again 00631 //Take a snapshot of the new GPIO state and the EVENT register to 00632 //record our wake event 00633 int32u GPIO_IN_NEW = GPIO_PAIN; 00634 GPIO_IN_NEW |= (GPIO_PBIN<<8); 00635 GPIO_IN_NEW |= (GPIO_PCIN<<16); 00636 //Only operate on power up events that are also wake events. Power 00637 //up events will always trigger like an interrupt flag, so we have 00638 //to check them against events that are enabled for waking. (This is 00639 //a two step process because we're accessing two volatile values.) 00640 int32u powerUpEvents = PWRUP_EVENT; 00641 powerUpEvents &= WAKE_SEL; 00642 halInternalWakeEvent |= ((GPIO_IN_SAVED^GPIO_IN_NEW)&gpioWakeSel); 00643 //PWRUP_SC1 is PB2 which is bit 10 00644 halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_SC1))<<((1*8)+2); 00645 //PWRUP_SC2 is PA2 which is bit 2 00646 halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_SC2))<<((0*8)+2); 00647 //PWRUP_IRQD is chosen by GPIO_IRQDSEL 00648 halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_IRQD))<<(GPIO_IRQDSEL); 00649 halInternalWakeEvent |= ((powerUpEvents & 00650 (PWRUP_CSYSPWRUPREQ_MASK | 00651 PWRUP_CDBGPWRUPREQ_MASK | 00652 PWRUP_WAKECORE_MASK | 00653 PWRUP_SLEEPTMRWRAP_MASK | 00654 PWRUP_SLEEPTMRCOMPB_MASK | 00655 PWRUP_SLEEPTMRCOMPA_MASK )) 00656 <<INTERNAL_WAKE_EVENT_BIT_SHIFT); 00657 //at this point wake events are fully captured and interrupts have 00658 //taken over handling all new events 00659 00660 00661 00662 00663 00664 00665 //Bring limited interrupts back online. INTERRUPTS_OFF will use 00666 //BASEPRI to disable all interrupts except fault handlers and PendSV. 00667 //PRIMASK is still set though (global interrupt disable) so we need 00668 //to clear that next. 00669 INTERRUPTS_OFF(); 00670 00671 00672 00673 00674 00675 //Now that BASEPRI has taken control of interrupt enable/disable, 00676 //we can clear PRIMASK to reenable global interrupt operation. 00677 _clearPriMask(); 00678 00679 00680 00681 00682 00683 //wake events are saved and interrupts are back on track, 00684 //disable gpio freeze 00685 EVENT_CTRL = EVENT_CTRL_RESET; 00686 00687 //restart watchdog if it was running when we entered sleep 00688 //do this before dispatching interrupts while we still have tight 00689 //control of code execution 00690 if(restoreWatchdog) { 00691 halInternalEnableWatchDog(); 00692 } 00693 00694 00695 00696 00697 00698 //Pend any interrupts associated with deep sleep wake sources. The 00699 //restoration of INT_CFGSET above and the changing of BASEPRI below 00700 //is responsible for proper dispatching of interrupts at the end of 00701 //halSleepWithOptions. 00702 // 00703 // 00704 //The WAKE_CORE wake source triggers a Debug Interrupt. If INT_DEBUG 00705 //interrupt is enabled and WAKE_CORE is a wake event, then pend the 00706 //Debug interrupt (using the wake_core bit). 00707 if( (INT_CFGSET&INT_DEBUG) && 00708 (halInternalWakeEvent&BIT(WAKE_CORE_INTERNAL_WAKE_EVENT_BIT)) ) { 00709 WAKE_CORE = WAKE_CORE_FIELD; 00710 00711 00712 00713 } 00714 // 00715 // 00716 //The SleepTMR CMPA is linked to a real ISR. If the SleepTMR CMPA 00717 //interrupt is enabled and CMPA is a wake event, then pend the CMPA 00718 //interrupt (force the second level interrupt). 00719 if( (INT_SLEEPTMRCFG&INT_SLEEPTMRCMPA) && 00720 (halInternalWakeEvent&BIT(CMPA_INTERNAL_WAKE_EVENT_BIT)) ) { 00721 INT_SLEEPTMRFORCE = INT_SLEEPTMRCMPA; 00722 00723 00724 00725 } 00726 // 00727 //The SleepTMR CMPB is linked to a real ISR. If the SleepTMR CMPB 00728 //interrupt is enabled and CMPB is a wake event, then pend the CMPB 00729 //interrupt (force the second level interrupt). 00730 if( (INT_SLEEPTMRCFG&INT_SLEEPTMRCMPB) && 00731 (halInternalWakeEvent&BIT(CMPB_INTERNAL_WAKE_EVENT_BIT)) ) { 00732 INT_SLEEPTMRFORCE = INT_SLEEPTMRCMPB; 00733 00734 00735 00736 } 00737 // 00738 //The SleepTMR WRAP is linked to a real ISR. If the SleepTMR WRAP 00739 //interrupt is enabled and WRAP is a wake event, then pend the WRAP 00740 //interrupt (force the second level interrupt). 00741 if( (INT_SLEEPTMRCFG&INT_SLEEPTMRWRAP) && 00742 (halInternalWakeEvent&BIT(WRAP_INTERNAL_WAKE_EVENT_BIT)) ) { 00743 INT_SLEEPTMRFORCE = INT_SLEEPTMRWRAP; 00744 00745 00746 00747 } 00748 // 00749 // 00750 //The four IRQs are linked to a real ISR. If any of the four IRQs 00751 //triggered, then pend their ISR 00752 // 00753 //If the IRQA interrupt mode is enabled and IRQA (PB0) is wake 00754 //event, then pend the interrupt. 00755 if( ((GPIO_INTCFGA&GPIO_INTMOD)!=0) && 00756 (halInternalWakeEvent&BIT(PORTB_PIN(0))) ) { 00757 INT_PENDSET = INT_IRQA; 00758 00759 00760 00761 } 00762 //If the IRQB interrupt mode is enabled and IRQB (PB6) is wake 00763 //event, then pend the interrupt. 00764 if( ((GPIO_INTCFGB&GPIO_INTMOD)!=0) && 00765 (halInternalWakeEvent&BIT(PORTB_PIN(6))) ) { 00766 INT_PENDSET = INT_IRQB; 00767 00768 00769 00770 } 00771 //If the IRQC interrupt mode is enabled and IRQC (GPIO_IRQCSEL) is wake 00772 //event, then pend the interrupt. 00773 if( ((GPIO_INTCFGC&GPIO_INTMOD)!=0) && 00774 (halInternalWakeEvent&BIT(GPIO_IRQCSEL)) ) { 00775 INT_PENDSET = INT_IRQC; 00776 00777 00778 00779 } 00780 //If the IRQD interrupt mode is enabled and IRQD (GPIO_IRQDSEL) is wake 00781 //event, then pend the interrupt. 00782 if( ((GPIO_INTCFGD&GPIO_INTMOD)!=0) && 00783 (halInternalWakeEvent&BIT(GPIO_IRQDSEL)) ) { 00784 INT_PENDSET = INT_IRQD; 00785 00786 00787 00788 } 00789 } 00790 00791 00792 00793 00794 00795 00796 //Mark the wake events valid just before exiting 00797 halInternalWakeEvent |= BIT32(WAKEINFOVALID_INTERNAL_WAKE_EVENT_BIT); 00798 00799 //We are now reconfigured, appropriate ISRs are pended, and ready to go, 00800 //so enable interrupts! 00801 INTERRUPTS_ON(); 00802 00803 00804 00805 00806 00807 break; //and deep sleeping is done! 00808 00809 case SLEEPMODE_IDLE: 00810 //Only the CPU is idled. The rest of the chip continues runing 00811 //normally. The chip will wake from any interrupt. 00812 { 00813 boolean restoreWatchdog = halInternalWatchDogEnabled(); 00814 //disable watchdog while sleeping (since we can't reset it asleep) 00815 halInternalDisableWatchDog(MICRO_DISABLE_WATCH_DOG_KEY); 00816 //Normal ATOMIC/INTERRUPTS_OFF/INTERRUPTS_ON uses the BASEPRI mask 00817 //to juggle priority levels so that the fault handlers can always 00818 //be serviced. But, the WFI instruction is only capable of 00819 //working with the PRIMASK bit. Therefore, we have to switch from 00820 //using BASEPRI to PRIMASK to keep interrupts disabled so that the 00821 //WFI can return on an interrupt 00822 //Globally disable interrupts with PRIMASK 00823 _setPriMask(); 00824 //Bring the BASEPRI up to 0 to allow interrupts (but still disabled 00825 //with PRIMASK) 00826 INTERRUPTS_ON(); 00827 //an internal function call is made here instead of injecting the 00828 //"WFI" assembly instruction because injecting assembly code will 00829 //cause the compiler's optimizer to reduce efficiency. 00830 halInternalIdleSleep(); 00831 //The WFI instruction does not actually clear the PRIMASK bit, it 00832 //only allows the PRIMASK bit to be bypassed. Therefore, we must 00833 //manually clear PRIMASK to reenable all interrupts. 00834 _clearPriMask(); 00835 //restart watchdog if it was running when we entered sleep 00836 if(restoreWatchdog) 00837 halInternalEnableWatchDog(); 00838 } 00839 break; 00840 00841 default: 00842 //Oops! Invalid sleepMode parameter. 00843 assert(0); 00844 } 00845 } 00846 00847 00848 void halSleepWithOptions(SleepModes sleepMode, int32u gpioWakeBitMask) 00849 { 00850 //configure all GPIO wake sources 00851 GPIO_PAWAKE = (gpioWakeBitMask>>0)&0xFF; 00852 GPIO_PBWAKE = (gpioWakeBitMask>>8)&0xFF; 00853 GPIO_PCWAKE = (gpioWakeBitMask>>16)&0xFF; 00854 00855 //use the defines found in the board file to choose our wakeup source(s) 00856 WAKE_SEL = 0; //start with no wake sources 00857 00858 //if any of the GPIO wakeup monitor bits are set, enable the top level 00859 //GPIO wakeup monitor 00860 if((GPIO_PAWAKE)||(GPIO_PBWAKE)||(GPIO_PCWAKE)) { 00861 WAKE_SEL |= GPIO_WAKE; 00862 } 00863 //always wakeup when the debugger is connected 00864 WAKE_SEL |= WAKE_CDBGPWRUPREQ; 00865 //always wakeup when the debugger attempts to access the chip 00866 WAKE_SEL |= WAKE_CSYSPWRUPREQ; 00867 //always wakeup when the debug channel attempts to access the chip 00868 WAKE_SEL |= WAKE_WAKE_CORE; 00869 //the timer wakeup sources are enabled below in POWERSAVE, if needed 00870 00871 //wake sources are configured so do the actual sleeping 00872 halInternalSleep(sleepMode); 00873 }