void gfxMutexEnter(gfxMutex *pmutex) {
	INTERRUPTS_OFF();
	while (pmutex[0]) {
		INTERRUPTS_ON();
		gfxYield();
		INTERRUPTS_OFF();
	}
	pmutex[0] = 1;
	INTERRUPTS_ON();
}
Esempio n. 2
0
/* ------------------------------------------------------------------
 * Initialise the UART
 * ------------------------------------------------------------------ */
void uart_init() {
	INTERRUPTS_OFF();

	// setup ring buffers
	ring_init(&rx, rxbuffer, RX_BUFFER_LENGTH);
	ring_init(&tx, txbuffer, TX_BUFFER_LENGTH);

	// baud rate
	UART_BAUD_RATE_LOW 	= UBRRL_VALUE;
	UART_BAUD_RATE_HIGH = UBRRH_VALUE;

	// double speed?
#ifdef UART_DOUBLE_SPEED
	UART_CONTROL_STATUS_REG_A |= MASK(U2X0);
#else
	UART_CONTROL_STATUS_REG_A &= ~(MASK(U2X0));
#endif

	// mode: async 8N1
	UART_CONTROL_STATUS_REG_C = MASK(UART_CHARACTER_SIZE_0) | MASK(UART_CHARACTER_SIZE_1);

	// enable TX/RX
	UART_CONTROL_STATUS_REG_B = MASK(UART_ENABLE_TRANSMITTER) | MASK(UART_ENABLE_RECEIVER);

	// enable data register empty interrupt
	UART_CONTROL_STATUS_REG_B |= MASK(UART_DATA_REGISTER_EMPTY_INTERRUPT_ENABLE);

	// enable RX complete interrupt
	UART_CONTROL_STATUS_REG_B |= MASK(UART_RECEIVE_COMPLETE);

	INTERRUPTS_ON();
}
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) {
	systemticks_t	starttm, delay;

	// Convert our delay to ticks
	starttm = 0;
	switch (ms) {
	case TIME_IMMEDIATE:
		delay = TIME_IMMEDIATE;
		break;
	case TIME_INFINITE:
		delay = TIME_INFINITE;
		break;
	default:
		delay = gfxMillisecondsToTicks(ms);
		if (!delay) delay = 1;
		starttm = gfxSystemTicks();
	}

	INTERRUPTS_OFF();
	while (psem->cnt <= 0) {
		INTERRUPTS_ON();
		// Check if we have exceeded the defined delay
		switch (delay) {
		case TIME_IMMEDIATE:
			return FALSE;
		case TIME_INFINITE:
			break;
		default:
			if (gfxSystemTicks() - starttm >= delay)
				return FALSE;
			break;
		}
		gfxYield();
		INTERRUPTS_OFF();
	}
	psem->cnt--;
	INTERRUPTS_ON();
	return TRUE;
}
Esempio n. 4
0
/**
  * @brief  Configures interrupt level
  * @param  None
  * @retval None
  */
