I am trying to understand how everything works when the device wakes up from LPM3.5. My setup is basically reading data from a sensor and displaying that data on the LCD, using an RTC to take readings from the sensor every 10 minutes. For most of the time, the unit will be in LPM3.5 with the RTC and LCD operational using the XT1 crystal. Also, during this time in LPM3.5, I have all the GPIO that are not associated with the LCD/XT1 crystal set as an output and driven low for low power. When I wakeup from LPM3.5, I want to setup some IO ports and timers to get my sensor reading, write the value to the LCD memory, and then go back to LPM 3.5.
Reading the userguide, it seems when LOCKLPM5 is set (by entering LPM3.5), it locks the pin states AND the configurations of the RTC and LCD. From the userguide: "After wakeup from LPMx.5, the state of the I/Os and the modules connected to the RTC LDO are locked and remain unchanged until you clear the LOCKLPM5 bit in the PM5CTL0 register." The datasheet indicates that the RTC and LCD are in the "LPM3.5 domain".
Since I have all the GPIO not used in LPM3.5 set as output and low, if I want to set some IO for the sensor operation, I obviously need to change the port mapping, and thus clear the LOCKLPM5 bit. When I clear the LOCKLPM5 bit, this forces me to have to reinitialize the XT1, RTC, and LCD controller, correct? The portion from the user guide below seems to indicate I do have to reinitialize pretty much everything since a wakeup is a BOR. EDIT: It seems the RTC and LCD settings do persist after an LPM3.5 wakeup and I do not have to reinitialize them. I found an example where they didn't reinit these, and it is working fine, so that is a little confusing....
The user guide also mentions in "Wake Up From LPM3.5" "
1.4.3.3 Wake up From LPM3.5
Do the following steps after a wakeup from LPM3.5:
1. Initialize the registers of the modules connected to the RTC LDO exactly the same way as they were
configured before the device entered LPM3.5 but do not enable the interrupts.
2. Initialize the port registers exactly the same way as they were configured before the device entered
LPM3.5 but do not enable port interrupts.
3. If the LF-crystal-oscillator was used in LPM3.5 the corresponding I/Os must be configured as LFXIN
and LFXOUT. The LF-crystal-oscillator must be enabled in the clock system (see the clock system CS
chapter).
4. Clear the LOCKLPM5 bit in the PM5CTL0 register.
5. Enable port interrupts as necessary.
6. Enable module interrupts.
7. After enabling the port and module interrupts, the wake-up interrupt is serviced as a normal interrupt.
In my case, before I entered LPM3.5, I had some of the ports that are used for the sensor reading as output/low for low power. But when I wakeup to take the measurement, I will want some driven high, and a couple as an input. Do I need to set the port registers as all output/low (that aren't used for XT1 and LCD) before I then set the ports I need for the sensor reading?
I have been looking at the RTC example that displays a time on the LCD on a Launchpad board. I guess the reason this example never had to reinitialize anything when it woke up from LPM3.5 is that it never has to clear the LOCKLPM5 bit, since it is only using the RTC and LCD:
int main( void ) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer if (SYSRSTIV == SYSRSTIV_LPM5WU) // If LPM3.5 wakeup { Inc_RTC(); // Real clock PMMCTL0_H = PMMPW_H; // Open PMM Registers for write PMMCTL0_L |= PMMREGOFF_L; // and set PMMREGOFF __bis_SR_register(LPM3_bits | GIE); // Re-enter LPM3.5 } else { // Initialize GPIO pins for low power Init_GPIO(); *Seconds = 0; // Set initial time to 12:00:00 *Minutes = 0; *Hours = 12; // Configure XT1 oscillator P4SEL0 |= BIT1 | BIT2; // P4.2~P4.1: crystal pins do { CSCTL7 &= ~(XT1OFFG | DCOFFG); // Clear XT1 and DCO fault flag SFRIFG1 &= ~OFIFG; }while (SFRIFG1 & OFIFG); // Test oscillator fault flag CSCTL6 = (CSCTL6 & ~(XT1DRIVE_3)) | XT1DRIVE_2; // Higher drive strength and current consumption for XT1 oscillator // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings PM5CTL0 &= ~LOCKLPM5; // Configure RTC RTCCTL |= RTCSS__XT1CLK | RTCIE; // Initialize RTC to use XT1 and enable RTC interrupt RTCMOD = 32768; // Set RTC modulo to 32768 to trigger interrupt each second // Configure LCD pins SYSCFG2 |= LCDPCTL; // R13/R23/R33/LCDCAP0/LCDCAP1 pins selected LCDPCTL0 = 0xFFFF; LCDPCTL1 = 0x07FF; LCDPCTL2 = 0x00F0; // L0~L26 & L36~L39 pins selected LCDCTL0 = LCDSSEL_0 | LCDDIV_7; // flcd ref freq is xtclk // LCD Operation - Mode 3, internal 3.08v, charge pump 256Hz LCDVCTL = LCDCPEN | LCDREFEN | VLCD_6 | (LCDCPFSEL0 | LCDCPFSEL1 | LCDCPFSEL2 | LCDCPFSEL3); LCDMEMCTL |= LCDCLRM; // Clear LCD memory LCDCSSEL0 = 0x000F; // Configure COMs and SEGs LCDCSSEL1 = 0x0000; // L0, L1, L2, L3: COM pins LCDCSSEL2 = 0x0000; LCDM0 = 0x21; // L0 = COM0, L1 = COM1 LCDM1 = 0x84; // L2 = COM2, L3 = COM3 LCDCTL0 |= LCD4MUX | LCDON; // Turn on LCD, 4-mux selected (LCD4MUX also includes LCDSON) // Display time LCDMEM[pos1] = digit[(*Hours) / 10]; LCDMEM[pos2] = digit[(*Hours) % 10]; LCDMEM[pos3] = digit[(*Minutes) / 10]; LCDMEM[pos4] = digit[(*Minutes) % 10]; LCDMEM[pos5] = digit[(*Seconds) / 10]; LCDMEM[pos6] = digit[(*Seconds) % 10]; // Display the 2 colons LCDMEM[7] = 0x04; LCDMEM[11] = 0x04; PMMCTL0_H = PMMPW_H; // Open PMM Registers for write PMMCTL0_L |= PMMREGOFF_L; // and set PMMREGOFF __bis_SR_register(LPM3_bits | GIE); // Enter LPM3.5 __no_operation(); // For debugger } }