Part Number: MSP430FR6989
I am trying to make a delay function that will enter LMP3 for one hour, then exit LMP3 using the TimerA1 interrupt. No other operations should occur during this time, it is only a 1 hour delay with power saving utility. I have modified the msp430fr69xx_ta1_06.c example code. Here is my current code:
#include <msp430.h>
void delay_hour(float hour)
{
TA1CCR0 = (int)(16524 * hour); //Set count target, up to 65535, or 3.96 hours
TA1CTL |= MC__UP; //Set count mode to up (Changed from TA1CTL = MC__UP;)
__bis_SR_register(LPM3_bits | GIE); //Enter LPM3
//while((TA1CTL & TAIFG) == 0) { __no_operation(); } //Wait until count target is reached and interrupt flag turns on
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
// Configure GPIO
P1DIR |= BIT0; // LED interrupt
P1OUT |= BIT0;
PJSEL0 |= BIT4 | BIT5;
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
// Clock setup
CSCTL0_H = CSKEY >> 8; // Unlock CS registers
CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK; // Set ACLK = VLO; MCLK = DCO
CSCTL3 = DIVA__32 | DIVS__1 | DIVM__1; // Set S and M dividers to 1, ACLK to 239.75Hz
CSCTL0_H = 0; // Lock CS registers
TA1CCTL0 = CCIE; // TACCR0 interrupt enabled
TA1CCR0 = 0; // Set count target to 0 by default
// Set timer clock speed to 4.5898 ticks/s, or 16524 ticks/hour
TA1CTL = TASSEL__ACLK | MC__UP | ID__8; //Set clock source to ACLK, the count mode to stop, and the clock divider to 8
TA1EX0 = TAIDEX_7; //Set expansion clock divider to 8
__bis_SR_register(LPM3_bits | GIE); // Enter LPM3 w/ interrupt
while(1)
{
delay_hour(0.000278); //Delay for one second (0.000278hr or 4.59 ticks) for fast toggling of LED (testing purposes)
P1OUT ^= BIT0; //Toggle LED
}
}
// Timer A1 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER1_A0_VECTOR
__interrupt void Timer1_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER1_A0_VECTOR))) Timer1_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
TA1CTL |= MC__STOP; // Stop timer to prevent repeat counting (Changed from TA1CTL = MC__STOP;)
__bic_SR_register_on_exit(LPM3_bits);
}
I am running this on the MSP430FR6989 Launchpad. The P1.0 led turns on, and does not turn off. I know that the setup of ACLK with VLOCLK is working properly. I tested it by making this script which toggles the LED on and off at an approximate rate of once per second, shown here:
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
// Configure GPIO
P1DIR |= BIT0; // LED interrupt
P1OUT |= BIT0;
PJSEL0 |= BIT4 | BIT5;
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
// Clock system setup
CSCTL0_H = CSKEY >> 8; // Unlock CS registers
CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK; // Set ACLK = VLO; MCLK = DCO
CSCTL3 = DIVA__32 | DIVS__1 | DIVM__1; // Set all dividers to 1
CSCTL0_H = 0; // Lock CS registers
TA1CCTL0 = CCIE; // TACCR0 interrupt enabled
TA1CCR0 = 2; // 2 ticks or 0.44s
TA1CTL = TASSEL__ACLK | MC__UP | ID__8; //Set clock source to ACLK, the count mode to stop, and the clock divider to 8
TA1EX0 = TAIDEX_7; //Set expansion clock divider to 8
__bis_SR_register(LPM3_bits | GIE); // Enter LPM3 w/ interrupt
}
// Timer A1 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER1_A0_VECTOR
__interrupt void Timer1_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER1_A0_VECTOR))) Timer1_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
P1OUT ^= BIT0;
}
Because the clock setup and timer setup are correct, I assume my error lies within the delay function or the interrupt. The delay function sets the count and starts the timer counting up before entering LPM3. Once the count is reached, the interrupt should set the counter to stop mode to avoid the count repeating. It should then exit LPM3.
I am using a while loop in my main function. The delay function should enter LPM3, reach the timer target count in 1s, then exit LPM3. I am assuming that because the CPU is off in LPM3, the main function cannot continue to the LED toggle until LPM3 is exited. Therefore, once the timer interrupt exits LPM3, the LED will toggle and the while loop will return to the delay function. Is this assumption wrong? If so, where does the main function resume after LPM3 is exited? If it is restarting at the beginning of the main function every time it leaves LPM3, I can understand that it will never reach the LED toggle. In that case, how can I modify my delay function to have the desired result?