static void low_level_init2(void)
{
#ifdef CORTEXM3_STM32W108xB
  /* USART bootloader software activation check */
  if ((*((uint32_t *)RAM_BOTTOM) == IAP_BOOTLOADER_APP_SWITCH_SIGNATURE) && (*((uint8_t *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_UART))
  {
    uint8_t cut = *(__IO uint8_t *) (FIB_BOTTOM + 0x0798);
    uint16_t offset = 0;
    typedef void (*EntryPoint)(void);     
    offset = (halFixedAddressTable.baseTable.version == 3) ? blOffset[cut - 2] : 0;
    *((uint32_t *)RAM_BOTTOM) = 0;
    if (offset) 
    {
      switchClock();
    }
    EntryPoint entryPoint = (EntryPoint)(*(uint32_t *)(FIB_BOTTOM+4) - offset);
    setStackPointer(*(uint32_t *)FIB_BOTTOM);
    entryPoint();
  }
#elif defined (CORTEXM3_STM32W108CC)
  /* Embedeed USART or RF bootloader software activation check */
  if ((*((uint32_t *)RAM_BOTTOM) == IAP_BOOTLOADER_APP_SWITCH_SIGNATURE))
  {
    typedef void (*EntryPoint)(void);
    EntryPoint entryPoint;
    uint32_t bootAddress;
    *((uint32_t *)RAM_BOTTOM) = 0;
    if ((*((uint8_t *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_UART) || (*((uint8_t *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_OTA)) 
    {
      bootAddress = (*((uint8_t *)(RAM_BOTTOM+4)) == IAP_BOOTLOADER_MODE_UART) ? FIB_BOTTOM : (FIB1_BOTTOM + 0x800);
      entryPoint = (EntryPoint)(*(uint32_t *)(bootAddress+4));
      setStackPointer(*((uint32_t *)bootAddress));
      entryPoint();
    }
  }
#endif
  
  INTERRUPTS_OFF();

#if (defined (__ICCARM__) || defined (__GNUC__)) 
	asm("CPSIE i");
#elif defined __CC_ARM
    CPSIE();
#else 
 #error "Inline assembler syntax expected"  
#endif
  
}
Esempio n. 5
0
/**
  * @brief  hal internal sleep mode.
  * @param PWR_SleepMode selects the sleep mode 
  * @retval None
  */
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.*/
  uint32_t CLK_SLEEPCRSAVED = CLK->SLEEPCR;
  
  /* 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.*/
  uint32_t gpioWakeSel  = (PWR->WAKEPAR<<0);
         gpioWakeSel |= (PWR->WAKEPBR<<8);
         gpioWakeSel |= (PWR->WAKEPCR<<16);
  
  /* PB2 is also PWR_WAKECR1_SC1.  Set this wake source if PB2's GPIO wake is set.*/
  if(PWR->WAKEPBR & PWR_WAKEPxR_Px2) {
    PWR->WAKECR1 |= PWR_WAKECR1_SC1;
  }
  
  /* PA2 is also PWR_WAKECR1_SC2.  Set this wake source if PA2's GPIO wake is set.*/
  if(PWR->WAKEPAR & PWR_WAKEPxR_Px2) {
    PWR->WAKECR1 |= PWR_WAKECR1_SC2;
  }
  
  /* The PWR_WAKECR1_IRQD source can come from any pin based on IRQD's sel register.*/
  if(gpioWakeSel & BIT(EXTI->CR[1])) {
    PWR->WAKECR1 |= PWR_WAKECR1_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.*/
      CLK->SLEEPCR = 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(SLPTMR->IER&SLPTMR_IER_WRAP) {
        PWR->WAKECR1 |= PWR_WAKECR1_WRAP;
      }
      if(SLPTMR->IER&SLPTMR_IER_CMPB) {
        PWR->WAKECR1 |= PWR_WAKECR1_COMPB;
      }
      if(SLPTMR->IER&SLPTMR_IER_CMPA) {
        PWR->WAKECR1 |= PWR_WAKECR1_COMPA;
      }
      /* 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 PWR->WAKECR1 will be captured and propagated across
         deep sleep.
        stick all our saved info onto stack since it's only temporary */
      {
        boolean restoreWatchdog = WDG_GetStatus();
        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:
            MAC, SECURITY, SERIAL, TMR1, TMR2, EVENT, CM_LV, RAM_CTRL,
            AUX_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() */
        uint32_t SLPTMR_IERSAVED = SLPTMR->IER;
        uint32_t MGMT_IT_IERSAVED = MGMT_IT->IER;
        /* TIM1_IT->IER - reinitialized by halPowerUp() or similar
           TIM2_IT->IER - reinitialized by halPowerUp() or similar
           SC1_IT->IER - reinitialized by halPowerUp() or similar
           SC2_IT->IER - reinitialized by halPowerUp() or similar
           ADC->IER - reinitialized by halPowerUp() or similar */
        uint32_t EXTI_TSRSAVED_0 = EXTI->TSR[0];
        uint32_t EXTI_TSRSAVED_1 = EXTI->TSR[1];
        uint32_t EXTI_TSRSAVED_2 = EXTI->TSR[2];
        uint32_t EXTI_TSRSAVED_3 = EXTI->TSR[3];
        /* SC1_IT->ICR - reinitialized by halPowerUp() or similar
           SC2_IT->ICR - reinitialized by halPowerUp() or similar */
        /* ----CM_LV */
        uint32_t CLK_HSECR1SAVED = CLK->HSECR1;
        uint32_t CLK_HSICRSAVED = CLK->HSICR;
        uint32_t CLK_DITHERCRSAVED = CLK->DITHERCR;
        /* CLK->HSECR2 - reinitialized by halPowerUp() or similar
           CLK->CPUCR  - reinitialized by halPowerUp() or similar
           TMR1_CLK_SEL - reinitialized by halPowerUp() or similar
           TMR2_CLK_SEL - reinitialized by halPowerUp() or similar */
        uint32_t GPIO_PCTRACECRSAVED = GPIO_DBG->PCTRACECR;
        /*----RAM_CTRL */
        uint32_t MEM_RAMPROTR1SAVED = MEM->RAMPROTR1;
        uint32_t MEM_RAMPROTR2SAVED = MEM->RAMPROTR2;
        uint32_t MEM_RAMPROTR3SAVED = MEM->RAMPROTR3;
        uint32_t MEM_RAMPROTR4SAVED = MEM->RAMPROTR4;
        uint32_t MEM_RAMPROTR5SAVED = MEM->RAMPROTR5;
        uint32_t MEM_RAMPROTR6SAVED = MEM->RAMPROTR6;
        uint32_t MEM_RAMPROTR7SAVED = MEM->RAMPROTR7;
        uint32_t MEM_RAMPROTR8SAVED = MEM->RAMPROTR8;
        uint32_t MEM_RAMCRSAVED = MEM->RAMCR;
        /*----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
            SysTick->CTRL- fixed, restored by cstartup when exiting deep sleep
           SysTick->LOAD - fixed, restored by cstartup when exiting deep sleep */
        uint32_t NVIC_ISERSAVED = NVIC->ISER[0]; //mask against wake sources
        /* NVIC->ISPR[0] - 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 */
        uint32_t SCB_VTORSAVED = SCB->VTOR;
        /* SCB->CCR - fixed, restored by cstartup when exiting deep sleep
           SCB->SHP[0] - fixed, restored by cstartup when exiting deep sleep
           SCB->SHP[1] - fixed, restored by cstartup when exiting deep sleep
           SCB->SHP[2] - fixed, restored by cstartup when exiting deep sleep
           SCB->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)*/
        PWR->DSLEEPCR1 = PWR_DSLEEPCR1_LVFREEZE;
        /* 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 __IO access. */
        uint32_t GPIO_IN_SAVED =   GPIOA->IDR;
               GPIO_IN_SAVED |= (GPIOB->IDR<<8);
               GPIO_IN_SAVED |= (GPIOC->IDR<<16);
        /* reset the power up events by writing 1 to all bits. */
        PWR->WAKESR = 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
            PWR->WAKECR2 (DebugIsr)*/

        /* check for IRQA interrupt and if IRQA (PB0) is wake source */
        if((NVIC->ISPR[0]&NVIC_IxxR_IRQA) && (PWR->WAKEPBR&PWR_WAKEPxR_Px0) && (PWR->WAKECR1&PWR_WAKECR1_MONEN))
        {
          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((NVIC->ISPR[0]&NVIC_IxxR_IRQB) && (PWR->WAKEPBR&PWR_WAKEPxR_Px6) && (PWR->WAKECR1&PWR_WAKECR1_MONEN))
        {
          skipSleep = TRUE;
          /* log IRQB as a wake event */
          halInternalWakeEvent |= BIT(PORTB_PIN(6));
        }
        /* check for IRQC interrupt and if IRQC (EXTI->CR[0]) is wake source */
        if((NVIC->ISPR[0]&NVIC_IxxR_IRQC) && (gpioWakeSel&BIT(EXTI->CR[0])) && (PWR->WAKECR1&PWR_WAKECR1_MONEN))
        {
          skipSleep = TRUE;
          /* log IRQC as a wake event */
          halInternalWakeEvent |= BIT(EXTI->CR[0]);
        }
        /* check for IRQD interrupt and if IRQD (EXTI->CR[1]) is wake source */
        if((NVIC->ISPR[0]&NVIC_IxxR_IRQD) && (gpioWakeSel&BIT(EXTI->CR[1])) && ((PWR->WAKECR1&PWR_WAKECR1_MONEN) || (PWR->WAKECR1&PWR_WAKECR1_IRQD)))
        {
          skipSleep = TRUE;
          /* log IRQD as a wake event */
          halInternalWakeEvent |= BIT(EXTI->CR[1]);
        }
        /* check for SleepTMR CMPA interrupt and if SleepTMR CMPA is wake source */
        if((NVIC_IxxR_SLEEPTMR&SLPTMR_IER_CMPA) && (PWR->WAKECR1&PWR_WAKECR1_COMPA))
        {
          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((NVIC_IxxR_SLEEPTMR&SLPTMR_IER_CMPB) && (PWR->WAKECR1&PWR_WAKECR1_COMPB))
        {
          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((NVIC_IxxR_SLEEPTMR&SLPTMR_IER_WRAP) && (PWR->WAKECR1&PWR_WAKECR1_WRAP))
        {
          skipSleep = TRUE;
          /* log SleepTMR WRAP as a wake event */
          halInternalWakeEvent |= BIT32(WRAP_INTERNAL_WAKE_EVENT_BIT);
        }
        /* check for Debug interrupt and if PWR->WAKECR2 is wake source */
        if((NVIC->ISPR[0]&NVIC_IxxR_DEBUG) && (PWR->WAKECR1&PWR_WAKECR1_CORE))
        {
          skipSleep = TRUE;
          /* log PWR->WAKECR2 as a wake event */
          halInternalWakeEvent |= BIT32(WAKECORE_INTERNAL_WAKE_EVENT_BIT);
        }
        
        /* only propagate across deep sleep the interrupts that are both
        enabled and possible wake sources */
        {
          uint32_t wakeSourceInterruptMask = 0;
          
          if(PWR->WAKEPBR & PWR_WAKEPxR_Px0)
          {
            wakeSourceInterruptMask |= NVIC_IxxR_IRQA;
          }
          if(PWR->WAKEPBR & PWR_WAKEPxR_Px6)
          {
            wakeSourceInterruptMask |= NVIC_IxxR_IRQB;
          }
          if(gpioWakeSel&BIT(EXTI->CR[0]))
          {
            wakeSourceInterruptMask |= NVIC_IxxR_IRQC;
          }
          if(gpioWakeSel&BIT(EXTI->CR[1]))
          {
            wakeSourceInterruptMask |= NVIC_IxxR_IRQD;
          }
          if((PWR->WAKECR1&PWR_WAKECR1_COMPA) || (PWR->WAKECR1&PWR_WAKECR1_COMPB) ||
             (PWR->WAKECR1&PWR_WAKECR1_WRAP))
          {
            wakeSourceInterruptMask |= NVIC_IxxR_SLEEPTMR;
          }
          if(PWR->WAKECR1&PWR_WAKECR1_CORE) 
          {
            wakeSourceInterruptMask |= NVIC_IxxR_DEBUG;
          }
          
          NVIC_ISERSAVED &= wakeSourceInterruptMask;
        }

        /* disable watchdog while sleeping (since we can't reset it asleep) */
        WDG_Cmd(DISABLE);
        
      /*  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 PWR->CSYSPWRUPACKCR
          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
          PWR->CSYSPWRUPACKCR and responding to a CSYSPWRUPREQ with a
          CSYSPWRUPACK at the right/safe time.*/
        PWR->CSYSPWRUPACKCR = PWR_CSYSPWRUPACKCR_INHIBIT;
        {
          /* Use a local copy of PWR->WAKECR1 to avoid warnings from the compiler
             about order of __IO accesses */
          uint32_t wakeSel = PWR->WAKECR1;
          /* stall until a wake event or CSYSPWRUPREQ/ACK clears */
          while( (PWR->CSYSPWRUPACKSR) && (!(PWR->WAKESR&wakeSel)) ) {}
          /* if there was a wake event, allow CSYSPWRUPACK and skip sleep */
          if(PWR->WAKESR&wakeSel)
          {
            PWR->CSYSPWRUPACKCR = 0x00;
            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.*/
          CLK->HSECR2 &= ~CLK_HSECR2_SW1;
          /* If DS12 needs to be forced regardless of state, clear
             PWR->DSLEEPCR2 here.  This is hugely dangerous and
             should only be done in very controlled chip tests.*/
          SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;      /* enable deep sleep */
          extern __IO 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.*/
          SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;    /* 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
             Save the value of the SLEEPTMR_CNT register immediately after
             waking up from a real sleep.  For FogBugz 11909/11920 workaround.*/
          wakeupSleepTmrCnt = SLPTMR->CNTH<<16;
          wakeupSleepTmrCnt |= SLPTMR->CNTL;
        } 
        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.*/
          __disable_irq();
        }
        
        /* 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.)*/
        SLPTMR->ISR = (SLPTMR_IER_CMPA | SLPTMR_IER_CMPB | SLPTMR_IER_WRAP);
        EXTI->PR = (EXTI_PR_IRQAP | EXTI_PR_IRQBP | EXTI_PR_IRQCP | EXTI_PR_IRQDP);
        
        /* 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 */

        CLK->SLEEPCR = CLK_SLEEPCRSAVED;
        SLPTMR->IER = SLPTMR_IERSAVED;
        MGMT_IT->IER = MGMT_IT_IERSAVED;
        EXTI->TSR[0] = EXTI_TSRSAVED_0;
        EXTI->TSR[1] = EXTI_TSRSAVED_1;
        EXTI->TSR[2] = EXTI_TSRSAVED_2;
        EXTI->TSR[3] = EXTI_TSRSAVED_3;
        CLK->HSECR1 = CLK_HSECR1SAVED;
        CLK->HSICR = CLK_HSICRSAVED;
        CLK->DITHERCR = CLK_DITHERCRSAVED;
        GPIO_DBG->PCTRACECR = GPIO_PCTRACECRSAVED;
        MEM->RAMPROTR1 = MEM_RAMPROTR1SAVED;
        MEM->RAMPROTR2 = MEM_RAMPROTR2SAVED;
        MEM->RAMPROTR3 = MEM_RAMPROTR3SAVED;
        MEM->RAMPROTR4 = MEM_RAMPROTR4SAVED;
        MEM->RAMPROTR5 = MEM_RAMPROTR5SAVED;
        MEM->RAMPROTR6 = MEM_RAMPROTR6SAVED;
        MEM->RAMPROTR7 = MEM_RAMPROTR7SAVED;
        MEM->RAMPROTR8 = MEM_RAMPROTR8SAVED;
        MEM->RAMCR = MEM_RAMCRSAVED;
        NVIC->ISER[0] = NVIC_ISERSAVED;
        SCB->VTOR = SCB_VTORSAVED;
        
        /* PWR->WAKECR2/NVIC_IxxR_DEBUG and INT_IRQx is cleared by NVIC->ICPR[0] below */
        NVIC->ICPR[0] = 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*/
        uint32_t GPIO_IN_NEW =   GPIOA->IDR;
               GPIO_IN_NEW |= (GPIOB->IDR<<8);
               GPIO_IN_NEW |= (GPIOC->IDR<<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 __IO values.)*/
        uint32_t powerUpEvents = PWR->WAKESR;
               powerUpEvents &= PWR->WAKECR1;
        halInternalWakeEvent |= ((GPIO_IN_SAVED^GPIO_IN_NEW)&gpioWakeSel);
        /* PWR_WAKESR_SC1 is PB2 which is bit 10 */
        halInternalWakeEvent |= (!!(powerUpEvents&PWR_WAKESR_SC1))<<((1*8)+2);
        /* PWR_WAKESR_SC2 is PA2 which is bit 2 */
        halInternalWakeEvent |= (!!(powerUpEvents&PWR_WAKESR_SC2))<<((0*8)+2);
        /* PWR_WAKESR_IRQD is chosen by EXTI->CR[1] */
        halInternalWakeEvent |= (!!(powerUpEvents&PWR_WAKESR_IRQD))<<(EXTI->CR[1]);
        halInternalWakeEvent |= ((powerUpEvents & 
                                  (PWR_WAKESR_CSYSPWRRUPREQ  |
                                   PWR_WAKESR_CPWRRUPREQ  |
                                   PWR_WAKESR_CORE      |
                                   PWR_WAKESR_WRAP  |
                                   PWR_WAKESR_COMPB |
                                   PWR_WAKESR_COMPA ))
                                          <<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.*/
        __enable_irq();
        
        /* wake events are saved and interrupts are back on track,
           disable gpio freeze */
        PWR->DSLEEPCR1 = 0x00;
        
        /* 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) 
        {
          WDG_Cmd(ENABLE);
        }
        
        /* Pend any interrupts associated with deep sleep wake sources.  The
           restoration of NVIC->ISER[0] above and the changing of BASEPRI below
           is responsible for proper dispatching of interrupts at the end of
           halSleepWithOptions.*/

        /* The PWR->WAKECR2 wake source triggers a Debug Interrupt. If NVIC_IxxR_DEBUG
           interrupt is enabled and PWR->WAKECR2 is a wake event, then pend the
           Debug interrupt (using the wake_core bit).*/
        if((NVIC->ISER[0]&NVIC_IxxR_DEBUG) &&
            (halInternalWakeEvent&BIT(WAKECORE_INTERNAL_WAKE_EVENT_BIT)))
        {
          PWR->WAKECR2 = PWR_WAKECR2_COREWAKE;
        }

        /* 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((SLPTMR->IER&SLPTMR_IER_CMPA) &&
            (halInternalWakeEvent&BIT(CMPA_INTERNAL_WAKE_EVENT_BIT)))
        {
          SLPTMR->IFR = SLPTMR_IER_CMPA;
        }

        /* 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((SLPTMR->IER&SLPTMR_IER_CMPB) &&
            (halInternalWakeEvent&BIT(CMPB_INTERNAL_WAKE_EVENT_BIT)))
        {
          SLPTMR->IFR = SLPTMR_IER_CMPB;
        }

        /* 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((SLPTMR->IER&SLPTMR_IER_WRAP) &&
            (halInternalWakeEvent&BIT(WRAP_INTERNAL_WAKE_EVENT_BIT)))
        {
          SLPTMR->IFR = SLPTMR_IER_WRAP;
        }

        /* 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(((EXTI->TSR[0]&EXTI_TSR_INTMOD)!=0) && (halInternalWakeEvent&BIT(PORTB_PIN(0))))
        {
          NVIC->ISPR[0] = NVIC_IxxR_IRQA;
        }
        /* If the IRQB interrupt mode is enabled and IRQB (PB6) is wake
           event, then pend the interrupt. */
        if(((EXTI->TSR[1]&EXTI_TSR_INTMOD)!=0) && (halInternalWakeEvent&BIT(PORTB_PIN(6))))
        {
          NVIC->ISPR[0] = NVIC_IxxR_IRQB;
        }
        /* If the IRQC interrupt mode is enabled and IRQC (EXTI->CR[0]) is wake
           event, then pend the interrupt. */
        if(((EXTI->TSR[2]&EXTI_TSR_INTMOD)!=0) && (halInternalWakeEvent&BIT(EXTI->CR[0])))
        {
          NVIC->ISPR[0] = NVIC_IxxR_IRQC;
        }
        /* If the IRQD interrupt mode is enabled and IRQD (EXTI->CR[1]) is wake
           event, then pend the interrupt. */
        if(((EXTI->TSR[3]&EXTI_TSR_INTMOD)!=0) && (halInternalWakeEvent&BIT(EXTI->CR[1])))
        {
          NVIC->ISPR[0] = NVIC_IxxR_IRQD;
        }

        /* Due to FogBugz 11909/11920, SLEEPTMR_CNT may not have updated yet so
           we must ensure that the CNT register updates before returning.  It's
           only necessary to wait for the CNT to update when we've gone to
           sleep, the SLEEPTMR is enabled, and the sleep mode used a timer.
           This code could delay for up to 1ms, but will return as soon as it
           can.  In the situation where the chip slept for a known amount of
           time, this code will not delay and instead the system timer will
           report a fake, but accurate time.*/
        if((!skipSleep) && (SLPTMR->CR&SLPTMR_CR_EN) &&
           (CLK->SLEEPCR&CLK_SLEEPCR_LSI10KEN) && (sleepMode!=SLEEPMODE_NOTIMER))
        {
          uint32_t currSleepTmrCnt;
          
         #ifdef BUG11909_WORKAROUND_C
          /* THIS WORKAROUND IS NOT PROVEN 100% RELIABLE.  THIS SHOULD NOT BE
             USED UNTIL IT IS PROVEN PERFECTLY RELIABLE.
             This workaround attempts to force the SLEEPTMR_CNT to tick sooner
             than normal.  It does so by toggling between the clock sources
             to get the CNT to increment.  There is a chance the SLEEPTMR_CNT
             could become random doing this! */
          {
            currSleepTmrCnt = SLPTMR->CNTH<<16;
            currSleepTmrCnt |= SLPTMR->CNTL;
            if(currSleepTmrCnt == wakeupSleepTmrCnt) {
              uint32_t GPIOC_ODRSAVED = GPIOC->ODR;
              uint32_t GPIOC_CRHSAVED = GPIOC->CRH;
              uint32_t SLPTMR_CRSAVED = SLPTMR->CR;
              /* It is not necessary to do anything with CLK->SLEEPCR.*/
              GPIOC->BSR = GPIO_BSR_BS7;
              SET_REG_FIELD(GPIOC->CRH, GPIO_BSR_BS7, GPIO_Mode_OUT_PP, 12);
              do {
                /* Toggling between RC/XTAL will produce a clock edge
                   into the timer and cause CNT to increment.*/
                SLPTMR->CR ^= SLPTMR_CR_CLKSEL;
                currSleepTmrCnt = SLPTMR->CNTH<<16;
                currSleepTmrCnt |= SLPTMR->CNTL;
              } while(currSleepTmrCnt == wakeupSleepTmrCnt);
              GPIOC->ODR = GPIOC_ODRSAVED;
              GPIOC->CRH = GPIOC_CRHSAVED;
              SLPTMR->CR = SLPTMR_CRSAVED;
              forceSleepTmrCnt = FALSE;
            }
          }
          #endif /* BUG11909_WORKAROUND_C */
          
          /* Knowing that halSleepTimerIsr is about to be taken (when
             interrupts get enabled) tells us that the chip woke up due
             to the timer and therefore sleepTmrArtificalCnt is valid
             and needs to be forced.  This allows us to bypass delaying
             for SLEEPTMR_CNT to tick forward.  For FogBugz 11909/11920
             workaround.*/
          if((NVIC->ISER[0]&NVIC_IxxR_SLEEPTMR) && (NVIC->ISPR[0]&NVIC_IxxR_SLEEPTMR)) {
            /* sleepTmrArtificalCnt was set before sleeping
               by halSleepForQuarterSeconds */
            forceSleepTmrCnt = TRUE;
          } else {
            uint16_t us = 1000;
            uint32_t beginTime;
            forceSleepTmrCnt = FALSE;
            /* It is possible to be in a situation where the SLEEPTMR is no
               longer ticking (32k XTAL issues).  To guard against getting
               stuck in this loop, use the MAC Timer to timeout after 1ms (since
               that is the maximum time this loop would normally delay for).*/
            MACTMR->CR |= MACTMR_CR_EN;
            if((CLK->HSECR2&CLK_HSECR2_SW1)!=CLK_HSECR2_SW1) {
              us >>= 1;
            }
            beginTime = MACTMR->CNTR;
            do{
              currSleepTmrCnt = SLPTMR->CNTH<<16;
              currSleepTmrCnt |= SLPTMR->CNTL;
            }while((currSleepTmrCnt == wakeupSleepTmrCnt) &&
                   (((MACTMR->CNTR - beginTime)&MACTMR_CNTR_CNT) < us));
          }
        }
      }
void gfxSemSignal(gfxSem *psem) {
	INTERRUPTS_OFF();
	gfxSemSignalI(psem);
	INTERRUPTS_ON();
}
void gfxSystemLock(void) {
	INTERRUPTS_OFF();
}
Esempio n. 8
0
/*******************************************************************************
* Function Name  : Reset_Handler
* Description    : This is the code that gets called when the processor first starts execution
*		       following a reset event.  Only the absolutely necessary set is performed,
*		       after which the application supplied main() routine is called. 
* Input          :
* Output         :
* Return         :
*******************************************************************************/
void Reset_Handler(void)
{
  //Ensure there is enough margin on VREG_1V8 for stable RAM reads by
  //setting it to a code of 6.  VREG_1V2 can be left at its reset value.
  VREG = 0x00000307;
  
  // This code should be careful about the use of local variables in case the
  // reset type happens to be a deep sleep reset.  If the reset is not from
  // deep sleep, then locals can be freely used

  //When the Cortex-M3 exits reset, interrupts are enable.  Explicitely
  //disable them immediately using the standard set PRIMASK instruction.
  //Injecting an assembly instruction this early does not effect optimization.
  asm("CPSID i");

  //It is quite possible that when the Cortex-M3 begins executing code the
  //Core Reset Vector Catch is still left enabled.  Because this VC would
  //cause us to halt at reset if another reset event tripped, we should
  //clear it as soon as possible.  If a debugger wants to halt at reset,
  //it will set this bit again.
  DEBUG_EMCR &= ~DEBUG_EMCR_VC_CORERESET;

  //Configure flash access for optimal current consumption early
  //during boot to save as much current as we can.
  FLASH_ACCESS = (FLASH_ACCESS_PREFETCH_EN          |
                  (1<<FLASH_ACCESS_CODE_LATENCY_BIT));

  ////---- Always Configure Interrupt Priorities ----////
  //The STM32W support 5 bits of priority configuration.
  //  The cortex allows this to be further divided into preemption and a
  //  "tie-breaker" sub-priority.
  //We configure a scheme that allows for 3 bits (8 values) of preemption and
  //   2 bits (4 values) of tie-breaker by using the value 4 in PRIGROUP.
  //The value 0x05FA0000 is a special key required to write to this register.
  SCS_AIRCR = (0x05FA0000 | (4 <<SCS_AIRCR_PRIGROUP_BIT));
    
  //A few macros to help with interrupt priority configuration.  Really only 
  //  uses 6 of the possible levels, and ignores the tie-breaker sub-priority
  //  for now.
  //Don't forget that the priority level values need to be shifted into the
  //  top 5 bits of the 8 bit priority fields. (hence the <<3)
  //
  // NOTE: The ATOMIC and DISABLE_INTERRUPTS macros work by setting the 
  //       current priority to a value of 12, which still allows CRITICAL and 
  //       HIGH priority interrupts to fire, while blocking MED and LOW.
  //       If a different value is desired, spmr.s79 will need to be edited.
  #define CRITICAL (0  <<3)
  #define HIGH     (8  <<3)
  #define MED      (16 <<3)
  #define LOW      (28 <<3)
  #define NONE     (31 <<3)

  //With optimization turned on, the compiler will indentify all the values
  //and variables used here as constants at compile time and will truncate
  //this entire block of code to 98 bytes, comprised of 7 load-load-store
  //operations.
                    //vect00 is fixed                        //Stack pointer
                    //vect01 is fixed                        //Reset Vector
                    //vect02 is fixed                        //NMI Handler
                    //vect03 is fixed                        //Hard Fault Handler
  SCS_SHPR_7to4   = ((CRITICAL <<SCS_SHPR_7to4_PRI_4_BIT) |  //Memory Fault Handler 
                     (CRITICAL <<SCS_SHPR_7to4_PRI_5_BIT) |  //Bus Fault Handler
                     (CRITICAL <<SCS_SHPR_7to4_PRI_6_BIT) |  //Usage Fault Handler
                     (NONE <<SCS_SHPR_7to4_PRI_7_BIT));      //Reserved
  SCS_SHPR_11to8  = ((NONE <<SCS_SHPR_11to8_PRI_8_BIT)  |    //Reserved
                     (NONE <<SCS_SHPR_11to8_PRI_9_BIT)  |    //Reserved
                     (NONE <<SCS_SHPR_11to8_PRI_10_BIT) |    //Reserved
                     (HIGH <<SCS_SHPR_11to8_PRI_11_BIT));    //SVCall Handler
  SCS_SHPR_15to12 = ((MED  <<SCS_SHPR_15to12_PRI_12_BIT) |   //Debug Monitor Handler
                     (NONE <<SCS_SHPR_15to12_PRI_13_BIT) |   //Reserved
                     (HIGH <<SCS_SHPR_15to12_PRI_14_BIT) |   //PendSV Handler
                     (MED  <<SCS_SHPR_15to12_PRI_15_BIT));   //SysTick Handler
  NVIC_IPR_3to0   = ((MED  <<NVIC_IPR_3to0_PRI_0_BIT) |      //Timer 1 Handler
                     (MED  <<NVIC_IPR_3to0_PRI_1_BIT) |      //Timer 2 Handler
                     (HIGH <<NVIC_IPR_3to0_PRI_2_BIT) |      //Management Handler
                     (MED  <<NVIC_IPR_3to0_PRI_3_BIT));      //BaseBand Handler
  NVIC_IPR_7to4   = ((MED  <<NVIC_IPR_7to4_PRI_4_BIT) |      //Sleep Timer Handler
                     (MED  <<NVIC_IPR_7to4_PRI_5_BIT) |      //SC1 Handler
                     (MED  <<NVIC_IPR_7to4_PRI_6_BIT) |      //SC2 Handler
                     (MED  <<NVIC_IPR_7to4_PRI_7_BIT));      //Security Handler
  NVIC_IPR_11to8  = ((MED  <<NVIC_IPR_11to8_PRI_8_BIT)  |    //MAC Timer Handler
                     (MED  <<NVIC_IPR_11to8_PRI_9_BIT)  |    //MAC TX Handler
                     (MED  <<NVIC_IPR_11to8_PRI_10_BIT) |    //MAC RX Handler
                     (MED  <<NVIC_IPR_11to8_PRI_11_BIT));    //ADC Handler
  NVIC_IPR_15to12 = ((MED  <<NVIC_IPR_15to12_PRI_12_BIT) |   //GPIO IRQA Handler
                     (MED  <<NVIC_IPR_15to12_PRI_13_BIT) |   //GPIO IRQB Handler
                     (MED  <<NVIC_IPR_15to12_PRI_14_BIT) |   //GPIO IRQC Handler
                     (MED  <<NVIC_IPR_15to12_PRI_15_BIT));   //GPIO IRQD Handler
  NVIC_IPR_19to16 = ((LOW  <<NVIC_IPR_19to16_PRI_16_BIT));   //Debug Handler
                    //vect33 not implemented
                    //vect34 not implemented
                    //vect35 not implemented

  ////---- Always Configure System Handlers Control and Configuration ----////
  SCS_CCR = SCS_CCR_DIV_0_TRP_MASK;
  SCS_SHCSR = ( SCS_SHCSR_USGFAULTENA_MASK
                | SCS_SHCSR_BUSFAULTENA_MASK
                | SCS_SHCSR_MEMFAULTENA_MASK );


  if((RESET_EVENT&RESET_DSLEEP) == RESET_DSLEEP) {
    //Since the 13 NVIC registers above are fixed values, they are restored
    //above (where they get set anyways during normal boot sequences) instead
    //of inside of the halInternalSleep code:

    void halTriggerContextRestore(void);
    extern volatile boolean halPendSvSaveContext;
    halPendSvSaveContext = 0;       //0 means restore context
    SCS_ICSR |= SCS_ICSR_PENDSVSET; //pend halPendSvIsr to enable later
    halTriggerContextRestore();     //sets MSP, enables interrupts
    //if the context restore worked properly, we should never return here
    while(1) { ; }
  }

  INTERRUPTS_OFF();
  asm("CPSIE i");

  /*==================================*/
  /* Choose if segment initialization */
  /* should be done or not.           */
  /* Return: 0 to omit seg_init       */
  /*         1 to run seg_init        */
  /*==================================*/
  //return 1;
  unsigned long *pulSrc, *pulDest;

  //
  // Copy the data segment initializers from flash to SRAM.
  //
  pulSrc = &_sidata;
  for(pulDest = &_sdata; pulDest < &_edata; )
    {
      *(pulDest++) = *(pulSrc++);
    }
  
  //
  // Zero fill the bss segment.
  //
  for(pulDest = &_sbss; pulDest < &_ebss; )
    {
      *(pulDest++) = 0;
    }
  
  //
  // Call the application's entry point.
  //
  main();
}
Esempio n. 9
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);
    }
}