]> oss.titaniummirror.com Git - tinyos-2.x.git/blob - tos/chips/msp430/McuSleepC.nc
Implement auto-set of SMCLK divider. SMCLK will be properly set to 1 binary
[tinyos-2.x.git] / tos / chips / msp430 / McuSleepC.nc
1 /*
2 * "Copyright (c) 2005 Stanford University. All rights reserved.
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose, without fee, and without written
6 * agreement is hereby granted, provided that the above copyright
7 * notice, the following two paragraphs and the author appear in all
8 * copies of this software.
9 *
10 * IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR
11 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
12 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
13 * IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
14 * DAMAGE.
15 *
16 * STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
19 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY
20 * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
21 * ENHANCEMENTS, OR MODIFICATIONS."
22 *
23 */
24
25 /**
26 * Implementation of TEP 112 (Microcontroller Power Management) for
27 * the MSP430. Code for low power calculation copied from older
28 * msp430hardware.h by Vlado Handziski, Joe Polastre, and Cory Sharp.
29 *
30 *
31 * @author Philip Levis
32 * @author Vlado Handziski
33 * @author Joe Polastre
34 * @author Cory Sharp
35 * @date October 26, 2005
36 * @see Please refer to TEP 112 for more information about this component and its
37 * intended use.
38 *
39 */
40
41 module McuSleepC @safe() {
42 provides {
43 interface McuSleep;
44 interface McuPowerState;
45 }
46 uses {
47 interface McuPowerOverride;
48 }
49 }
50 implementation {
51 bool dirty = TRUE;
52 mcu_power_t powerState = MSP430_POWER_ACTIVE;
53
54 /* Note that the power values are maintained in an order
55 * based on their active components, NOT on their values.*/
56 // NOTE: This table should be in progmem.
57 const uint16_t msp430PowerBits[MSP430_POWER_LPM4 + 1] = {
58 0, // ACTIVE
59 SR_CPUOFF, // LPM0
60 SR_SCG0+SR_CPUOFF, // LPM1
61 SR_SCG1+SR_CPUOFF, // LPM2
62 SR_SCG1+SR_SCG0+SR_CPUOFF, // LPM3
63 SR_SCG1+SR_SCG0+SR_OSCOFF+SR_CPUOFF, // LPM4
64 };
65
66 mcu_power_t getPowerState() {
67 mcu_power_t pState = MSP430_POWER_LPM3;
68 // TimerA, USART0, USART1 check
69 if ((((TACCTL0 & CCIE) ||
70 (TACCTL1 & CCIE) ||
71 (TACCTL2 & CCIE)) &&
72 ((TACTL & TASSEL_3) == TASSEL_2))
73 #ifdef __MSP430_HAS_UART0__
74 || ((ME1 & (UTXE0 | URXE0)) && (U0TCTL & SSEL1))
75 #endif
76 #ifdef __MSP430_HAS_UART1__
77 || ((ME2 & (UTXE1 | URXE1)) && (U1TCTL & SSEL1))
78 #endif
79 #ifdef __MSP430_HAS_I2C__
80 // registers end in "nr" to prevent nesC race condition detection
81 || ((U0CTLnr & I2CEN) && (I2CTCTLnr & SSEL1) &&
82 (I2CDCTLnr & I2CBUSY) && (U0CTLnr & SYNC) && (U0CTLnr & I2C))
83 #endif
84 )
85 pState = MSP430_POWER_LPM1;
86
87 #ifdef __MSP430_HAS_ADC12
88 // ADC12 check, pre-condition: pState != MSP430_POWER_ACTIVE
89 if (ADC12CTL0 & ADC12ON){
90 if (ADC12CTL1 & ADC12SSEL_2){
91 // sample or conversion operation with MCLK or SMCLK
92 if (ADC12CTL1 & ADC12SSEL_1)
93 pState = MSP430_POWER_LPM1;
94 else
95 pState = MSP430_POWER_ACTIVE;
96 } else if ((ADC12CTL1 & SHS0) && ((TACTL & TASSEL_3) == TASSEL_2)){
97 // Timer A is used as sample-and-hold source and SMCLK sources Timer A
98 // (Timer A interrupts are always disabled when it is used by the
99 // ADC subsystem, that's why the Timer check above is not enough)
100 pState = MSP430_POWER_LPM1;
101 }
102 }
103 #endif
104
105 return pState;
106 }
107
108 void computePowerState() {
109 powerState = mcombine(getPowerState(),
110 call McuPowerOverride.lowestState());
111 }
112
113 async command void McuSleep.sleep() {
114 uint16_t temp;
115 if (dirty) {
116 computePowerState();
117 //dirty = 0;
118 }
119 temp = msp430PowerBits[powerState] | SR_GIE;
120 __asm__ __volatile__( "bis %0, r2" : : "m" (temp) );
121 // All of memory may change at this point...
122 asm volatile ("" : : : "memory");
123 __nesc_disable_interrupt();
124 }
125
126 async command void McuPowerState.update() {
127 atomic dirty = 1;
128 }
129
130 default async command mcu_power_t McuPowerOverride.lowestState() {
131 return MSP430_POWER_LPM4;
132 }
133
134 }