Exemplo n.º 1
0
/*---------------------------------------------------------------------------*/
void
watchdog_stop(void)
{
  halInternalDisableWatchDog(MICRO_DISABLE_WATCH_DOG_KEY);
}
Exemplo n.º 2
0
void halInternalSleep(SleepModes sleepMode)
{
    //Timer restoring always takes place during the wakeup sequence.  We save
    //the state here in case SLEEPMODE_NOTIMER is invoked, which would disable
    //the clocks.
    int32u SLEEPTMR_CLKEN_SAVED = SLEEPTMR_CLKEN;

    //This code assumes all wake source registers are properly configured.
    //As such, it should be called from halSleepWithOptions() or from
    // halSleepForQsWithOptions() which configues the wake sources.

    //The parameter gpioWakeSel is a bitfield composite of the GPIO wake
    //sources derived from the 3 ports, indicating which of the 24 GPIO
    //are configured as a wake source.
    int32u gpioWakeSel  = (GPIO_PAWAKE<<0);
    gpioWakeSel |= (GPIO_PBWAKE<<8);
    gpioWakeSel |= (GPIO_PCWAKE<<16);

    //PB2 is also WAKE_SC1.  Set this wake source if PB2's GPIO wake is set.
    if(GPIO_PBWAKE & PB2)
    {
        WAKE_SEL |= WAKE_SC1;
    }

    //PA2 is also WAKE_SC2.  Set this wake source if PA2's GPIO wake is set.
    if(GPIO_PAWAKE & PA2)
    {
        WAKE_SEL |= WAKE_SC2;
    }

    //The WAKE_IRQD source can come from any pin based on IRQD's sel register.
    if(gpioWakeSel & BIT(GPIO_IRQDSEL))
    {
        WAKE_SEL |= WAKE_IRQD;
    }

    halInternalWakeEvent = 0; //clear old wake events

    switch(sleepMode)
    {
    case SLEEPMODE_NOTIMER:
        //The sleep timer clock sources (both RC and XTAL) are turned off.
        //Wakeup is possible from only GPIO.  System time is lost.
        //NOTE: Timer restoring always takes place during the wakeup sequence.
        SLEEPTMR_CLKEN = 0;
        goto deepSleepCore;

    case SLEEPMODE_WAKETIMER:
        //The sleep timer clock sources remain running.  The RC is always
        //running and the 32kHz XTAL depends on the board header.  Wakeup
        //is possible from both GPIO and the sleep timer.  System time
        //is maintained.  The sleep timer is assumed to be configured
        //properly for wake events.
        //NOTE: This mode assumes the caller has configured the *entire*
        //      sleep timer properly.

        if(INT_SLEEPTMRCFG&INT_SLEEPTMRWRAP)
        {
            WAKE_SEL |= WAKE_SLEEPTMRWRAP;
        }
        if(INT_SLEEPTMRCFG&INT_SLEEPTMRCMPB)
        {
            WAKE_SEL |= WAKE_SLEEPTMRCMPB;
        }
        if(INT_SLEEPTMRCFG&INT_SLEEPTMRCMPA)
        {
            WAKE_SEL |= WAKE_SLEEPTMRCMPA;
        }
        //fall into SLEEPMODE_MAINTAINTIMER's sleep code:

    case SLEEPMODE_MAINTAINTIMER:
        //The sleep timer clock sources remain running.  The RC is always
        //running and the 32kHz XTAL depends on the board header.  Wakeup
        //is possible from only GPIO.  System time is maintained.
        //NOTE: System time is maintained without any sleep timer interrupts
        //      because the hardware sleep timer counter is large enough
        //      to hold the entire count value and not need a RAM counter.

        ////////////////////////////////////////////////////////////////////////////
        // Core deep sleep code
        ////////////////////////////////////////////////////////////////////////////
deepSleepCore:
        // Interrupts *must* be/stay disabled for DEEP SLEEP operation
        // INTERRUPTS_OFF will use BASEPRI to disable all interrupts except
        // fault handlers and PendSV.
        INTERRUPTS_OFF();
        // This is the point of no return.  From here on out, only the interrupt
        // sources available in WAKE_SEL will be captured and propagated across
        // deep sleep.
        //stick all our saved info onto stack since it's only temporary
        {
            boolean restoreWatchdog = halInternalWatchDogEnabled();
            boolean skipSleep = FALSE;

            // Only three register blocks keep power across deep sleep:
            //  CM_HV, GPIO, SLOW_TIMERS
            //
            // All other register blocks lose their state across deep sleep:
            //  BASEBAND, MAC, SECURITY, SERIAL, TMR1, TMR2, EVENT, CM_LV, RAM_CTRL,
            //  AUX_ADC, CAL_ADC, FLASH_CONTROL, ITM, DWT, FPB, NVIC, TPIU
            //
            // The sleep code will only save and restore registers where it is
            // meaningful and necessary to do so.  In most cases, there must still
            // be a powerup function to restore proper state.
            //
            // NOTE: halPowerUp() and halPowerDown() will always be called before
            // and after this function.  halPowerDown and halPowerUp should leave
            // the modules in a safe state and then restart the modules.
            // (For example, shutting down and restarting Timer1)
            //
            //----BASEBAND
            //        reinitialized by stStackPowerUp()
            //----MAC
            //        reinitialized by stStackPowerUp()
            //----SECURITY
            //        reinitialized by stStackPowerUp()
            //----SERIAL
            //        reinitialized by halPowerUp() or similar
            //----TMR1
            //        reinitialized by halPowerUp() or similar
            //----TMR2
            //        reinitialized by halPowerUp() or similar
            //----EVENT
            //SRC or FLAG interrupts are not saved or restored
            //MISS interrupts are not saved or restored
            //MAC_RX_INT_MASK - reinitialized by stStackPowerUp()
            //MAC_TX_INT_MASK - reinitialized by stStackPowerUp()
            //MAC_TIMER_INT_MASK - reinitialized by stStackPowerUp()
            //BB_INT_MASK - reinitialized by stStackPowerUp()
            //SEC_INT_MASK - reinitialized by stStackPowerUp()
            int32u INT_SLEEPTMRCFG_SAVED = INT_SLEEPTMRCFG_REG;
            int32u INT_MGMTCFG_SAVED = INT_MGMTCFG_REG;
            //INT_TIM1CFG - reinitialized by halPowerUp() or similar
            //INT_TIM2CFG - reinitialized by halPowerUp() or similar
            //INT_SC1CFG - reinitialized by halPowerUp() or similar
            //INT_SC2CFG - reinitialized by halPowerUp() or similar
            //INT_ADCCFG - reinitialized by halPowerUp() or similar
            int32u GPIO_INTCFGA_SAVED = GPIO_INTCFGA_REG;
            int32u GPIO_INTCFGB_SAVED = GPIO_INTCFGB_REG;
            int32u GPIO_INTCFGC_SAVED = GPIO_INTCFGC_REG;
            int32u GPIO_INTCFGD_SAVED = GPIO_INTCFGD_REG;
            //SC1_INTMODE - reinitialized by halPowerUp() or similar
            //SC2_INTMODE - reinitialized by halPowerUp() or similar
            //----CM_LV
            int32u OSC24M_BIASTRIM_SAVED = OSC24M_BIASTRIM_REG;
            int32u OSCHF_TUNE_SAVED = OSCHF_TUNE_REG;
            int32u DITHER_DIS_SAVED = DITHER_DIS_REG;
            //OSC24M_CTRL - reinitialized by halPowerUp() or similar
            //CPU_CLKSEL  - reinitialized by halPowerUp() or similar
            //TMR1_CLK_SEL - reinitialized by halPowerUp() or similar
            //TMR2_CLK_SEL - reinitialized by halPowerUp() or similar
            int32u PCTRACE_SEL_SAVED = PCTRACE_SEL_REG;
            //----RAM_CTRL
            int32u MEM_PROT_0_SAVED = MEM_PROT_0_REG;
            int32u MEM_PROT_1_SAVED = MEM_PROT_1_REG;
            int32u MEM_PROT_2_SAVED = MEM_PROT_2_REG;
            int32u MEM_PROT_3_SAVED = MEM_PROT_3_REG;
            int32u MEM_PROT_4_SAVED = MEM_PROT_4_REG;
            int32u MEM_PROT_5_SAVED = MEM_PROT_5_REG;
            int32u MEM_PROT_6_SAVED = MEM_PROT_6_REG;
            int32u MEM_PROT_7_SAVED = MEM_PROT_7_REG;
            int32u MEM_PROT_EN_SAVED = MEM_PROT_EN_REG;
            //----AUX_ADC
            //        reinitialized by halPowerUp() or similar
            //----CAL_ADC
            //        reinitialized by stStackPowerUp()
            //----FLASH_CONTROL
            //        configured on the fly by the flash library
            //----ITM
            //        reinitialized by halPowerUp() or similar
            //----DWT
            //        not used by software on chip
            //----FPB
            //        not used by software on chip
            //----NVIC
            //ST_CSR - fixed, restored by cstartup when exiting deep sleep
            //ST_RVR - fixed, restored by cstartup when exiting deep sleep
            int32u INT_CFGSET_SAVED = INT_CFGSET_REG; //mask against wake sources
            //INT_PENDSET - used below when overlapping interrupts and wake sources
            //NVIC_IPR_3to0 - fixed, restored by cstartup when exiting deep sleep
            //NVIC_IPR_7to4 - fixed, restored by cstartup when exiting deep sleep
            //NVIC_IPR_11to8 - fixed, restored by cstartup when exiting deep sleep
            //NVIC_IPR_15to12 - fixed, restored by cstartup when exiting deep sleep
            //NVIC_IPR_19to16 - fixed, restored by cstartup when exiting deep sleep
            int32u SCS_VTOR_SAVED = SCS_VTOR_REG;
            //SCS_CCR - fixed, restored by cstartup when exiting deep sleep
            //SCS_SHPR_7to4 - fixed, restored by cstartup when exiting deep sleep
            //SCS_SHPR_11to8 - fixed, restored by cstartup when exiting deep sleep
            //SCS_SHPR_15to12 - fixed, restored by cstartup when exiting deep sleep
            //SCS_SHCSR - fixed, restored by cstartup when exiting deep sleep
            //----TPIU
            //        reinitialized by halPowerUp() or similar

            //stmDebugPowerDown() should have shutdown the DWT/ITM/TPIU already.

            //freeze input to the GPIO from LV (alternate output functions freeze)
            EVENT_CTRL = LV_FREEZE;
            //record GPIO state for wake monitoring purposes
            //By having a snapshot of GPIO state, we can figure out after waking
            //up exactly which GPIO could have woken us up.
            //Reading the three IN registers is done separately to avoid warnings
            //about undefined order of volatile access.
            int32u GPIO_IN_SAVED =   GPIO_PAIN;
            GPIO_IN_SAVED |= (GPIO_PBIN<<8);
            GPIO_IN_SAVED |= (GPIO_PCIN<<16);
            //reset the power up events by writing 1 to all bits.
            PWRUP_EVENT = 0xFFFFFFFF;



            //By clearing the events, the wake up event capturing is activated.
            //At this point we can safely check our interrupt flags since event
            //capturing is now overlapped.  Up to now, interrupts indicate
            //activity, after this point, powerup events indicate activity.
            //If any of the interrupt flags are set, that means we saw a wake event
            //sometime while entering sleep, so we need to skip over sleeping
            //
            //--possible interrupt sources for waking:
            //  IRQA, IRQB, IRQC, IRQD
            //  SleepTMR CMPA, CMPB, Wrap
            //  WAKE_CORE (DebugIsr)
            //
            //check for IRQA interrupt and if IRQA (PB0) is wake source
            if((INT_PENDSET&INT_IRQA) &&
                    (GPIO_PBWAKE&PB0) &&
                    (WAKE_SEL&GPIO_WAKE))
            {
                skipSleep = TRUE;
                //log IRQA as a wake event
                halInternalWakeEvent |= BIT(PORTB_PIN(0));



            }
            //check for IRQB interrupt and if IRQB (PB6) is wake source
            if((INT_PENDSET&INT_IRQB) &&
                    (GPIO_PBWAKE&PB6) &&
                    (WAKE_SEL&GPIO_WAKE))
            {
                skipSleep = TRUE;
                //log IRQB as a wake event
                halInternalWakeEvent |= BIT(PORTB_PIN(6));



            }
            //check for IRQC interrupt and if IRQC (GPIO_IRQCSEL) is wake source
            if((INT_PENDSET&INT_IRQC) &&
                    (gpioWakeSel&BIT(GPIO_IRQCSEL)) &&
                    (WAKE_SEL&GPIO_WAKE))
            {
                skipSleep = TRUE;
                //log IRQC as a wake event
                halInternalWakeEvent |= BIT(GPIO_IRQCSEL);



            }
            //check for IRQD interrupt and if IRQD (GPIO_IRQDSEL) is wake source
            if((INT_PENDSET&INT_IRQD) &&
                    (gpioWakeSel&BIT(GPIO_IRQDSEL)) &&
                    ((WAKE_SEL&GPIO_WAKE) ||
                     (WAKE_SEL&WAKE_IRQD)))
            {
                skipSleep = TRUE;
                //log IRQD as a wake event
                halInternalWakeEvent |= BIT(GPIO_IRQDSEL);



            }
            //check for SleepTMR CMPA interrupt and if SleepTMR CMPA is wake source
            if((INT_SLEEPTMR&INT_SLEEPTMRCMPA) && (WAKE_SEL&WAKE_SLEEPTMRCMPA))
            {
                skipSleep = TRUE;
                //log SleepTMR CMPA as a wake event
                halInternalWakeEvent |= BIT32(CMPA_INTERNAL_WAKE_EVENT_BIT);



            }
            //check for SleepTMR CMPB interrupt and if SleepTMR CMPB is wake source
            if((INT_SLEEPTMR&INT_SLEEPTMRCMPB) && (WAKE_SEL&WAKE_SLEEPTMRCMPB))
            {
                skipSleep = TRUE;
                //log SleepTMR CMPB as a wake event
                halInternalWakeEvent |= BIT32(CMPB_INTERNAL_WAKE_EVENT_BIT);



            }
            //check for SleepTMR WRAP interrupt and if SleepTMR WRAP is wake source
            if((INT_SLEEPTMR&INT_SLEEPTMRWRAP) && (WAKE_SEL&WAKE_SLEEPTMRWRAP))
            {
                skipSleep = TRUE;
                //log SleepTMR WRAP as a wake event
                halInternalWakeEvent |= BIT32(WRAP_INTERNAL_WAKE_EVENT_BIT);



            }
            //check for Debug interrupt and if WAKE_CORE is wake source
            if((INT_PENDSET&INT_DEBUG) && (WAKE_SEL&WAKE_WAKE_CORE))
            {
                skipSleep = TRUE;
                //log WAKE_CORE as a wake event
                halInternalWakeEvent |= BIT32(WAKE_CORE_INTERNAL_WAKE_EVENT_BIT);



            }

            //only propagate across deep sleep the interrupts that are both
            //enabled and possible wake sources
            {
                int32u wakeSourceInterruptMask = 0;

                if(GPIO_PBWAKE&PB0)
                {
                    wakeSourceInterruptMask |= INT_IRQA;



                }
                if(GPIO_PBWAKE&PB6)
                {
                    wakeSourceInterruptMask |= INT_IRQB;



                }
                if(gpioWakeSel&BIT(GPIO_IRQCSEL))
                {
                    wakeSourceInterruptMask |= INT_IRQC;



                }
                if(gpioWakeSel&BIT(GPIO_IRQDSEL))
                {
                    wakeSourceInterruptMask |= INT_IRQD;



                }
                if( (WAKE_SEL&WAKE_SLEEPTMRCMPA) ||
                        (WAKE_SEL&WAKE_SLEEPTMRCMPB) ||
                        (WAKE_SEL&WAKE_SLEEPTMRWRAP) )
                {
                    wakeSourceInterruptMask |= INT_SLEEPTMR;



                }
                if(WAKE_SEL&WAKE_WAKE_CORE)
                {
                    wakeSourceInterruptMask |= INT_DEBUG;



                }

                INT_CFGSET_SAVED &= wakeSourceInterruptMask;
            }

















            //disable watchdog while sleeping (since we can't reset it asleep)
            halInternalDisableWatchDog(MICRO_DISABLE_WATCH_DOG_KEY);

            //The chip is not allowed to enter a deep sleep mode (which could
            //cause a core reset cycle) while CSYSPWRUPREQ is set.  CSYSPWRUPREQ
            //indicates that the debugger is trying to access sections of the
            //chip that would get reset during deep sleep.  Therefore, a reset
            //cycle could very easily cause the debugger to error and we don't
            //want that.  While the power management state machine will stall
            //if CSYSPWRUPREQ is set (to avoid the situation just described),
            //in this stalled state the chip will not be responsive to wake
            //events.  To be sensitive to wake events, we must handle them in
            //software instead.  To accomplish this, we request that the
            //CSYSPWRUPACK be inhibited (which will indicate the debugger is not
            //connected).  But, we cannot induce deep sleep until CSYSPWRUPREQ/ACK
            //go low and these are under the debuggers control, so we must stall
            //and wait here.  If there is a wake event during this time, break
            //out and wake like normal.  If the ACK eventually clears,
            //we can proceed into deep sleep.  The CSYSPWRUPACK_INHIBIT
            //functionality will hold off the debugger (by holding off the ACK)
            //until we are safely past and out of deep sleep.  The power management
            //state machine then becomes responsible for clearing
            //CSYSPWRUPACK_INHIBIT and responding to a CSYSPWRUPREQ with a
            //CSYSPWRUPACK at the right/safe time.
            CSYSPWRUPACK_INHIBIT = CSYSPWRUPACK_INHIBIT_CSYSPWRUPACK_INHIBIT;
            {
                //Use a local copy of WAKE_SEL to avoid warnings from the compiler
                //about order of volatile accesses
                int32u wakeSel = WAKE_SEL;
                //stall until a wake event or CSYSPWRUPREQ/ACK clears
                while( (CSYSPWRUPACK_STATUS) && (!(PWRUP_EVENT&wakeSel)) ) {}
                //if there was a wake event, allow CSYSPWRUPACK and skip sleep
                if(PWRUP_EVENT&wakeSel)
                {
                    CSYSPWRUPACK_INHIBIT = CSYSPWRUPACK_INHIBIT_RESET;
                    skipSleep = TRUE;
                }
            }





            if(!skipSleep)
            {



                //FogBugz 7283 states that we must switch to the OSCHF when entering
                //deep sleep since using the 24MHz XTAL could result in RAM
                //corruption.  This switch must occur at least 2*24MHz cycles before
                //sleeping.
                //FogBugz 8858 states that we cannot go into deep-sleep when the
                //chip is clocked with the 24MHz XTAL with a duty cycle as low as
                //70/30 since this causes power_down generation timing to fail.
                OSC24M_CTRL &= ~OSC24M_CTRL_OSC24M_SEL;
                //If DS12 needs to be forced regardless of state, clear
                //REGEN_DSLEEP here.  This is hugely dangerous and
                //should only be done in very controlled chip tests.
                SCS_SCR |= SCS_SCR_SLEEPDEEP;      //enable deep sleep
                extern volatile boolean halPendSvSaveContext;
                halPendSvSaveContext = 1;          //1 means save context
                //The INTERRUPTS_OFF used at the beginning of this function set
                //BASEPRI such that the only interrupts that will fire are faults
                //and PendSV.  Trigger PendSV now to induce a context save.
                SCS_ICSR |= SCS_ICSR_PENDSVSET;    //pend the context save and Dsleep
                //Since the interrupt will not fire immediately it is possible to
                //execute a few lines of code.  To stay halted in this spot until the
                //WFI instruction, spin on the context flag (which will get cleared
                //during the startup sequence when restoring context).
                while(halPendSvSaveContext) {}
                //I AM ASLEEP.  WHEN EXECUTION RESUMES, CSTARTUP WILL RESTORE TO HERE
            }
            else
            {
                //Record the fact that we skipped sleep
                halInternalWakeEvent |= BIT32(SLEEPSKIPPED_INTERNAL_WAKE_EVENT_BIT);
                //If this was a true deep sleep, we would have executed cstartup and
                //PRIMASK would be set right now.  If we skipped sleep, PRIMASK is not
                //set so we explicitely set it to guarantee the powerup sequence
                //works cleanly and consistently with respect to interrupt
                //dispatching and enabling.
                _setPriMask();
            }








            //Clear the interrupt flags for all wake sources.  This
            //is necessary because if we don't execute an actual deep sleep cycle
            //the interrupt flags will never be cleared.  By clearing the flags,
            //we always mimick a real deep sleep as closely as possible and
            //guard against any accidental interrupt triggering coming out
            //of deep sleep.  (The interrupt dispatch code coming out of sleep
            //is responsible for translating wake events into interrupt events,
            //and if we don't clear interrupt flags here it's possible for an
            //interrupt to trigger even if it wasn't the true wake event.)
            INT_SLEEPTMRFLAG = (INT_SLEEPTMRCMPA |
                                INT_SLEEPTMRCMPB |
                                INT_SLEEPTMRWRAP);
            INT_GPIOFLAG = (INT_IRQAFLAG |
                            INT_IRQBFLAG |
                            INT_IRQCFLAG |
                            INT_IRQDFLAG);

            //immediately restore the registers we saved before sleeping
            //so IRQ and SleepTMR capture can be reenabled as quickly as possible
            //this is safe because our global interrupts are still disabled
            //other registers will be restored later







            SLEEPTMR_CLKEN_REG = SLEEPTMR_CLKEN_SAVED;
            INT_SLEEPTMRCFG_REG = INT_SLEEPTMRCFG_SAVED;
            INT_MGMTCFG_REG = INT_MGMTCFG_SAVED;
            GPIO_INTCFGA_REG = GPIO_INTCFGA_SAVED;
            GPIO_INTCFGB_REG = GPIO_INTCFGB_SAVED;
            GPIO_INTCFGC_REG = GPIO_INTCFGC_SAVED;
            GPIO_INTCFGD_REG = GPIO_INTCFGD_SAVED;
            OSC24M_BIASTRIM_REG = OSC24M_BIASTRIM_SAVED;
            OSCHF_TUNE_REG = OSCHF_TUNE_SAVED;
            DITHER_DIS_REG = DITHER_DIS_SAVED;
            PCTRACE_SEL_REG = PCTRACE_SEL_SAVED;
            MEM_PROT_0_REG = MEM_PROT_0_SAVED;
            MEM_PROT_1_REG = MEM_PROT_1_SAVED;
            MEM_PROT_2_REG = MEM_PROT_2_SAVED;
            MEM_PROT_3_REG = MEM_PROT_3_SAVED;
            MEM_PROT_4_REG = MEM_PROT_4_SAVED;
            MEM_PROT_5_REG = MEM_PROT_5_SAVED;
            MEM_PROT_6_REG = MEM_PROT_6_SAVED;
            MEM_PROT_7_REG = MEM_PROT_7_SAVED;
            MEM_PROT_EN_REG = MEM_PROT_EN_SAVED;
            INT_CFGSET_REG = INT_CFGSET_SAVED;
            SCS_VTOR_REG = SCS_VTOR_SAVED;

            //WAKE_CORE/INT_DEBUG and INT_IRQx is cleared by INT_PENDCLR below
            INT_PENDCLR = 0xFFFFFFFF;

            //Now that we're awake, normal interrupts are operational again
            //Take a snapshot of the new GPIO state and the EVENT register to
            //record our wake event
            int32u GPIO_IN_NEW =   GPIO_PAIN;
            GPIO_IN_NEW |= (GPIO_PBIN<<8);
            GPIO_IN_NEW |= (GPIO_PCIN<<16);
            //Only operate on power up events that are also wake events.  Power
            //up events will always trigger like an interrupt flag, so we have
            //to check them against events that are enabled for waking. (This is
            //a two step process because we're accessing two volatile values.)
            int32u powerUpEvents = PWRUP_EVENT;
            powerUpEvents &= WAKE_SEL;
            halInternalWakeEvent |= ((GPIO_IN_SAVED^GPIO_IN_NEW)&gpioWakeSel);
            //PWRUP_SC1 is PB2 which is bit 10
            halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_SC1))<<((1*8)+2);
            //PWRUP_SC2 is PA2 which is bit 2
            halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_SC2))<<((0*8)+2);
            //PWRUP_IRQD is chosen by GPIO_IRQDSEL
            halInternalWakeEvent |= (!!(powerUpEvents&PWRUP_IRQD))<<(GPIO_IRQDSEL);
            halInternalWakeEvent |= ((powerUpEvents &
                                      (PWRUP_CSYSPWRUPREQ_MASK  |
                                       PWRUP_CDBGPWRUPREQ_MASK  |
                                       PWRUP_WAKECORE_MASK      |
                                       PWRUP_SLEEPTMRWRAP_MASK  |
                                       PWRUP_SLEEPTMRCOMPB_MASK |
                                       PWRUP_SLEEPTMRCOMPA_MASK ))
                                     <<INTERNAL_WAKE_EVENT_BIT_SHIFT);
            //at this point wake events are fully captured and interrupts have
            //taken over handling all new events






            //Bring limited interrupts back online.  INTERRUPTS_OFF will use
            //BASEPRI to disable all interrupts except fault handlers and PendSV.
            //PRIMASK is still set though (global interrupt disable) so we need
            //to clear that next.
            INTERRUPTS_OFF();





            //Now that BASEPRI has taken control of interrupt enable/disable,
            //we can clear PRIMASK to reenable global interrupt operation.
            _clearPriMask();





            //wake events are saved and interrupts are back on track,
            //disable gpio freeze
            EVENT_CTRL = EVENT_CTRL_RESET;

            //restart watchdog if it was running when we entered sleep
            //do this before dispatching interrupts while we still have tight
            //control of code execution
            if(restoreWatchdog)
            {
                halInternalEnableWatchDog();
            }





            //Pend any interrupts associated with deep sleep wake sources.  The
            //restoration of INT_CFGSET above and the changing of BASEPRI below
            //is responsible for proper dispatching of interrupts at the end of
            //halSleepWithOptions.
            //
            //
            //The WAKE_CORE wake source triggers a Debug Interrupt.  If INT_DEBUG
            //interrupt is enabled and WAKE_CORE is a wake event, then pend the
            //Debug interrupt (using the wake_core bit).
            if( (INT_CFGSET&INT_DEBUG) &&
                    (halInternalWakeEvent&BIT(WAKE_CORE_INTERNAL_WAKE_EVENT_BIT)) )
            {
                WAKE_CORE = WAKE_CORE_FIELD;



            }
            //
            //
            //The SleepTMR CMPA is linked to a real ISR.  If the SleepTMR CMPA
            //interrupt is enabled and CMPA is a wake event, then pend the CMPA
            //interrupt (force the second level interrupt).
            if( (INT_SLEEPTMRCFG&INT_SLEEPTMRCMPA) &&
                    (halInternalWakeEvent&BIT(CMPA_INTERNAL_WAKE_EVENT_BIT)) )
            {
                INT_SLEEPTMRFORCE = INT_SLEEPTMRCMPA;



            }
            //
            //The SleepTMR CMPB is linked to a real ISR.  If the SleepTMR CMPB
            //interrupt is enabled and CMPB is a wake event, then pend the CMPB
            //interrupt (force the second level interrupt).
            if( (INT_SLEEPTMRCFG&INT_SLEEPTMRCMPB) &&
                    (halInternalWakeEvent&BIT(CMPB_INTERNAL_WAKE_EVENT_BIT)) )
            {
                INT_SLEEPTMRFORCE = INT_SLEEPTMRCMPB;



            }
            //
            //The SleepTMR WRAP is linked to a real ISR.  If the SleepTMR WRAP
            //interrupt is enabled and WRAP is a wake event, then pend the WRAP
            //interrupt (force the second level interrupt).
            if( (INT_SLEEPTMRCFG&INT_SLEEPTMRWRAP) &&
                    (halInternalWakeEvent&BIT(WRAP_INTERNAL_WAKE_EVENT_BIT)) )
            {
                INT_SLEEPTMRFORCE = INT_SLEEPTMRWRAP;



            }
            //
            //
            //The four IRQs are linked to a real ISR.  If any of the four IRQs
            //triggered, then pend their ISR
            //
            //If the IRQA interrupt mode is enabled and IRQA (PB0) is wake
            //event, then pend the interrupt.
            if( ((GPIO_INTCFGA&GPIO_INTMOD)!=0) &&
                    (halInternalWakeEvent&BIT(PORTB_PIN(0))) )
            {
                INT_PENDSET = INT_IRQA;



            }
            //If the IRQB interrupt mode is enabled and IRQB (PB6) is wake
            //event, then pend the interrupt.
            if( ((GPIO_INTCFGB&GPIO_INTMOD)!=0) &&
                    (halInternalWakeEvent&BIT(PORTB_PIN(6))) )
            {
                INT_PENDSET = INT_IRQB;



            }
            //If the IRQC interrupt mode is enabled and IRQC (GPIO_IRQCSEL) is wake
            //event, then pend the interrupt.
            if( ((GPIO_INTCFGC&GPIO_INTMOD)!=0) &&
                    (halInternalWakeEvent&BIT(GPIO_IRQCSEL)) )
            {
                INT_PENDSET = INT_IRQC;



            }
            //If the IRQD interrupt mode is enabled and IRQD (GPIO_IRQDSEL) is wake
            //event, then pend the interrupt.
            if( ((GPIO_INTCFGD&GPIO_INTMOD)!=0) &&
                    (halInternalWakeEvent&BIT(GPIO_IRQDSEL)) )
            {
                INT_PENDSET = INT_IRQD;



            }
        }






        //Mark the wake events valid just before exiting
        halInternalWakeEvent |= BIT32(WAKEINFOVALID_INTERNAL_WAKE_EVENT_BIT);

        //We are now reconfigured, appropriate ISRs are pended, and ready to go,
        //so enable interrupts!
        INTERRUPTS_ON();





        break; //and deep sleeping is done!

    case SLEEPMODE_IDLE:
        //Only the CPU is idled.  The rest of the chip continues runing
        //normally.  The chip will wake from any interrupt.
    {
        boolean restoreWatchdog = halInternalWatchDogEnabled();
        //disable watchdog while sleeping (since we can't reset it asleep)
        halInternalDisableWatchDog(MICRO_DISABLE_WATCH_DOG_KEY);
        //Normal ATOMIC/INTERRUPTS_OFF/INTERRUPTS_ON uses the BASEPRI mask
        //to juggle priority levels so that the fault handlers can always
        //be serviced.  But, the WFI instruction is only capable of
        //working with the PRIMASK bit.  Therefore, we have to switch from
        //using BASEPRI to PRIMASK to keep interrupts disabled so that the
        //WFI can return on an interrupt
        //Globally disable interrupts with PRIMASK
        _setPriMask();
        //Bring the BASEPRI up to 0 to allow interrupts (but still disabled
        //with PRIMASK)
        INTERRUPTS_ON();
        //an internal function call is made here instead of injecting the
        //"WFI" assembly instruction because injecting assembly code will
        //cause the compiler's optimizer to reduce efficiency.
        halInternalIdleSleep();
        //The WFI instruction does not actually clear the PRIMASK bit, it
        //only allows the PRIMASK bit to be bypassed.  Therefore, we must
        //manually clear PRIMASK to reenable all interrupts.
        _clearPriMask();
        //restart watchdog if it was running when we entered sleep
        if(restoreWatchdog)
            halInternalEnableWatchDog();
    }
    break;

    default:
        //Oops!  Invalid sleepMode parameter.
        assert(0);
    }
}