Colleagues,
The circuit that I'm working on is based on an 8-pin MSP430G2210. The RST#/NMI serves as a soft on/off switch. While the device is on, it will use the WDT in the interval mode for cyclic sleep (at least, that's my intent). I was able to make the NMI# interrupt work to wake up from LPM4. Separately, I was able to make the WDT interrupt work to wake up from LPM3. But I wasn't able to make them work together.
// PURPOSE: Keep track of button presses
#pragma vector=NMI_VECTOR
__interrupt void nmi_isr(void) {
g_nmiFlag = true; // set a flag, which will be examined in the main() loop
for (volatile unsigned int i = 20000; i != 0; --i); // allow some time for contact bouncing to settle
IFG1 &= ~NMIIFG; // re-clear NMI flag if there was bouncing
IE1 |= NMIIE; // enable NMI
__bic_SR_register_on_exit(LPM4_bits); // exit the LPM on return from the ISR
}
// PURPOSE: Allow cyclic wake up.
#pragma vector=WDT_VECTOR
__interrupt void wdt_isr(void) {
__bic_SR_register_on_exit(LPM3_bits); // exit the LPM on return from the ISR
}
int main(void) {
// Initialize the MSP430
P1DIR |= 0x04; // LED. Set P1.2 to output direction
P1OUT |= 0x04; // LED off
P1OUT &= ~0x20; // Make sure that sensors are powered down
P1DIR |= 0x20;
while (1) {
// Enter the Dormant state
WDTCTL = WDTPW
| WDTHOLD // WDT off
| WDTNMI // NMI (instead of reset). See section 10.3.1 in [1] and fig. 2-1 in [1].
| WDTNMIES; // NMI on falling edge
IFG1 &= ~NMIIFG; // make sure that the interrupt flag is not set
IE1 |= NMIIE; // Enable NMI
__bis_SR_register(LPM4_bits | GIE); // Enter LPM4 w/interrupt
// Button will cause the interrupt, which will end the dormant state. See NMI ISR.
g_nmiFlag = false;
// WDT is used for cyclic sleep. Set WDT to interval mode.
BCSCTL1 |= DIVA_1; // ACLK/2
BCSCTL3 |= LFXT1S_2; // ACLK = VLO
WDTCTL = WDTPW
| WDTTMSEL // WDT in interval mode
| WDTCNTCL // clear counter
| WDTSSEL // clock WDT from ACLK
| WDTNMI; // NMI (instead of reset). See section 10.3.1 in [1] and fig. 2-1 in [1].
IE1 |= WDTIE; // Enable WDT interrupt
volatile bool remainAware = true;
while (remainAware) {
__bis_SR_register(LPM3_bits | GIE); // nap
// awoken by the WDT interrupt
// <bring-up>
P1OUT &= ~0x04; // Set P1.0 LED on
for (volatile int i = 5000; i>0; i--); // Delay
P1OUT |= 0x04; // Reset P1.0 LED off
// </bring-up>
// Did user press the button to deactivate the unit?
if (g_nmiFlag == true) {
remainAware = false;
}
}
}
return 0;
}
The LED blinks only once after the NMI is created with a button. I expected that the WDT timer would make the LED blink repeatedly. What am I missing?
Any suggestion, insight or reference is really appreciated!
Cheers,
- Nick