Contiki 2.5
sleep.c
Go to the documentation of this file.
1 /** @file hal/micro/cortexm3/sleep.c
2  *
3  * @brief STM32W108 micro specific sleep functions.
4  *
5  * <!--(C) COPYRIGHT 2010 STMicroelectronics. All rights reserved. -->
6  */
7 
8 #include PLATFORM_HEADER
9 #include "hal/micro/micro-common.h"
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 //We don't have a real register to hold this composite information.
97 //Pretend we do so halGetWakeInfo can operate like halGetResetInfo.
98 //This "register" is only ever set by halInternalSleep.
99 // [31] = WakeInfoValid
100 // [30] = SleepSkipped
101 // [29] = CSYSPWRUPREQ
102 // [28] = CDBGPWRUPREQ
103 // [27] = WAKE_CORE
104 // [26] = TIMER_WAKE_WRAP
105 // [25] = TIMER_WAKE_COMPB
106 // [24] = TIMER_WAKE_COMPA
107 // [23:0] = corresponding GPIO activity
108 #define WAKEINFOVALID_INTERNAL_WAKE_EVENT_BIT 31
109 #define SLEEPSKIPPED_INTERNAL_WAKE_EVENT_BIT 30
110 #define CSYSPWRUPREQ_INTERNAL_WAKE_EVENT_BIT 29
111 #define CDBGPWRUPREQ_INTERNAL_WAKE_EVENT_BIT 28
112 #define WAKE_CORE_INTERNAL_WAKE_EVENT_BIT 27
113 #define WRAP_INTERNAL_WAKE_EVENT_BIT 26
114 #define CMPB_INTERNAL_WAKE_EVENT_BIT 25
115 #define CMPA_INTERNAL_WAKE_EVENT_BIT 24
116 //This define shifts events from the PWRUP_EVENT register into the proper
117 //place in the halInternalWakeEvent variable
118 #define INTERNAL_WAKE_EVENT_BIT_SHIFT 20
119 
120 static int32u halInternalWakeEvent=0;
121 
122 int32u halGetWakeInfo(void)
123 {
124  return halInternalWakeEvent;
125 }
126 
127 void halInternalSleep(SleepModes sleepMode)
128 {
129  //Timer restoring always takes place during the wakeup sequence. We save
130  //the state here in case SLEEPMODE_NOTIMER is invoked, which would disable
131  //the clocks.
132  int32u SLEEPTMR_CLKEN_SAVED = SLEEPTMR_CLKEN;
133 
134  //This code assumes all wake source registers are properly configured.
135  //As such, it should be called from halSleepWithOptions() or from
136  // halSleepForQsWithOptions() which configues the wake sources.
137 
138  //The parameter gpioWakeSel is a bitfield composite of the GPIO wake
139  //sources derived from the 3 ports, indicating which of the 24 GPIO
140  //are configured as a wake source.
141  int32u gpioWakeSel = (GPIO_PAWAKE<<0);
142  gpioWakeSel |= (GPIO_PBWAKE<<8);
143  gpioWakeSel |= (GPIO_PCWAKE<<16);
144 
145  //PB2 is also WAKE_SC1. Set this wake source if PB2's GPIO wake is set.
146  if(GPIO_PBWAKE & PB2) {
147  WAKE_SEL |= WAKE_SC1;
148  }
149 
150  //PA2 is also WAKE_SC2. Set this wake source if PA2's GPIO wake is set.
151  if(GPIO_PAWAKE & PA2) {
152  WAKE_SEL |= WAKE_SC2;
153  }
154 
155  //The WAKE_IRQD source can come from any pin based on IRQD's sel register.
156  if(gpioWakeSel & BIT(GPIO_IRQDSEL)) {
157  WAKE_SEL |= WAKE_IRQD;
158  }
159 
160  halInternalWakeEvent = 0; //clear old wake events
161 
162  switch(sleepMode)
163  {
164  case SLEEPMODE_NOTIMER:
165  //The sleep timer clock sources (both RC and XTAL) are turned off.
166  //Wakeup is possible from only GPIO. System time is lost.
167  //NOTE: Timer restoring always takes place during the wakeup sequence.
168  SLEEPTMR_CLKEN = 0;
169  goto deepSleepCore;
170 
171  case SLEEPMODE_WAKETIMER:
172  //The sleep timer clock sources remain running. The RC is always
173  //running and the 32kHz XTAL depends on the board header. Wakeup
174  //is possible from both GPIO and the sleep timer. System time
175  //is maintained. The sleep timer is assumed to be configured
176  //properly for wake events.
177  //NOTE: This mode assumes the caller has configured the *entire*
178  // sleep timer properly.
179 
180  if(INT_SLEEPTMRCFG&INT_SLEEPTMRWRAP) {
181  WAKE_SEL |= WAKE_SLEEPTMRWRAP;
182  }
183  if(INT_SLEEPTMRCFG&INT_SLEEPTMRCMPB) {
184  WAKE_SEL |= WAKE_SLEEPTMRCMPB;
185  }
186  if(INT_SLEEPTMRCFG&INT_SLEEPTMRCMPA) {
187  WAKE_SEL |= WAKE_SLEEPTMRCMPA;
188  }
189  //fall into SLEEPMODE_MAINTAINTIMER's sleep code:
190 
191  case SLEEPMODE_MAINTAINTIMER:
192  //The sleep timer clock sources remain running. The RC is always
193  //running and the 32kHz XTAL depends on the board header. Wakeup
194  //is possible from only GPIO. System time is maintained.
195  //NOTE: System time is maintained without any sleep timer interrupts
196  // because the hardware sleep timer counter is large enough
197  // to hold the entire count value and not need a RAM counter.
198 
199  ////////////////////////////////////////////////////////////////////////////
200  // Core deep sleep code
201  ////////////////////////////////////////////////////////////////////////////
202 deepSleepCore:
203  // Interrupts *must* be/stay disabled for DEEP SLEEP operation
204  // INTERRUPTS_OFF will use BASEPRI to disable all interrupts except
205  // fault handlers and PendSV.
206  INTERRUPTS_OFF();
207  // This is the point of no return. From here on out, only the interrupt
208  // sources available in WAKE_SEL will be captured and propagated across
209  // deep sleep.
210  //stick all our saved info onto stack since it's only temporary
211  {
212  boolean restoreWatchdog = halInternalWatchDogEnabled();
213  boolean skipSleep = FALSE;
214 
215  // Only three register blocks keep power across deep sleep:
216  // CM_HV, GPIO, SLOW_TIMERS
217  //
218  // All other register blocks lose their state across deep sleep:
219  // BASEBAND, MAC, SECURITY, SERIAL, TMR1, TMR2, EVENT, CM_LV, RAM_CTRL,
220  // AUX_ADC, CAL_ADC, FLASH_CONTROL, ITM, DWT, FPB, NVIC, TPIU
221  //
222  // The sleep code will only save and restore registers where it is
223  // meaningful and necessary to do so. In most cases, there must still
224  // be a powerup function to restore proper state.
225  //
226  // NOTE: halPowerUp() and halPowerDown() will always be called before
227  // and after this function. halPowerDown and halPowerUp should leave
228  // the modules in a safe state and then restart the modules.
229  // (For example, shutting down and restarting Timer1)
230  //
231  //----BASEBAND
232  // reinitialized by stStackPowerUp()
233  //----MAC
234  // reinitialized by stStackPowerUp()
235  //----SECURITY
236  // reinitialized by stStackPowerUp()
237  //----SERIAL
238  // reinitialized by halPowerUp() or similar
239  //----TMR1
240  // reinitialized by halPowerUp() or similar
241  //----TMR2
242  // reinitialized by halPowerUp() or similar
243  //----EVENT
244  //SRC or FLAG interrupts are not saved or restored
245  //MISS interrupts are not saved or restored
246  //MAC_RX_INT_MASK - reinitialized by stStackPowerUp()
247  //MAC_TX_INT_MASK - reinitialized by stStackPowerUp()
248  //MAC_TIMER_INT_MASK - reinitialized by stStackPowerUp()
249  //BB_INT_MASK - reinitialized by stStackPowerUp()
250  //SEC_INT_MASK - reinitialized by stStackPowerUp()
251  int32u INT_SLEEPTMRCFG_SAVED = INT_SLEEPTMRCFG_REG;
252  int32u INT_MGMTCFG_SAVED = INT_MGMTCFG_REG;
253  //INT_TIM1CFG - reinitialized by halPowerUp() or similar
254  //INT_TIM2CFG - reinitialized by halPowerUp() or similar
255  //INT_SC1CFG - reinitialized by halPowerUp() or similar
256  //INT_SC2CFG - reinitialized by halPowerUp() or similar
257  //INT_ADCCFG - reinitialized by halPowerUp() or similar
258  int32u GPIO_INTCFGA_SAVED = GPIO_INTCFGA_REG;
259  int32u GPIO_INTCFGB_SAVED = GPIO_INTCFGB_REG;
260  int32u GPIO_INTCFGC_SAVED = GPIO_INTCFGC_REG;
261  int32u GPIO_INTCFGD_SAVED = GPIO_INTCFGD_REG;
262  //SC1_INTMODE - reinitialized by halPowerUp() or similar
263  //SC2_INTMODE - reinitialized by halPowerUp() or similar
264  //----CM_LV
265  int32u OSC24M_BIASTRIM_SAVED = OSC24M_BIASTRIM_REG;
266  int32u OSCHF_TUNE_SAVED = OSCHF_TUNE_REG;
267  int32u DITHER_DIS_SAVED = DITHER_DIS_REG;
268  //OSC24M_CTRL - reinitialized by halPowerUp() or similar
269  //CPU_CLKSEL - reinitialized by halPowerUp() or similar
270  //TMR1_CLK_SEL - reinitialized by halPowerUp() or similar
271  //TMR2_CLK_SEL - reinitialized by halPowerUp() or similar
272  int32u PCTRACE_SEL_SAVED = PCTRACE_SEL_REG;
273  //----RAM_CTRL
274  int32u MEM_PROT_0_SAVED = MEM_PROT_0_REG;
275  int32u MEM_PROT_1_SAVED = MEM_PROT_1_REG;
276  int32u MEM_PROT_2_SAVED = MEM_PROT_2_REG;
277  int32u MEM_PROT_3_SAVED = MEM_PROT_3_REG;
278  int32u MEM_PROT_4_SAVED = MEM_PROT_4_REG;
279  int32u MEM_PROT_5_SAVED = MEM_PROT_5_REG;
280  int32u MEM_PROT_6_SAVED = MEM_PROT_6_REG;
281  int32u MEM_PROT_7_SAVED = MEM_PROT_7_REG;
282  int32u MEM_PROT_EN_SAVED = MEM_PROT_EN_REG;
283  //----AUX_ADC
284  // reinitialized by halPowerUp() or similar
285  //----CAL_ADC
286  // reinitialized by stStackPowerUp()
287  //----FLASH_CONTROL
288  // configured on the fly by the flash library
289  //----ITM
290  // reinitialized by halPowerUp() or similar
291  //----DWT
292  // not used by software on chip
293  //----FPB
294  // not used by software on chip
295  //----NVIC
296  //ST_CSR - fixed, restored by cstartup when exiting deep sleep
297  //ST_RVR - fixed, restored by cstartup when exiting deep sleep
298  int32u INT_CFGSET_SAVED = INT_CFGSET_REG; //mask against wake sources
299  //INT_PENDSET - used below when overlapping interrupts and wake sources
300  //NVIC_IPR_3to0 - fixed, restored by cstartup when exiting deep sleep
301  //NVIC_IPR_7to4 - fixed, restored by cstartup when exiting deep sleep
302  //NVIC_IPR_11to8 - fixed, restored by cstartup when exiting deep sleep
303  //NVIC_IPR_15to12 - fixed, restored by cstartup when exiting deep sleep
304  //NVIC_IPR_19to16 - fixed, restored by cstartup when exiting deep sleep
305  int32u SCS_VTOR_SAVED = SCS_VTOR_REG;
306  //SCS_CCR - fixed, restored by cstartup when exiting deep sleep
307  //SCS_SHPR_7to4 - fixed, restored by cstartup when exiting deep sleep
308  //SCS_SHPR_11to8 - fixed, restored by cstartup when exiting deep sleep
309  //SCS_SHPR_15to12 - fixed, restored by cstartup when exiting deep sleep
310  //SCS_SHCSR - fixed, restored by cstartup when exiting deep sleep
311  //----TPIU
312  // reinitialized by halPowerUp() or similar
313 
314  //stmDebugPowerDown() should have shutdown the DWT/ITM/TPIU already.
315 
316  //freeze input to the GPIO from LV (alternate output functions freeze)
317  EVENT_CTRL = LV_FREEZE;
318  //record GPIO state for wake monitoring purposes
319  //By having a snapshot of GPIO state, we can figure out after waking
320  //up exactly which GPIO could have woken us up.
321  //Reading the three IN registers is done separately to avoid warnings
322  //about undefined order of volatile access.
323  int32u GPIO_IN_SAVED = GPIO_PAIN;
324  GPIO_IN_SAVED |= (GPIO_PBIN<<8);
325  GPIO_IN_SAVED |= (GPIO_PCIN<<16);
326  //reset the power up events by writing 1 to all bits.
327  PWRUP_EVENT = 0xFFFFFFFF;
328 
329 
330 
331  //By clearing the events, the wake up event capturing is activated.
332  //At this point we can safely check our interrupt flags since event
333  //capturing is now overlapped. Up to now, interrupts indicate
334  //activity, after this point, powerup events indicate activity.
335  //If any of the interrupt flags are set, that means we saw a wake event
336  //sometime while entering sleep, so we need to skip over sleeping
337  //
338  //--possible interrupt sources for waking:
339  // IRQA, IRQB, IRQC, IRQD
340  // SleepTMR CMPA, CMPB, Wrap
341  // WAKE_CORE (DebugIsr)
342  //
343  //check for IRQA interrupt and if IRQA (PB0) is wake source
344  if((INT_PENDSET&INT_IRQA) &&
345  (GPIO_PBWAKE&PB0) &&
346  (WAKE_SEL&GPIO_WAKE)) {
347  skipSleep = TRUE;
348  //log IRQA as a wake event
349  halInternalWakeEvent |= BIT(PORTB_PIN(0));
350 
351 
352 
353  }
354  //check for IRQB interrupt and if IRQB (PB6) is wake source
355  if((INT_PENDSET&INT_IRQB) &&
356  (GPIO_PBWAKE&PB6) &&
357  (WAKE_SEL&GPIO_WAKE)) {
358  skipSleep = TRUE;
359  //log IRQB as a wake event
360  halInternalWakeEvent |= BIT(PORTB_PIN(6));
361 
362 
363 
364  }
365  //check for IRQC interrupt and if IRQC (GPIO_IRQCSEL) is wake source
366  if((INT_PENDSET&INT_IRQC) &&
367  (gpioWakeSel&BIT(GPIO_IRQCSEL)) &&
368  (WAKE_SEL&GPIO_WAKE)) {
369  skipSleep = TRUE;
370  //log IRQC as a wake event
371  halInternalWakeEvent |= BIT(GPIO_IRQCSEL);
372 
373 
374 
375  }
376  //check for IRQD interrupt and if IRQD (GPIO_IRQDSEL) is wake source
377  if((INT_PENDSET&INT_IRQD) &&
378  (gpioWakeSel&BIT(GPIO_IRQDSEL)) &&
379  ((WAKE_SEL&GPIO_WAKE) ||
380  (WAKE_SEL&WAKE_IRQD))) {
381  skipSleep = TRUE;
382  //log IRQD as a wake event
383  halInternalWakeEvent |= BIT(GPIO_IRQDSEL);
384 
385 
386 
387  }
388  //check for SleepTMR CMPA interrupt and if SleepTMR CMPA is wake source
389  if((INT_SLEEPTMR&INT_SLEEPTMRCMPA) && (WAKE_SEL&WAKE_SLEEPTMRCMPA)) {
390  skipSleep = TRUE;
391  //log SleepTMR CMPA as a wake event
392  halInternalWakeEvent |= BIT32(CMPA_INTERNAL_WAKE_EVENT_BIT);
393 
394 
395 
396  }
397  //check for SleepTMR CMPB interrupt and if SleepTMR CMPB is wake source
398  if((INT_SLEEPTMR&INT_SLEEPTMRCMPB) && (WAKE_SEL&WAKE_SLEEPTMRCMPB)) {
399  skipSleep = TRUE;
400  //log SleepTMR CMPB as a wake event
401  halInternalWakeEvent |= BIT32(CMPB_INTERNAL_WAKE_EVENT_BIT);
402 
403 
404 
405  }
406  //check for SleepTMR WRAP interrupt and if SleepTMR WRAP is wake source
407  if((INT_SLEEPTMR&INT_SLEEPTMRWRAP) && (WAKE_SEL&WAKE_SLEEPTMRWRAP)) {
408  skipSleep = TRUE;
409  //log SleepTMR WRAP as a wake event
410  halInternalWakeEvent |= BIT32(WRAP_INTERNAL_WAKE_EVENT_BIT);
411 
412 
413 
414  }
415  //check for Debug interrupt and if WAKE_CORE is wake source
416  if((INT_PENDSET&INT_DEBUG) && (WAKE_SEL&WAKE_WAKE_CORE)) {
417  skipSleep = TRUE;
418  //log WAKE_CORE as a wake event
419  halInternalWakeEvent |= BIT32(WAKE_CORE_INTERNAL_WAKE_EVENT_BIT);
420 
421 
422 
423  }
424 
425  //only propagate across deep sleep the interrupts that are both
426  //enabled and possible wake sources
427  {
428  int32u wakeSourceInterruptMask = 0;
429 
430  if(GPIO_PBWAKE&PB0) {
431  wakeSourceInterruptMask |= INT_IRQA;
432 
433 
434 
435  }
436  if(GPIO_PBWAKE&PB6) {
437  wakeSourceInterruptMask |= INT_IRQB;
438 
439 
440 
441  }
442  if(gpioWakeSel&BIT(GPIO_IRQCSEL)) {
443  wakeSourceInterruptMask |= INT_IRQC;
444 
445 
446 
447  }
448  if(gpioWakeSel&BIT(GPIO_IRQDSEL)) {
449  wakeSourceInterruptMask |= INT_IRQD;
450 
451 
452 
453  }
454  if( (WAKE_SEL&WAKE_SLEEPTMRCMPA) ||
455  (WAKE_SEL&WAKE_SLEEPTMRCMPB) ||
456  (WAKE_SEL&WAKE_SLEEPTMRWRAP) ) {
457  wakeSourceInterruptMask |= INT_SLEEPTMR;
458 
459 
460 
461  }
462  if(WAKE_SEL&WAKE_WAKE_CORE) {
463  wakeSourceInterruptMask |= INT_DEBUG;
464 
465 
466 
467  }
468 
469  INT_CFGSET_SAVED &= wakeSourceInterruptMask;
470  }
471 
472 
473 
474 
475 
476 
477 
478 
479 
480 
481 
482 
483 
484 
485 
486 
487 
488  //disable watchdog while sleeping (since we can't reset it asleep)
490 
491  //The chip is not allowed to enter a deep sleep mode (which could
492  //cause a core reset cycle) while CSYSPWRUPREQ is set. CSYSPWRUPREQ
493  //indicates that the debugger is trying to access sections of the
494  //chip that would get reset during deep sleep. Therefore, a reset
495  //cycle could very easily cause the debugger to error and we don't
496  //want that. While the power management state machine will stall
497  //if CSYSPWRUPREQ is set (to avoid the situation just described),
498  //in this stalled state the chip will not be responsive to wake
499  //events. To be sensitive to wake events, we must handle them in
500  //software instead. To accomplish this, we request that the
501  //CSYSPWRUPACK be inhibited (which will indicate the debugger is not
502  //connected). But, we cannot induce deep sleep until CSYSPWRUPREQ/ACK
503  //go low and these are under the debuggers control, so we must stall
504  //and wait here. If there is a wake event during this time, break
505  //out and wake like normal. If the ACK eventually clears,
506  //we can proceed into deep sleep. The CSYSPWRUPACK_INHIBIT
507  //functionality will hold off the debugger (by holding off the ACK)
508  //until we are safely past and out of deep sleep. The power management
509  //state machine then becomes responsible for clearing
510  //CSYSPWRUPACK_INHIBIT and responding to a CSYSPWRUPREQ with a
511  //CSYSPWRUPACK at the right/safe time.
512  CSYSPWRUPACK_INHIBIT = CSYSPWRUPACK_INHIBIT_CSYSPWRUPACK_INHIBIT;
513  {
514  //Use a local copy of WAKE_SEL to avoid warnings from the compiler
515  //about order of volatile accesses
516  int32u wakeSel = WAKE_SEL;
517  //stall until a wake event or CSYSPWRUPREQ/ACK clears
518  while( (CSYSPWRUPACK_STATUS) && (!(PWRUP_EVENT&wakeSel)) ) {}
519  //if there was a wake event, allow CSYSPWRUPACK and skip sleep
520  if(PWRUP_EVENT&wakeSel) {
521  CSYSPWRUPACK_INHIBIT = CSYSPWRUPACK_INHIBIT_RESET;
522  skipSleep = TRUE;
523  }
524  }
525 
526 
527 
528 
529 
530  if(!skipSleep) {
531 
532 
533 
534  //FogBugz 7283 states that we must switch to the OSCHF when entering
535  //deep sleep since using the 24MHz XTAL could result in RAM
536  //corruption. This switch must occur at least 2*24MHz cycles before
537  //sleeping.
538  //FogBugz 8858 states that we cannot go into deep-sleep when the
539  //chip is clocked with the 24MHz XTAL with a duty cycle as low as
540  //70/30 since this causes power_down generation timing to fail.
541  OSC24M_CTRL &= ~OSC24M_CTRL_OSC24M_SEL;
542  //If DS12 needs to be forced regardless of state, clear
543  //REGEN_DSLEEP here. This is hugely dangerous and
544  //should only be done in very controlled chip tests.
545  SCS_SCR |= SCS_SCR_SLEEPDEEP; //enable deep sleep
546  extern volatile boolean halPendSvSaveContext;
547  halPendSvSaveContext = 1; //1 means save context
548  //The INTERRUPTS_OFF used at the beginning of this function set
549  //BASEPRI such that the only interrupts that will fire are faults
550  //and PendSV. Trigger PendSV now to induce a context save.
551  SCS_ICSR |= SCS_ICSR_PENDSVSET; //pend the context save and Dsleep
552  //Since the interrupt will not fire immediately it is possible to
553  //execute a few lines of code. To stay halted in this spot until the
554  //WFI instruction, spin on the context flag (which will get cleared
555  //during the startup sequence when restoring context).
556  while(halPendSvSaveContext) {}
557  //I AM ASLEEP. WHEN EXECUTION RESUMES, CSTARTUP WILL RESTORE TO HERE
558  } else {
559  //Record the fact that we skipped sleep
560  halInternalWakeEvent |= BIT32(SLEEPSKIPPED_INTERNAL_WAKE_EVENT_BIT);
561  //If this was a true deep sleep, we would have executed cstartup and
562  //PRIMASK would be set right now. If we skipped sleep, PRIMASK is not
563  //set so we explicitely set it to guarantee the powerup sequence
564  //works cleanly and consistently with respect to interrupt
565  //dispatching and enabling.
566  _setPriMask();
567  }
568 
569 
570 
571 
572 
573 
574 
575 
576  //Clear the interrupt flags for all wake sources. This
577  //is necessary because if we don't execute an actual deep sleep cycle
578  //the interrupt flags will never be cleared. By clearing the flags,
579  //we always mimick a real deep sleep as closely as possible and
580  //guard against any accidental interrupt triggering coming out
581  //of deep sleep. (The interrupt dispatch code coming out of sleep
582  //is responsible for translating wake events into interrupt events,
583  //and if we don't clear interrupt flags here it's possible for an
584  //interrupt to trigger even if it wasn't the true wake event.)
585  INT_SLEEPTMRFLAG = (INT_SLEEPTMRCMPA |
586  INT_SLEEPTMRCMPB |
587  INT_SLEEPTMRWRAP);
588  INT_GPIOFLAG = (INT_IRQAFLAG |
589  INT_IRQBFLAG |
590  INT_IRQCFLAG |
591  INT_IRQDFLAG);
592 
593  //immediately restore the registers we saved before sleeping
594  //so IRQ and SleepTMR capture can be reenabled as quickly as possible
595  //this is safe because our global interrupts are still disabled
596  //other registers will be restored later
597 
598 
599 
600 
601 
602 
603 
604  SLEEPTMR_CLKEN_REG = SLEEPTMR_CLKEN_SAVED;
605  INT_SLEEPTMRCFG_REG = INT_SLEEPTMRCFG_SAVED;
606  INT_MGMTCFG_REG = INT_MGMTCFG_SAVED;
607  GPIO_INTCFGA_REG = GPIO_INTCFGA_SAVED;
608  GPIO_INTCFGB_REG = GPIO_INTCFGB_SAVED;
609  GPIO_INTCFGC_REG = GPIO_INTCFGC_SAVED;
610  GPIO_INTCFGD_REG = GPIO_INTCFGD_SAVED;
611  OSC24M_BIASTRIM_REG = OSC24M_BIASTRIM_SAVED;
612  OSCHF_TUNE_REG = OSCHF_TUNE_SAVED;
613  DITHER_DIS_REG = DITHER_DIS_SAVED;
614  PCTRACE_SEL_REG = PCTRACE_SEL_SAVED;
615  MEM_PROT_0_REG = MEM_PROT_0_SAVED;
616  MEM_PROT_1_REG = MEM_PROT_1_SAVED;
617  MEM_PROT_2_REG = MEM_PROT_2_SAVED;
618  MEM_PROT_3_REG = MEM_PROT_3_SAVED;
619  MEM_PROT_4_REG = MEM_PROT_4_SAVED;
620  MEM_PROT_5_REG = MEM_PROT_5_SAVED;
621  MEM_PROT_6_REG = MEM_PROT_6_SAVED;
622  MEM_PROT_7_REG = MEM_PROT_7_SAVED;
623  MEM_PROT_EN_REG = MEM_PROT_EN_SAVED;
624  INT_CFGSET_REG = INT_CFGSET_SAVED;
625  SCS_VTOR_REG = SCS_VTOR_SAVED;
626 
627  //WAKE_CORE/INT_DEBUG and INT_IRQx is cleared by INT_PENDCLR below
628  INT_PENDCLR = 0xFFFFFFFF;
629 
630  //Now that we're awake, normal interrupts are operational again
631  //Take a snapshot of the new GPIO state and the EVENT register to
632  //record our wake event
633  int32u GPIO_IN_NEW = GPIO_PAIN;
634  GPIO_IN_NEW |= (GPIO_PBIN<<8);
635  GPIO_IN_NEW |= (GPIO_PCIN<<16);
636  //Only operate on power up events that are also wake events. Power
637  //up events will always trigger like an interrupt flag, so we have
638  //to check them against events that are enabled for waking. (This is
639  //a two step process because we're accessing two volatile values.)
640  int32u powerUpEvents = PWRUP_EVENT;
641  powerUpEvents &= WAKE_SEL;
642  halInternalWakeEvent |= ((GPIO_IN_SAVED^GPIO_IN_NEW)&gpioWakeSel);
643  //PWRUP_SC1 is PB2 which is bit 10
644  halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_SC1))<<((1*8)+2);
645  //PWRUP_SC2 is PA2 which is bit 2
646  halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_SC2))<<((0*8)+2);
647  //PWRUP_IRQD is chosen by GPIO_IRQDSEL
648  halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_IRQD))<<(GPIO_IRQDSEL);
649  halInternalWakeEvent |= ((powerUpEvents &
650  (PWRUP_CSYSPWRUPREQ_MASK |
651  PWRUP_CDBGPWRUPREQ_MASK |
652  PWRUP_WAKECORE_MASK |
653  PWRUP_SLEEPTMRWRAP_MASK |
654  PWRUP_SLEEPTMRCOMPB_MASK |
655  PWRUP_SLEEPTMRCOMPA_MASK ))
656  <<INTERNAL_WAKE_EVENT_BIT_SHIFT);
657  //at this point wake events are fully captured and interrupts have
658  //taken over handling all new events
659 
660 
661 
662 
663 
664 
665  //Bring limited interrupts back online. INTERRUPTS_OFF will use
666  //BASEPRI to disable all interrupts except fault handlers and PendSV.
667  //PRIMASK is still set though (global interrupt disable) so we need
668  //to clear that next.
669  INTERRUPTS_OFF();
670 
671 
672 
673 
674 
675  //Now that BASEPRI has taken control of interrupt enable/disable,
676  //we can clear PRIMASK to reenable global interrupt operation.
677  _clearPriMask();
678 
679 
680 
681 
682 
683  //wake events are saved and interrupts are back on track,
684  //disable gpio freeze
685  EVENT_CTRL = EVENT_CTRL_RESET;
686 
687  //restart watchdog if it was running when we entered sleep
688  //do this before dispatching interrupts while we still have tight
689  //control of code execution
690  if(restoreWatchdog) {
692  }
693 
694 
695 
696 
697 
698  //Pend any interrupts associated with deep sleep wake sources. The
699  //restoration of INT_CFGSET above and the changing of BASEPRI below
700  //is responsible for proper dispatching of interrupts at the end of
701  //halSleepWithOptions.
702  //
703  //
704  //The WAKE_CORE wake source triggers a Debug Interrupt. If INT_DEBUG
705  //interrupt is enabled and WAKE_CORE is a wake event, then pend the
706  //Debug interrupt (using the wake_core bit).
707  if( (INT_CFGSET&INT_DEBUG) &&
708  (halInternalWakeEvent&BIT(WAKE_CORE_INTERNAL_WAKE_EVENT_BIT)) ) {
709  WAKE_CORE = WAKE_CORE_FIELD;
710 
711 
712 
713  }
714  //
715  //
716  //The SleepTMR CMPA is linked to a real ISR. If the SleepTMR CMPA
717  //interrupt is enabled and CMPA is a wake event, then pend the CMPA
718  //interrupt (force the second level interrupt).
719  if( (INT_SLEEPTMRCFG&INT_SLEEPTMRCMPA) &&
720  (halInternalWakeEvent&BIT(CMPA_INTERNAL_WAKE_EVENT_BIT)) ) {
721  INT_SLEEPTMRFORCE = INT_SLEEPTMRCMPA;
722 
723 
724 
725  }
726  //
727  //The SleepTMR CMPB is linked to a real ISR. If the SleepTMR CMPB
728  //interrupt is enabled and CMPB is a wake event, then pend the CMPB
729  //interrupt (force the second level interrupt).
730  if( (INT_SLEEPTMRCFG&INT_SLEEPTMRCMPB) &&
731  (halInternalWakeEvent&BIT(CMPB_INTERNAL_WAKE_EVENT_BIT)) ) {
732  INT_SLEEPTMRFORCE = INT_SLEEPTMRCMPB;
733 
734 
735 
736  }
737  //
738  //The SleepTMR WRAP is linked to a real ISR. If the SleepTMR WRAP
739  //interrupt is enabled and WRAP is a wake event, then pend the WRAP
740  //interrupt (force the second level interrupt).
741  if( (INT_SLEEPTMRCFG&INT_SLEEPTMRWRAP) &&
742  (halInternalWakeEvent&BIT(WRAP_INTERNAL_WAKE_EVENT_BIT)) ) {
743  INT_SLEEPTMRFORCE = INT_SLEEPTMRWRAP;
744 
745 
746 
747  }
748  //
749  //
750  //The four IRQs are linked to a real ISR. If any of the four IRQs
751  //triggered, then pend their ISR
752  //
753  //If the IRQA interrupt mode is enabled and IRQA (PB0) is wake
754  //event, then pend the interrupt.
755  if( ((GPIO_INTCFGA&GPIO_INTMOD)!=0) &&
756  (halInternalWakeEvent&BIT(PORTB_PIN(0))) ) {
757  INT_PENDSET = INT_IRQA;
758 
759 
760 
761  }
762  //If the IRQB interrupt mode is enabled and IRQB (PB6) is wake
763  //event, then pend the interrupt.
764  if( ((GPIO_INTCFGB&GPIO_INTMOD)!=0) &&
765  (halInternalWakeEvent&BIT(PORTB_PIN(6))) ) {
766  INT_PENDSET = INT_IRQB;
767 
768 
769 
770  }
771  //If the IRQC interrupt mode is enabled and IRQC (GPIO_IRQCSEL) is wake
772  //event, then pend the interrupt.
773  if( ((GPIO_INTCFGC&GPIO_INTMOD)!=0) &&
774  (halInternalWakeEvent&BIT(GPIO_IRQCSEL)) ) {
775  INT_PENDSET = INT_IRQC;
776 
777 
778 
779  }
780  //If the IRQD interrupt mode is enabled and IRQD (GPIO_IRQDSEL) is wake
781  //event, then pend the interrupt.
782  if( ((GPIO_INTCFGD&GPIO_INTMOD)!=0) &&
783  (halInternalWakeEvent&BIT(GPIO_IRQDSEL)) ) {
784  INT_PENDSET = INT_IRQD;
785 
786 
787 
788  }
789  }
790 
791 
792 
793 
794 
795 
796  //Mark the wake events valid just before exiting
797  halInternalWakeEvent |= BIT32(WAKEINFOVALID_INTERNAL_WAKE_EVENT_BIT);
798 
799  //We are now reconfigured, appropriate ISRs are pended, and ready to go,
800  //so enable interrupts!
801  INTERRUPTS_ON();
802 
803 
804 
805 
806 
807  break; //and deep sleeping is done!
808 
809  case SLEEPMODE_IDLE:
810  //Only the CPU is idled. The rest of the chip continues runing
811  //normally. The chip will wake from any interrupt.
812  {
813  boolean restoreWatchdog = halInternalWatchDogEnabled();
814  //disable watchdog while sleeping (since we can't reset it asleep)
816  //Normal ATOMIC/INTERRUPTS_OFF/INTERRUPTS_ON uses the BASEPRI mask
817  //to juggle priority levels so that the fault handlers can always
818  //be serviced. But, the WFI instruction is only capable of
819  //working with the PRIMASK bit. Therefore, we have to switch from
820  //using BASEPRI to PRIMASK to keep interrupts disabled so that the
821  //WFI can return on an interrupt
822  //Globally disable interrupts with PRIMASK
823  _setPriMask();
824  //Bring the BASEPRI up to 0 to allow interrupts (but still disabled
825  //with PRIMASK)
826  INTERRUPTS_ON();
827  //an internal function call is made here instead of injecting the
828  //"WFI" assembly instruction because injecting assembly code will
829  //cause the compiler's optimizer to reduce efficiency.
831  //The WFI instruction does not actually clear the PRIMASK bit, it
832  //only allows the PRIMASK bit to be bypassed. Therefore, we must
833  //manually clear PRIMASK to reenable all interrupts.
834  _clearPriMask();
835  //restart watchdog if it was running when we entered sleep
836  if(restoreWatchdog)
838  }
839  break;
840 
841  default:
842  //Oops! Invalid sleepMode parameter.
843  assert(0);
844  }
845 }
846 
847 
848 void halSleepWithOptions(SleepModes sleepMode, int32u gpioWakeBitMask)
849 {
850  //configure all GPIO wake sources
851  GPIO_PAWAKE = (gpioWakeBitMask>>0)&0xFF;
852  GPIO_PBWAKE = (gpioWakeBitMask>>8)&0xFF;
853  GPIO_PCWAKE = (gpioWakeBitMask>>16)&0xFF;
854 
855  //use the defines found in the board file to choose our wakeup source(s)
856  WAKE_SEL = 0; //start with no wake sources
857 
858  //if any of the GPIO wakeup monitor bits are set, enable the top level
859  //GPIO wakeup monitor
860  if((GPIO_PAWAKE)||(GPIO_PBWAKE)||(GPIO_PCWAKE)) {
861  WAKE_SEL |= GPIO_WAKE;
862  }
863  //always wakeup when the debugger is connected
864  WAKE_SEL |= WAKE_CDBGPWRUPREQ;
865  //always wakeup when the debugger attempts to access the chip
866  WAKE_SEL |= WAKE_CSYSPWRUPREQ;
867  //always wakeup when the debug channel attempts to access the chip
868  WAKE_SEL |= WAKE_WAKE_CORE;
869  //the timer wakeup sources are enabled below in POWERSAVE, if needed
870 
871  //wake sources are configured so do the actual sleeping
872  halInternalSleep(sleepMode);
873 }