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.

MSP430G2231 TAIV keeps resetting

Other Parts Discussed in Thread: MSP430F2274, MSP430F2410

It is clear in sample code and explanation that we can use TAIV to recognize the source of timer interrupt, ie. capture/compare or timer overflow. Tried several times, and found that TAIV always reset to zero in its Interrupt Service Routine. So the following code does not work.

>>  // Timer A1 interrupt service routine  #pragma vector=TIMERA1_VECTOR 

>> __interrupt void Timer_A1 (void){


>>  switch (TAIV) {

>>  case TAIV_TAIFG:

>>  Event |= ev_timer;

>>  break;

>>  default:

>>  break;

>>  }


Any other techniques like copying TAIV to variable, also did not work. Debugging with Code Composer Studio, reveals that after step executing just one assembly line code in Timer ISR, TAIV is reset from 0x000A to 0x0000, which make it useless.

Please find attached screen capture. I am not sure what had gone wrong.

  • Hi Poh,

    would you pls test it doing it that way (for TA1 with 3 CCR registers i.e. like MSP430F2274):

    #pragma vector=TIMER1_A1_VECTOR

    __interrupt void TIMER1_A1_ISR(void)




        case  0: break;                          // No interrupt

        case  2: break;                          // CCR1 not used

        case  4: break;                          // CCR2 not used

        case  6: break;                          // reserved

        case  8: break;                          // reserved

        case 10: break;                          // reserved

        case 12: break;                          // reserved

        case 14: break;                 // overflow not used

        default: break; 



  • Have you tried not watching TAIV in the debugger?  When the debugger reads TAIV to show it to you, it's just like your ISR reading TAIV as far as Timer A is concerned.


  • Hi aBUGS,

    Your code was tried on MSP430F2274 and it works.

    Enable interrupt CCIE for CCTL1 and CCTL2, and of course TAIE.

    It ends up with three queued values in TAIV (2,4,10) and it correctly change whenever executing the code mov taiv,r15.

    Hence, no problem with MSP430F2410.

    In G2231's TAIV, queueing but uncorrectly changed on every code it pass until reset. I still do not understand what happen? Is there a workaround? Can I used the same code that you suggested for G2231?

  • Hi Jeff,

    If I do not watch the TAIV, is there another way to make sure that the code is executing correctly and the right value is moved?

    Using the downloaded code from TI, sample code: msp430g2xx1_ta_04.c 2.

    The first statement in the interrupt is the switch (TAIV) statement.

    TI compiler here translates that switch statement into several assembly codes:

    - Firstly PUSH R15, which save R15 before copying TAIV, right?

    - Secondly JUMP,

    - Thirdly after jump,  MOV.W TAIV,R15 which copy TAIV to R15.


    So, what happened is, at the first statement PUSH R15, suddenly, unexpectedly, TAIV begin to change.

    In this sample code ta_04.c it reset to zero; in other code (as in my pdf) it changed from 2 to 10 and then reset to 0 at the first two line

    instructions. We haven't even access TAIV yet!!


    Arriving at the third statement, when we want to copy TAIV, it is already reset to zero.

    So R15 will not be OK, since it copies a wrong value.

    And that happened at a single C statement switch(TAIV).

    And that beats me.

    Some info on TAIV from the product family guide.


  • In CCS, close the "Timer_A2" expansion here:

    Then the debugger won't be reading TAIV after every debug stop (single step in your case).

    To debug the value, first read TAIV into a temporary (like uint16 taivCapture).  Then in CCS watch the variable taivCapture.


  • Poh Leong Ng said:
    switch (TAIV) {

    This won't work as expected. TAIV (or any other vector register) is cleared when you read it. The switch statement, however, re-reads it for every case instruction. (the classic switch statement is more or less a chain of if(){}else if(){}... statements (plus optional fallthrough). each case is an individual comparison that each time re-reads the TAIV.
    Applying the special compiler intrinsic "__even_in_range()" to the switch statement tell the compiler to only read the register once and use a jump table instead for reaching the individual case blocks. The parameter of this intrinsic is the maximum value the IV register will return, and the compiler will create a jump table of half of this size (as the generated values are always even).

    P.s.: The reading of the IV register also resets the IFG bit associated with the reported interrupt event.

  • JMG,

    Here is the disassembly for his ISR.  You can see the code only reads TAIV once.

    The problem is the debugger constantly reading TAIV at every single step before ever reaching the switch statement.

    When a register like TAIV is declared as volatile, the compiler is careful to read it only once for each right-hand usage.

    Having said all that, it is still much better to use even_in_range.


  • Yes, in this case (and here is only one case statement too) it is read only once. However, it depends on the compiler.

    The crux with the volatile keyword is that it is just a hint (like 'inline') and not a must. and it is usuallyobeyed during optimization. However, the switch statement is rather a macro expansion (and you agree, with expanding mcros, you can easily fetch a value several times even if it is written only once and volatile).

    Since there is the __even_in_range intrinsic, specifically built for these interrupt vectors, there is no reason to assume that the normal switch statement has been optimized too. And it may (even if it shouldn't) stop working with the next compiler version.

    Nevertheless, peeking with the debugger into the TAIV register is an additional access in every case and causes havoc to the program logic.