]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/msp430/McuSleepC.nc
Make McuSleepC smarter about newer msp430 processors.
[tinyos-2.x.git] / tos / chips / msp430 / McuSleepC.nc
index dd9f5e1767e8ddda4a1388942761d97b27bf5705..57c6d393aaefcb522c22cc0738cb56df82d14e24 100644 (file)
@@ -38,7 +38,7 @@
  *
  */
 
-module McuSleepC {
+module McuSleepC @safe() {
   provides {
     interface McuSleep;
     interface McuPowerState;
@@ -52,9 +52,7 @@ implementation {
   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
@@ -66,35 +64,44 @@ implementation {
   };
     
   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;
   }
   
@@ -111,6 +118,8 @@ implementation {
     }
     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();
   }