This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F5438 Timer Interrupt Problem

Hello again.  I'm working with the MSP430F5438, and at the moment I'm trying to implement basic timer counter functionality into my system.

I've looked at the examples, and read the users guide.  I'm fairly sure that I'm following what I need to do, but it's not working.  When I get my interrupt, instead of jumping to the correct interrupt vector, it's jumping to the system reset vector, and then halting.  I haven't been able to figure out any reason for this behavior - all my registers look correct.

The code I'm using is as follows:

 

#ifndef TA0_H_

#define TA0_H_

 

void (*TA0IFunction)(void) = 0;

 

void Setup_TA0(int val, void(*IntFunc)(void))

{

  TA0IFunction = IntFunc;

  TA0CCR0 = val;

  TA0CTL = TASSEL_2 + MC_0 + TACLR + TAIE;      // SMCLK, halted, clear TAR, enable interrupt

}

 

void Enable_TA0()

{

  TA0CTL |= 0x10;                               // MC set to Up mode

}

 

void Disable_TA0()

{

  TA0CTL &= 0xEF;                               // Halt counter

  TA0CTL |= 0x04;                               // Reset timer

}

 

// Timer A0 interrupt service routine

#pragma vector=TIMER1_A0_VECTOR

__interrupt void TIMER1_A0_ISR(void)

{

  switch(__even_in_range(UCA0IV,14))

  {

  case  0:break;                             // Vector  0 - no interrupt

  case  2:break;                             // Vector  2 - CCR1

  case  4:break;                             // Vector  4 - CCR2 

  case  6:break;                             // Vector  6 - CCR3

  case  8:break;                             // Vector  8 - CCR4

  case 10:break;                             // Vector 10 - CCR5

  case 12:break;                             // Vector 12 - CCR6

  case 14:                                   // Vector 14 - CTL  - Timer Overflow

    TA0IFunction();

    break;                             

  default: break;

  }

}

#endif

The main code looks similiar to the following:
void main()
{
WDTCTL = WDTPW + WDTHOLD;          // Stop WDT
P1OUT |= 0x00;                     // Debug LED
P1DIR |= 0x01;
Setup_TA0(200, TA0Interrupt);           // 12MHz/24000 ~= 500Hz  Probably need to tweak
Enable_TA0();
_BIS_SR(GIE);
while(1);
}

The interrupt function TA0Interrupt is as follows:

 

void TA0Interrupt()

{

  P1OUT ^= 0x01;

}

 

 

The hardware I'm using is the MSP430F5438 on the MSP-TS430PZ5x100.  I'm programming and debugging through the MSP-FETU430IF.

 

According to the Users Guide and the Data Sheets, I've been looking at the following registers:

TA0 (0x0340-0x036E)

System Registers (0x019A-0x019E)

As far as I can tell, what SHOULD be happening is that when the Timer Counter crosses the threshold I've set, it should set the interrupt flag in the TA0 Interrupt Vector (0x36E) as well as the TAIFG in the TA0 Control Register (0x0340).  This appears to be happening when i step through in assembly mode.  However, instead of jumping to the Timer Interrupt Vector (0xFFE0/0xFFE2) like expected, I jump to the System Interrupt Vector (0xFFFE).

When I look at my registers, the only thing that I can see that's set in the system registers is the Reset Interrupt Vector (SYSRSTIV - 0x019E) is set to 0x000A - Security Violation.  However, I can't find any other information in the users guide as to what this actually means, or how to fix it.  As far as I can tell, it's always set - I don't actually ever see that flag BEING set, it's just set.  So I'm not sure what I could be doing to cause this, if it is the problem.

Other interrupts seem to work fine - I've setup the RTC in a similar manner, and it works just fine.  Any information on what I might be doing wrong would be greatly appreciated.

Thanks,

Ian

  • First, it is a bad idea to call fronctions from inside an ISR. It does not only add the overhead for a function call, it also hinders optimization. The called function doe snot know whether its registers have been already saved in the calling function, so you probably do unnecessary register saves to the stack, aslo the calling function does not know whether the normal function parameter registers are clobbered in the called function and therefore needs to save them too (as an ISR must ensure that all registers are restored on its exit)

    o if the code you want to execute is short, include it directly into the ISR. If it is longer code, you should not call it inside the ISR at all 8as it will block other interrupts during its execution) but rathe rset a global flag and let main() do the job.

    Ian Cyr said:
    instead of jumping to the Timer Interrupt Vector (0xFFE0/0xFFE2) like expected, I jump to the System Interrupt Vector (0xFFFE).

    This usually means that the ISR is not present at all. Then the vector of this ISR contains 0xffff and the cpu jumps to 0xfffe (LSB is discarded in the program counter).

    Maybe you confused TIMER1_A0_VECTOR and TIMER0_A1_VECTOR? (I'm not happy with this naming too. On the first MSPs, there was only one TimerA, so it was the Timer_A1 vector)

  • After looking at the data sheets more closely, I think you might be right about the Timer1_A0/Timer0_A1.  Is there a Timer1_A1 and a Timer0_A0?  If not, what does the value after the Timer indicate?

    I'll make the changes for this and see if it fixes my problem.

    Thanks.

  • Ian Cyr said:
    Is there a Timer1_A1 and a Timer0_A0?

    Yes. The TIMER1_A1 vector belongs to the combined interrupts of the TimerA1, while TIMER0_A0_VECTOR belongs to the TA0CCR0 interrupt.

    Originally, there was TIMER_A0/1_VECTOR only, as there was only one Timer_A in an MSP. Now there can be more than one Timer_A, so since the number behind the A was already occupied, the number of the timer unit is placed directly behind the word TIMER.

    An easier to unserstand naming would have been

    TIMER_A1_VECTOR_0
    for the CCR0 vector of TimerA1 and
    TIMER_A0_VECTOR_1
    or even
    TIMER_A0_1_VECTOR
    (or _A/_B) for the combined vector of TimerA0 etc. But all vector names end with "_VECTOR", so the appended 0/1 was not chosen (maybe never considered) when these vectors have been named for the first MSPs. And now we have to stay "compatible". :(

     

**Attention** This is a public forum