*
*/
-module McuSleepC {
+module McuSleepC @safe() {
provides {
interface McuSleep;
interface McuPowerState;
mcu_power_t powerState = MSP430_POWER_ACTIVE;
/* Note that the power values are maintained in an order
- * based on their active components, NOT on their values.
- * Look at atm128hardware.h and page 42 of the ATmeg128
- * manual (figure 17).*/
+ * based on their active components, NOT on their values.*/
// NOTE: This table should be in progmem.
const uint16_t msp430PowerBits[MSP430_POWER_LPM4 + 1] = {
0, // ACTIVE
};
mcu_power_t getPowerState() {
- mcu_power_t pState = MSP430_POWER_LPM3;
+ mcu_power_t pState = MSP430_POWER_LPM4;
// TimerA, USART0, USART1 check
if ((((TACCTL0 & CCIE) ||
(TACCTL1 & CCIE) ||
(TACCTL2 & CCIE)) &&
- ((TACTL & TASSEL_3) == TASSEL_2)) ||
- ((ME1 & (UTXE0 | URXE0)) && (U0TCTL & SSEL1)) ||
- ((ME2 & (UTXE1 | URXE1)) && (U1TCTL & SSEL1))
-#ifdef __msp430_have_usart0_with_i2c
+ ((TACTL & TASSEL_3) == TASSEL_2))
+#ifdef __MSP430_HAS_UART0__
+ || ((ME1 & (UTXE0 | URXE0)) && (U0TCTL & SSEL1))
+#endif
+#ifdef __MSP430_HAS_UART1__
+ || ((ME2 & (UTXE1 | URXE1)) && (U1TCTL & SSEL1))
+#endif
+#ifdef __MSP430_HAS_I2C__
// registers end in "nr" to prevent nesC race condition detection
|| ((U0CTLnr & I2CEN) && (I2CTCTLnr & SSEL1) &&
(I2CDCTLnr & I2CBUSY) && (U0CTLnr & SYNC) && (U0CTLnr & I2C))
#endif
)
pState = MSP430_POWER_LPM1;
- // ADC12 check
- if (ADC12CTL1 & ADC12BUSY){
- if (!(ADC12CTL0 & MSC) && ((TACTL & TASSEL_3) == TASSEL_2))
- pState = MSP430_POWER_LPM1;
- else
- switch (ADC12CTL1 & ADC12SSEL_3) {
- case ADC12SSEL_2:
- pState = MSP430_POWER_ACTIVE;
- break;
- case ADC12SSEL_3:
- pState = MSP430_POWER_LPM1;
- break;
- }
+
+#ifdef __MSP430_HAS_ADC12__
+ // ADC12 check, pre-condition: pState != MSP430_POWER_ACTIVE
+ if (ADC12CTL0 & ADC12ON){
+ if (ADC12CTL1 & ADC12SSEL_2){
+ // sample or conversion operation with MCLK or SMCLK
+ if (ADC12CTL1 & ADC12SSEL_1)
+ pState = MSP430_POWER_LPM1;
+ else
+ pState = MSP430_POWER_ACTIVE;
+ } else if ((ADC12CTL1 & SHS0) && ((TACTL & TASSEL_3) == TASSEL_2)){
+ // Timer A is used as sample-and-hold source and SMCLK sources Timer A
+ // (Timer A interrupts are always disabled when it is used by the
+ // ADC subsystem, that's why the Timer check above is not enough)
+ pState = MSP430_POWER_LPM1;
+ }
}
+#endif
+
return pState;
}
}
temp = msp430PowerBits[powerState] | SR_GIE;
__asm__ __volatile__( "bis %0, r2" : : "m" (temp) );
+ // All of memory may change at this point...
+ asm volatile ("" : : : "memory");
__nesc_disable_interrupt();
}