Jump to content
43oh

While(1) not Executing with Timer Interrupt


Recommended Posts

Hey all,

I've run into a peculiar problem where my main loop doesn't execute. I know my interrupt routine is executing because I can uncomment the led toggle and I can see it blink. From what I've researched thus far, I believe the issue might be that the ISR is starving the main loop from ever executing. If that is the case, I'm not sure what the solution would be. 

 

The reason I have my main loop set up this way is because I am going to need different functions executing at different intervals.

 

I'm still fairly new to MSP430 development, so any help will be appreciated!

#include <msp430g2553.h>

#define MS_TIME 1000

volatile unsigned int s_cnt = 0;
unsigned int last_cnt = 0;

int main(void) {
  WDTCTL = WDTPW + WDTHOLD;            // Stop WDT
  
  P1DIR |= BIT0 + BIT6; 	       // P1.0 and P1.6 are the red+green LEDs	
  P1OUT &= ~(BIT0 + BIT6); 	       // Both LEDs off
  
  TA0CCTL0 = CCIE;                     // Enable Timer A0 interrupts
  TA0CCR0 = 22;                        // Count limit
  TA0CTL = TASSEL_1 + MC_1;            // Timer A0 with ACLK, count UP
  
  _BIS_SR(LPM0_bits + GIE);            // Enable interrupts

  while(1) {
    if (last_cnt != s_cnt) {
      last_cnt = s_cnt;
      if (last_cnt == MS_TIME) {
        P1OUT ^= BIT6;                 // Toggle green LED
        s_cnt = 0;
      }
    }
  }
}

#pragma vector=TIMER0_A0_VECTOR        // Timer0 A0 interrupt service routine
  __interrupt void Timer0_A0 (void) {
  s_cnt++;
  //P1OUT ^= BIT6;
}
Link to post
Share on other sites
__enable_interrupt();

could be achieved by this

_BIS_SR(GIE);            // Enable interrupts

GIE is your Global Interrupt Enable bit. and now you aren't entering sleep mode, so your code will continue running.

 

 

FWIW, you probably should go to sleep in the while loop instead of spinning continually checking for a count change.

 while(1) {
   LPM0; //enter Low Power mode
      
      if (s_cnt == MS_TIME) {
        P1OUT ^= BIT6;                 // Toggle green LED
        s_cnt = 0;
      }
  }

And then you would need to add a line to your interrupt to tell the processor to stay awake when the interrupt is processed. Place this inside your interrupt.

LPM0_EXIT;
Link to post
Share on other sites

@@pabigot The capture compare flag needs to be manually reset after each ISR execution?

 

From the user guide page 11-20:
 

CCIFG0 is automatically reset when the

interrupt request was accepted according to the
interrupt scheme of the MSP430 family

 

@@greeeg Even after removing Low Power Mode I'm still getting that starvation. 

Link to post
Share on other sites

I ended up using SMCLK and increasing the capture compare register. Why this suddenly works while the ACLK didn't... I don't know. The updated code is below for reference.

#include <msp430g2553.h>

#define MS_TIME 1000

volatile unsigned int s_cnt = 0;
unsigned int last_cnt = 0;

int main(void) {
  WDTCTL = WDTPW + WDTHOLD;            // Stop WDT
  
  P1DIR |= BIT0 + BIT6; 	       // P1.0 and P1.6 are the red+green LEDs	
  P1OUT &= ~(BIT0 + BIT6); 	       // Both LEDs off
  
  TA0CCTL0 = CCIE;                     // Enable Timer A0 interrupts
  TA0CCR0 = 1000;                      // Count limit
  TA0CTL = TASSEL_2 + MC_1;            // Timer A0 with SMCLK, count UP
  
  _BIS_SR(GIE);                        // Enable interrupts

  while(1) {
    if (last_cnt != s_cnt) {
      last_cnt = s_cnt;
      if (s_cnt >= MS_TIME) {
        P1OUT ^= BIT6;                 // Toggle green LED
        s_cnt = 0;
      }
    }
  }
}

#pragma vector=TIMER0_A0_VECTOR        // Timer0 A0 interrupt service routine
  __interrupt void Timer0_A0 (void) {
  s_cnt++;
}
Link to post
Share on other sites

You mentioned that uncommenting the LED toggle in your interrupt routine worked. From your code, the frequency of this will be 1000 times quicker than when you are running it through your ISR.

 

CCR0 is set at 1000, ISR is called every 1000 clocks.

 

s_cnt is incremented once per ISR. So s_cnt will reach 1000 after 1000*1000 clocks.

 

It may have been working, but just slower than you expected, now that you switched to a quicker clock 1000 clocks happen around every second.

 

Compared to about 30 seconds for the 32khz, or if you don't have a crystal attached then ACLK runs from the VLO which runs at 12khz and would take about a minute to toggle the LED.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...