EmbeddedRelated.com
Forums

TAIFG

Started by Unknown September 7, 2005
alex@alex... wrote:

> The following program has been used to verify the
Timer A TAIFG operation.
> It is a modified version of
> a TI supplied sample code.
> 
<big snip>

> #include  <msp430x16x.h>
> int temp;
> void main(void)
> {
>     temp=0;
>   WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
>   P1DIR |= 0x01;                        // P1.0 output
>   CCTL0 = CCIE;                         // CCR0 interrupt enabled
>   CCR0 = 0x7fff;
>   CCR1 = 0x9000;
>   CCR2 = 0xa000;
>   TACTL = TASSEL_1 + MC_1;              // ACLK, upmode
> 
>   //_BIS_SR(LPM3_bits + GIE);             // Enter LPM3 w/ interrupt
>   _BIS_SR(GIE);
> 
>     while(1)
>     {};
> }
> 
> // Timer A0 interrupt service routine
> #pragma vector=TIMERA0_VECTOR
> __interrupt void Timer_A (void)
> {
> 
>   P1OUT ^= 0x01;
> 
>   if( (TACTL & TAIFG)== 0x0000) // count how many times we
>     temp++;                                       // do not find the
TAIFG
> set
> 
>   TACTL   &= ~TAIFG;
>   TACCTL2 &= ~CCIFG;
>   TACCTL1 &= ~CCIFG;
> }
> 

Alex,

The TAIFG is used to indicate that TimerA has overflowed. TimerA will 
never overflow since you are using the CCR0 register and the timer in UP 
mode. Every time it reaches the CCR0 value, the CCIFG will be set and 
the timer will get reset back to zero. When the the vector to TIMER_A0 
is taken, your CCIFG will get reset.

Hope this helps,

Greg

Beginning Microcontrollers with the MSP430

Did you run the program, Greg? Just try it out :)O
Alex


----- Original Message ----- 
From: "Greg Maki" <gmaki@gmak...>
To: <msp430@msp4...>
Sent: Friday, September 09, 2005 2:39 PM
Subject: Re: Fw: [msp430] TAIFG Take 3.


> alex@alex... wrote:
>
> > The following program has been used to verify the Timer A TAIFG
operation.
> > It is a modified version of
> > a TI supplied sample code.
> >
> <big snip>
>
> > #include  <msp430x16x.h>
> > int temp;
> > void main(void)
> > {
> >     temp=0;
> >   WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
> >   P1DIR |= 0x01;                        // P1.0 output
> >   CCTL0 = CCIE;                         // CCR0 interrupt enabled
> >   CCR0 = 0x7fff;
> >   CCR1 = 0x9000;
> >   CCR2 = 0xa000;
> >   TACTL = TASSEL_1 + MC_1;              // ACLK, upmode
> >
> >   //_BIS_SR(LPM3_bits + GIE);             // Enter LPM3 w/ interrupt
> >   _BIS_SR(GIE);
> >
> >     while(1)
> >     {};
> > }
> >
> > // Timer A0 interrupt service routine
> > #pragma vector=TIMERA0_VECTOR
> > __interrupt void Timer_A (void)
> > {
> >
> >   P1OUT ^= 0x01;
> >
> >   if( (TACTL & TAIFG)== 0x0000) // count how many times we
> >     temp++;                                       // do not find
the
TAIFG
> > set
> >
> >   TACTL   &= ~TAIFG;
> >   TACCTL2 &= ~CCIFG;
> >   TACCTL1 &= ~CCIFG;
> > }
> >
>
> Alex,
>
> The TAIFG is used to indicate that TimerA has overflowed. TimerA will
> never overflow since you are using the CCR0 register and the timer in UP
> mode. Every time it reaches the CCR0 value, the CCIFG will be set and
> the timer will get reset back to zero. When the the vector to TIMER_A0
> is taken, your CCIFG will get reset.
>
> Hope this helps,
>
> Greg
>
>
>
> .
>
>
> Yahoo! Groups Links
>
>
>
>
>
>
>
>
>
>
> ---
> avast! Antivirus: Inbound message clean.
> Virus Database (VPS): 0536-0, 09/05/2005
> Tested on: 9/9/2005 2:41:38 PM
> avast! - copyright (c) 1988-2005 ALWIL Software.
> http://www.avast.com
>
>
>


As my insurance companys slogan goes" We can't help but
help", even when 
the people you're trying to help are too thick headed to accept it, or 
believe it. Perhaps he's baiting me in some perverse way, who cares, 
well I do when he starts sucking others into his delusions.

alex@alex... wrote:

>>The following program has been used to verify
the Timer A TAIFG
>>    
>>
>operation.
>  
>
>>>It is a modified version of
>>>a TI supplied sample code.
>>>      
>>>
>>>      
>>>
>><big snip>
>>
>>    
>>
>>>#include  <msp430x16x.h>
>>>int temp;
>>>void main(void)
>>>{
>>>    temp=0;
>>>  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
>>>  P1DIR |= 0x01;                        // P1.0 output
>>>  CCTL0 = CCIE;                         // CCR0 interrupt enabled
>>>  CCR0 = 0x7fff;
>>>
1 second roll over with a watch crystal in Up Mode

>>>			
>>>  CCR1 = 0x9000;
>>>  CCR2 = 0xa000;
>>>
Pointless values since the timer rolls over to 0000 from 7FFF it can 
never reach these values.

>>>  TACTL = TASSEL_1 + MC_1;              //
ACLK, upmode
>>>
UP MODE is set. TAR will roll over twhen it equals 7FFF to 0000, it will 
generate a CCR0 interrupt on mathc and a TimerA overflow interrupt on 
the very next clock cycle. Not an overly useful thing to do, but TAIFG 
isn't used.

>>>  //_BIS_SR(LPM3_bits + GIE);            
// Enter LPM3 w/ interrupt
>>>  _BIS_SR(GIE);
>>>
>>>    while(1)
>>>    {};
>>>}
>>>
>>>// Timer A0 interrupt service routine
>>>#pragma vector=TIMERA0_VECTOR
>>>__interrupt void Timer_A (void)
>>>{
>>>
>>>  P1OUT ^= 0x01;
>>>
>>>  if( (TACTL & TAIFG)== 0x0000) // count how many times we
>>>    temp++;                                       // do not find
the
>>>      
>>>
>TAIFG
>  
>
>>>set
>>>
Well we won't find TAIFG set the first time around, because it sets
on 
the rollover. You should never find TACCTL1 or 2 set, and, because TAR 
has continued counting after TACCTL0 CCIFG was set to get to this ISR 
you will never have TAIFG set if MCLK = ACLK, but may see it set if MCLK 
and ACLK are asynchronous and MCLK is much faster than ACLK. And this 
behaviour will be sporadic because occasionally you will meet a 
situation where the CCR0 flag is set, and the check point in the ISR is 
reached after TAIFG gets set, while on others you will reach it before 
this point, in which case it won't be seen by your software, as The flag 
gest reset before exit from the ISR.

Cheers

Al

>>>
>>>  TACTL   &= ~TAIFG;
>>>  TACCTL2 &= ~CCIFG;
>>>  TACCTL1 &= ~CCIFG;
>>>}
>>>
>>>      
>>>
>>Alex,
>>
>>The TAIFG is used to indicate that TimerA has overflowed. TimerA will
>>never overflow since you are using the CCR0 register and the timer in UP
>>mode. Every time it reaches the CCR0 value, the CCIFG will be set and
>>the timer will get reset back to zero. When the the vector to TIMER_A0
>>is taken, your CCIFG will get reset.
>>
>>Hope this helps,
>>
>>Greg
>>
>>
>>
>>.
>>
>>
>>Yahoo! Groups Links
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>---
>>avast! Antivirus: Inbound message clean.
>>Virus Database (VPS): 0536-0, 09/05/2005
>>Tested on: 9/9/2005 2:41:38 PM
>>avast! - copyright (c) 1988-2005 ALWIL Software.
>>http://www.avast.com
>>
>>
>>
>>    
>>
>
>
>
>
>.
>
> 
>Yahoo! Groups Links
>
>
>
> 
>
>
>
>
>  
>


Greg, I happen to think that the word "overflow" is missused here
TAIFG will be set anytime TAR is zero. This means that one clock
after the count reaches CCR0 the TAR is reset to zero thus setting the
TAIFG! This much is clear. But now an other  problem occurs.
I can not see the CCIFG set although TAR is equal to CCR0!
And so, I am full circle where I started :(

I can see the timing drawing in the UM whereCCIG is depicted as a
very narrow pulse, much smaller that a clock cycle. Is this meaning
that CCIFG is reset immediately and I really can not see it set once
in the ISR. If this is so, why describe it as a user accessible flag?

Alex.





----- Original Message ----- 
From: "Greg Maki" <gmaki@gmak...>
To: <msp430@msp4...>
Sent: ay, September 09, 2005 2:39 PM
Subject: Re: Fw: [msp430] TAIFG Take 3.
> 
> The TAIFG is used to indicate that TimerA has overflowed. TimerA will 
> never overflow since you are using the CCR0 register and the timer in UP 
> mode. Every time it reaches the CCR0 value, the CCIFG will be set and 
> the timer will get reset back to zero. When the the vector to TIMER_A0 
> is taken, your CCIFG will get reset.
> 
> Hope this helps,
> 
> Greg
> 
> 
> 
> .
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  
> 
> 
> 
> 
> 
> 
> ---
> avast! Antivirus: Inbound message clean.
> Virus Database (VPS): 0536-0, 09/05/2005
> Tested on: 9/9/2005 2:41:38 PM
> avast! - copyright (c) 1988-2005 ALWIL Software.
> http://www.avast.com
> 
> 
> 

Greg,
I am starting to think that the docs should be annotated as follows:

"Timer A in Up Mode uses a single dedicated Vector to witch the ISR jumps
when CCR0 ==  TAR.
No IFG are available during ISR execution."

This would have been much more simple!

Is this a good synthesis of the much discussed problem?
Alex


The best way to test it is using the interrupt handler itself. It
isn't 
immediately obvious, but in "up" mode you generate 2 interrupts. One
when 
TAR reaches CCR0 (ie TACCR0 IFG) and one when the timer overflows from CCR0 
to 0 (ie TAIFG). This means you can use either interrupt, but it is usual 
in this case to disable the TAIFG via TAIE since TACCR0 is faster to 
process. If they are both left enabled - this is a common mistake - you get 
a spurious TAIFG interrupt which in fact does nothing other than cause an 
interrupt - every single time TAR rolls over from CCR0 to 0. This of course 
wastes power.

Note the use of the intermediary LocalTAIV variable; this allows multiple 
interrupts to be processed within one interrupt function overhead, should 
such a situation ever occur. That does not include the TACCR0 interrupt, 
which as you note has a separate vector. This doesn't actually help much, 
unless you expect interrupts close together, since it means all interrupts 
then have the additional overhead of first latching this value. However, it 
can stop you missing such an event entirely, since the first read of TAIV 
clears all the interrupt flags. A line such as "if (TAIV & mask)
,,," 
therefore clears all the flags currently set, but you only get to process 
just one of them.

Here is a typical interrupt handler pair for Timer_A. Note how the TAIE bit 
is cleared in case it ever happens as a precaution, since our real code is 
in the other handler.

Initialise:

This is a mistake, but try it:
    // Select ACLK in continuous up mode with overflow interrupt enabled
    TACTL = TASSEL0 | MC_1 | TAIE;
This is what we really wanted:
    // Select ACLK in continuous up mode with overflow interrupt disabled
    TACTL = TASSEL0 | MC_1;

    CCTL0 = CCIE;   // Enable CCR0 interrupt
    CCR1 = Trip_1;
    CCTL1 = CCIE;
    CCR2 = Trip_2;
    CCTL2 = CCIS0 | CCIE;

// 0xFFF2 Timer A CC0

void isr_timerA_cc0(void) __interrupt[TIMERA0_VECTOR]
{
/*
  * Timer A0 interrupt
  *
  * TimerA Up Mode
  * =============  * The up mode is used if the timer period must be different
from 0FFFFh
  * counts.
  * The timer repeatedly counts up to the value of compare register TACCR0,
  * which defines the period. The number of timer counts in the period is
  * TACCR0+1. When the timer value equals TACCR0 the timer restarts
  * counting from zero. If up mode is selected when the timer value is
  * greater than TACCR0, the timer immediately restarts counting from zero.
  *
  * The TACCR0 CCIFG interrupt flag is set when the timer equals the TACCR0
  * value. The TAIFG interrupt flag is set when the timer counts from TACCR0 to
  * zero.
  */

    // blah blah
    LPM3_EXIT;        // Exit Low Power Mode 3
}

// 0xFFF0 Timer A3 CC1-2, TA

void isr_timerA_cc1_2(void) __interrupt[TIMERA1_VECTOR]
/*
  * Timer A3 interrupts
  *
  * The TAIFG interrupt flag is set in up mode when the timer counts from 
TACCR0
  * to zero.
  */
{
    uint16 LocalTAIV;

    // Only read TAIV once per interrupt action within the switch since the
    // read of the register clears the hardware flags
    while (LocalTAIV = TAIV)
    {
       switch(LocalTAIV)          // Timer A Interrupt Vector Word
       {
       default:
       case 0:       // no interrupt ready
          // blah blah
          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
          break;

       case 2:       // CCR1 - ADC time-to-read interrupt
          // blah blah
          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
          break;

       case 4:       // CCR2 - RTC interrupt, typically every 1 second
          // blah blah
          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
          break;

       case 10:      // TAIFG
          NaughtyNaughty++;
          TACTL &= ~TAIE;         // Disable timer A overflow interrupt to 
reduce power
          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
          break;
       }
    }
}

Hugh


At 15:59 09/09/2005 -0400, you wrote:

Greg, I happen to think that the word "overflow" is missused here
TAIFG will be set anytime TAR is zero. This means that one clock
after the count reaches CCR0 the TAR is reset to zero thus setting the
TAIFG! This much is clear. But now an other  problem occurs.
I can not see the CCIFG set although TAR is equal to CCR0!
And so, I am full circle where I started :(

I can see the timing drawing in the UM whereCCIG is depicted as a
very narrow pulse, much smaller that a clock cycle. Is this meaning
that CCIFG is reset immediately and I really can not see it set once
in the ISR. If this is so, why describe it as a user accessible flag?

Alex.

----- Original Message -----
From: "Greg Maki" <gmaki@gmak...>
To: <msp430@msp4...>
Sent: ay, September 09, 2005 2:39 PM
Subject: Re: Fw: [msp430] TAIFG Take 3.
 >
 > The TAIFG is used to indicate that TimerA has overflowed. TimerA will
 > never overflow since you are using the CCR0 register and the timer in UP
 > mode. Every time it reaches the CCR0 value, the CCIFG will be set and
 > the timer will get reset back to zero. When the the vector to TIMER_A0
 > is taken, your CCIFG will get reset.
 >
 > Hope this helps,
 >
 > Greg



Hi Hugh, good post except the first read of TAIV does NOT clear all the 
pending interrupt flags. Only the highest pending one that is enabled.

Al

Hugh Molesworth wrote:

>The best way to test it is using the interrupt
handler itself. It isn't 
>immediately obvious, but in "up" mode you generate 2 interrupts.
One when 
>TAR reaches CCR0 (ie TACCR0 IFG) and one when the timer overflows from CCR0 
>to 0 (ie TAIFG). This means you can use either interrupt, but it is usual 
>in this case to disable the TAIFG via TAIE since TACCR0 is faster to 
>process. If they are both left enabled - this is a common mistake - you get 
>a spurious TAIFG interrupt which in fact does nothing other than cause an 
>interrupt - every single time TAR rolls over from CCR0 to 0. This of course 
>wastes power.
>
>Note the use of the intermediary LocalTAIV variable; this allows multiple 
>interrupts to be processed within one interrupt function overhead, should 
>such a situation ever occur. That does not include the TACCR0 interrupt, 
>which as you note has a separate vector. This doesn't actually help
much, 
>unless you expect interrupts close together, since it means all interrupts 
>then have the additional overhead of first latching this value. However, it 
>can stop you missing such an event entirely, since the first read of TAIV 
>clears all the interrupt flags. A line such as "if (TAIV & mask)
,,," 
>therefore clears all the flags currently set, but you only get to process 
>just one of them.
>
>Here is a typical interrupt handler pair for Timer_A. Note how the TAIE bit 
>is cleared in case it ever happens as a precaution, since our real code is 
>in the other handler.
>
>Initialise:
>
>This is a mistake, but try it:
>    // Select ACLK in continuous up mode with overflow interrupt enabled
>    TACTL = TASSEL0 | MC_1 | TAIE;
>This is what we really wanted:
>    // Select ACLK in continuous up mode with overflow interrupt disabled
>    TACTL = TASSEL0 | MC_1;
>
>    CCTL0 = CCIE;   // Enable CCR0 interrupt
>    CCR1 = Trip_1;
>    CCTL1 = CCIE;
>    CCR2 = Trip_2;
>    CCTL2 = CCIS0 | CCIE;
>
>// 0xFFF2 Timer A CC0
>
>void isr_timerA_cc0(void) __interrupt[TIMERA0_VECTOR]
>{
>/*
>  * Timer A0 interrupt
>  *
>  * TimerA Up Mode
>  * =============>  * The up mode is used if the timer period must be
different from 0FFFFh
>  * counts.
>  * The timer repeatedly counts up to the value of compare register TACCR0,
>  * which defines the period. The number of timer counts in the period is
>  * TACCR0+1. When the timer value equals TACCR0 the timer restarts
>  * counting from zero. If up mode is selected when the timer value is
>  * greater than TACCR0, the timer immediately restarts counting from zero.
>  *
>  * The TACCR0 CCIFG interrupt flag is set when the timer equals the TACCR0
>  * value. The TAIFG interrupt flag is set when the timer counts from TACCR0
to
>  * zero.
>  */
>
>    // blah blah
>    LPM3_EXIT;        // Exit Low Power Mode 3
>}
>
>// 0xFFF0 Timer A3 CC1-2, TA
>
>void isr_timerA_cc1_2(void) __interrupt[TIMERA1_VECTOR]
>/*
>  * Timer A3 interrupts
>  *
>  * The TAIFG interrupt flag is set in up mode when the timer counts from 
>TACCR0
>  * to zero.
>  */
>{
>    uint16 LocalTAIV;
>
>    // Only read TAIV once per interrupt action within the switch since the
>    // read of the register clears the hardware flags
>    while (LocalTAIV = TAIV)
>    {
>       switch(LocalTAIV)          // Timer A Interrupt Vector Word
>       {
>       default:
>       case 0:       // no interrupt ready
>          // blah blah
>          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>          break;
>
>       case 2:       // CCR1 - ADC time-to-read interrupt
>          // blah blah
>          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>          break;
>
>       case 4:       // CCR2 - RTC interrupt, typically every 1 second
>          // blah blah
>          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>          break;
>
>       case 10:      // TAIFG
>          NaughtyNaughty++;
>          TACTL &= ~TAIE;         // Disable timer A overflow interrupt
to 
>reduce power
>          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>          break;
>       }
>    }
>}
>
>Hugh
>
>
>At 15:59 09/09/2005 -0400, you wrote:
>
>Greg, I happen to think that the word "overflow" is missused here
>TAIFG will be set anytime TAR is zero. This means that one clock
>after the count reaches CCR0 the TAR is reset to zero thus setting the
>TAIFG! This much is clear. But now an other  problem occurs.
>I can not see the CCIFG set although TAR is equal to CCR0!
>And so, I am full circle where I started :(
>
>I can see the timing drawing in the UM whereCCIG is depicted as a
>very narrow pulse, much smaller that a clock cycle. Is this meaning
>that CCIFG is reset immediately and I really can not see it set once
>in the ISR. If this is so, why describe it as a user accessible flag?
>
>Alex.
>
>----- Original Message -----
>From: "Greg Maki" <gmaki@gmak...>
>To: <msp430@msp4...>
>Sent: ay, September 09, 2005 2:39 PM
>Subject: Re: Fw: [msp430] TAIFG Take 3.
> >
> > The TAIFG is used to indicate that TimerA has overflowed. TimerA will
> > never overflow since you are using the CCR0 register and the timer in
UP
> > mode. Every time it reaches the CCR0 value, the CCIFG will be set and
> > the timer will get reset back to zero. When the the vector to TIMER_A0
> > is taken, your CCIFG will get reset.
> >
> > Hope this helps,
> >
> > Greg
>
>
>
>
>
>.
>
> 
>Yahoo! Groups Links
>
>
>
> 
>
>
>
>
>  
>


Good point, I forgot that. The next highest interrupt gets read inside the 
while loop.

Hugh

At 08:00 10/09/2005 +0930, you wrote:
Hi Hugh, good post except the first read of TAIV does NOT clear all the
pending interrupt flags. Only the highest pending one that is enabled.

Al

Hugh Molesworth wrote:

 >The best way to test it is using the interrupt handler itself. It
isn't
 >immediately obvious, but in "up" mode you generate 2 interrupts.
One when
 >TAR reaches CCR0 (ie TACCR0 IFG) and one when the timer overflows from CCR0
 >to 0 (ie TAIFG). This means you can use either interrupt, but it is usual
 >in this case to disable the TAIFG via TAIE since TACCR0 is faster to
 >process. If they are both left enabled - this is a common mistake - you get
 >a spurious TAIFG interrupt which in fact does nothing other than cause an
 >interrupt - every single time TAR rolls over from CCR0 to 0. This of course
 >wastes power.
 >
 >Note the use of the intermediary LocalTAIV variable; this allows multiple
 >interrupts to be processed within one interrupt function overhead, should
 >such a situation ever occur. That does not include the TACCR0 interrupt,
 >which as you note has a separate vector. This doesn't actually help
much,
 >unless you expect interrupts close together, since it means all interrupts
 >then have the additional overhead of first latching this value. However, it
 >can stop you missing such an event entirely, since the first read of TAIV
 >clears all the interrupt flags. A line such as "if (TAIV & mask)
,,,"
 >therefore clears all the flags currently set, but you only get to process
 >just one of them.
 >
 >Here is a typical interrupt handler pair for Timer_A. Note how the TAIE bit
 >is cleared in case it ever happens as a precaution, since our real code is
 >in the other handler.
 >
 >Initialise:
 >
 >This is a mistake, but try it:
 >    // Select ACLK in continuous up mode with overflow interrupt enabled
 >    TACTL = TASSEL0 | MC_1 | TAIE;
 >This is what we really wanted:
 >    // Select ACLK in continuous up mode with overflow interrupt disabled
 >    TACTL = TASSEL0 | MC_1;
 >
 >    CCTL0 = CCIE;   // Enable CCR0 interrupt
 >    CCR1 = Trip_1;
 >    CCTL1 = CCIE;
 >    CCR2 = Trip_2;
 >    CCTL2 = CCIS0 | CCIE;
 >
 >// 0xFFF2 Timer A CC0
 >
 >void isr_timerA_cc0(void) __interrupt[TIMERA0_VECTOR]
 >{
 >/*
 >  * Timer A0 interrupt
 >  *
 >  * TimerA Up Mode
 >  * ============= >  * The up mode is used if the timer period must be
different from 0FFFFh
 >  * counts.
 >  * The timer repeatedly counts up to the value of compare register TACCR0,
 >  * which defines the period. The number of timer counts in the period is
 >  * TACCR0+1. When the timer value equals TACCR0 the timer restarts
 >  * counting from zero. If up mode is selected when the timer value is
 >  * greater than TACCR0, the timer immediately restarts counting from zero.
 >  *
 >  * The TACCR0 CCIFG interrupt flag is set when the timer equals the TACCR0
 >  * value. The TAIFG interrupt flag is set when the timer counts from 
TACCR0 to
 >  * zero.
 >  */
 >
 >    // blah blah
 >    LPM3_EXIT;        // Exit Low Power Mode 3
 >}
 >
 >// 0xFFF0 Timer A3 CC1-2, TA
 >
 >void isr_timerA_cc1_2(void) __interrupt[TIMERA1_VECTOR]
 >/*
 >  * Timer A3 interrupts
 >  *
 >  * The TAIFG interrupt flag is set in up mode when the timer counts from
 >TACCR0
 >  * to zero.
 >  */
 >{
 >    uint16 LocalTAIV;
 >
 >    // Only read TAIV once per interrupt action within the switch since the
 >    // read of the register clears the hardware flags
 >    while (LocalTAIV = TAIV)
 >    {
 >       switch(LocalTAIV)          // Timer A Interrupt Vector Word
 >       {
 >       default:
 >       case 0:       // no interrupt ready
 >          // blah blah
 >          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >          break;
 >
 >       case 2:       // CCR1 - ADC time-to-read interrupt
 >          // blah blah
 >          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >          break;
 >
 >       case 4:       // CCR2 - RTC interrupt, typically every 1 second
 >          // blah blah
 >          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >          break;
 >
 >       case 10:      // TAIFG
 >          NaughtyNaughty++;
 >          TACTL &= ~TAIE;         // Disable timer A overflow interrupt
to
 >reduce power
 >          // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >          break;
 >       }
 >    }
 >}
 >
 >Hugh
 >
 >
 >At 15:59 09/09/2005 -0400, you wrote:
 >
 >Greg, I happen to think that the word "overflow" is missused here
 >TAIFG will be set anytime TAR is zero. This means that one clock
 >after the count reaches CCR0 the TAR is reset to zero thus setting the
 >TAIFG! This much is clear. But now an other  problem occurs.
 >I can not see the CCIFG set although TAR is equal to CCR0!
 >And so, I am full circle where I started :(
 >
 >I can see the timing drawing in the UM whereCCIG is depicted as a
 >very narrow pulse, much smaller that a clock cycle. Is this meaning
 >that CCIFG is reset immediately and I really can not see it set once
 >in the ISR. If this is so, why describe it as a user accessible flag?
 >
 >Alex.
 >
 >----- Original Message -----
 >From: "Greg Maki" <gmaki@gmak...>
 >To: <msp430@msp4...>
 >Sent: ay, September 09, 2005 2:39 PM
 >Subject: Re: Fw: [msp430] TAIFG Take 3.
 > >
 > > The TAIFG is used to indicate that TimerA has overflowed. TimerA will
 > > never overflow since you are using the CCR0 register and the timer in
UP
 > > mode. Every time it reaches the CCR0 value, the CCIFG will be set and
 > > the timer will get reset back to zero. When the the vector to
TIMER_A0
 > > is taken, your CCIFG will get reset.
 > >
 > > Hope this helps,
 > >
 > > Greg



Hugh, tanks.
You have posted much more information than I was looking for :)
I have a much more simple question which is:
 Are TAIFG and CCR0 IFG flags visible with the C-SPY as set when I
breakpoint on first instruction in my ISR?
This instruction is a simple "i++:"

This is ALL I need to know ;) A simple yes or no will suffice :)

Alex.



inal Message ----- 
From: "Hugh Molesworth" <nzbackpackers@nzba...>
To: <msp430@msp4...>
Sent: Friday, September 09, 2005 5:30 PM
Subject: Re: [msp430] TAIFG


> The best way to test it is using the interrupt
handler itself. It isn't
> immediately obvious, but in "up" mode you generate 2 interrupts.
One when
> TAR reaches CCR0 (ie TACCR0 IFG) and one when the timer overflows from
CCR0
> to 0 (ie TAIFG). This means you can use either
interrupt, but it is usual
> in this case to disable the TAIFG via TAIE since TACCR0 is faster to
> process. If they are both left enabled - this is a common mistake - you
get
> a spurious TAIFG interrupt which in fact does
nothing other than cause an
> interrupt - every single time TAR rolls over from CCR0 to 0. This of
course
> wastes power.
>
> Note the use of the intermediary LocalTAIV variable; this allows multiple
> interrupts to be processed within one interrupt function overhead, should
> such a situation ever occur. That does not include the TACCR0 interrupt,
> which as you note has a separate vector. This doesn't actually help
much,
> unless you expect interrupts close together, since it means all interrupts
> then have the additional overhead of first latching this value. However,
it
> can stop you missing such an event entirely, since
the first read of TAIV
> clears all the interrupt flags. A line such as "if (TAIV & mask)
,,,"
> therefore clears all the flags currently set, but you only get to process
> just one of them.
>
> Here is a typical interrupt handler pair for Timer_A. Note how the TAIE
bit
> is cleared in case it ever happens as a
precaution, since our real code is
> in the other handler.
>
> Initialise:
>
> This is a mistake, but try it:
>     // Select ACLK in continuous up mode with overflow interrupt enabled
>     TACTL = TASSEL0 | MC_1 | TAIE;
> This is what we really wanted:
>     // Select ACLK in continuous up mode with overflow interrupt disabled
>     TACTL = TASSEL0 | MC_1;
>
>     CCTL0 = CCIE;   // Enable CCR0 interrupt
>     CCR1 = Trip_1;
>     CCTL1 = CCIE;
>     CCR2 = Trip_2;
>     CCTL2 = CCIS0 | CCIE;
>
> // 0xFFF2 Timer A CC0
>
> void isr_timerA_cc0(void) __interrupt[TIMERA0_VECTOR]
> {
> /*
>   * Timer A0 interrupt
>   *
>   * TimerA Up Mode
>   * =============>   * The up mode is used if the timer period must be
different from 0FFFFh
>   * counts.
>   * The timer repeatedly counts up to the value of compare register
TACCR0,
>   * which defines the period. The number of timer
counts in the period is
>   * TACCR0+1. When the timer value equals TACCR0 the timer restarts
>   * counting from zero. If up mode is selected when the timer value is
>   * greater than TACCR0, the timer immediately restarts counting from
zero.
>   *
>   * The TACCR0 CCIFG interrupt flag is set when the timer equals the
TACCR0
>   * value. The TAIFG interrupt flag is set when
the timer counts from
TACCR0 to
>   * zero.
>   */
>
>     // blah blah
>     LPM3_EXIT;        // Exit Low Power Mode 3
> }
>
> // 0xFFF0 Timer A3 CC1-2, TA
>
> void isr_timerA_cc1_2(void) __interrupt[TIMERA1_VECTOR]
> /*
>   * Timer A3 interrupts
>   *
>   * The TAIFG interrupt flag is set in up mode when the timer counts from
> TACCR0
>   * to zero.
>   */
> {
>     uint16 LocalTAIV;
>
>     // Only read TAIV once per interrupt action within the switch since
the
>     // read of the register clears the hardware
flags
>     while (LocalTAIV = TAIV)
>     {
>        switch(LocalTAIV)          // Timer A Interrupt Vector Word
>        {
>        default:
>        case 0:       // no interrupt ready
>           // blah blah
>           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>           break;
>
>        case 2:       // CCR1 - ADC time-to-read interrupt
>           // blah blah
>           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>           break;
>
>        case 4:       // CCR2 - RTC interrupt, typically every 1 second
>           // blah blah
>           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>           break;
>
>        case 10:      // TAIFG
>           NaughtyNaughty++;
>           TACTL &= ~TAIE;         // Disable timer A overflow interrupt
to
> reduce power
>           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
>           break;
>        }
>     }
> }
>
> Hugh
>
>
> At 15:59 09/09/2005 -0400, you wrote:
>
> Greg, I happen to think that the word "overflow" is missused here
> TAIFG will be set anytime TAR is zero. This means that one clock
> after the count reaches CCR0 the TAR is reset to zero thus setting the
> TAIFG! This much is clear. But now an other  problem occurs.
> I can not see the CCIFG set although TAR is equal to CCR0!
> And so, I am full circle where I started :(
>
> I can see the timing drawing in the UM whereCCIG is depicted as a
> very narrow pulse, much smaller that a clock cycle. Is this meaning
> that CCIFG is reset immediately and I really can not see it set once
> in the ISR. If this is so, why describe it as a user accessible flag?
>
> Alex.
>
> ----- Original Message -----
> From: "Greg Maki" <gmaki@gmak...>
> To: <msp430@msp4...>
> Sent: ay, September 09, 2005 2:39 PM
> Subject: Re: Fw: [msp430] TAIFG Take 3.
>  >
>  > The TAIFG is used to indicate that TimerA has overflowed. TimerA will
>  > never overflow since you are using the CCR0 register and the timer in
UP
>  > mode. Every time it reaches the CCR0 value,
the CCIFG will be set and
>  > the timer will get reset back to zero. When the the vector to
TIMER_A0
>  > is taken, your CCIFG will get reset.
>  >
>  > Hope this helps,
>  >
>  > Greg
>
>
>
>
>
> .
>
>
> Yahoo! Groups Links
>
>
>
>
>
>
>
>
>
> ---
> avast! Antivirus: Inbound message clean.
> Virus Database (VPS): 0536-0, 09/05/2005
> Tested on: 9/9/2005 7:27:32 PM
> avast! - copyright (c) 1988-2005 ALWIL Software.
> http://www.avast.com
>
>
>


Actually I'm not sure about CCR0 IFG; TAIFG should however be visible
until 
TAIV is read. The problem here is that although you don't read TAIV before 
you break, C-Spy probably does read TAIV after the breakpoint when it 
updates it's register display, and any read of TAIV will clear TAIFG if it 
is the highest priority bit set. Does C-Spy display the latched value? Hmm. 
Question for Anders. My IAR stuff is older, since I didn't care to pay the 
update fees.

However, the work-around for TAIFG is to copy TAIV it into a register as 
below, then break. I think CCR0 IFG may be indeterminate, but of course it 
must have been set for the CCR0 interrupt to have been triggered. So any 
breakpoint which goes active inside the CCR0 interrupt indicates CCR0 IFG 
was set.

So, Yes and No.

However ... enable TAIE, disable CCR0 IE, break on i++ in interrupt 
function CCR1-2 and both will be visible, since TAIFG will be set 
(generating the interrupt) and CCR0 IFG will have been already set but 
won't generate an interrupt.

Hugh

At 19:40 09/09/2005 -0400, you wrote:
Hugh, tanks.
You have posted much more information than I was looking for :)
I have a much more simple question which is:
Are TAIFG and CCR0 IFG flags visible with the C-SPY as set when I
breakpoint on first instruction in my ISR?
This instruction is a simple "i++:"

This is ALL I need to know ;) A simple yes or no will suffice :)

Alex.



inal Message -----
From: "Hugh Molesworth" <nzbackpackers@nzba...>
To: <msp430@msp4...>
Sent: Friday, September 09, 2005 5:30 PM
Subject: Re: [msp430] TAIFG


 > The best way to test it is using the interrupt handler itself. It
isn't
 > immediately obvious, but in "up" mode you generate 2 interrupts.
One when
 > TAR reaches CCR0 (ie TACCR0 IFG) and one when the timer overflows from
CCR0
 > to 0 (ie TAIFG). This means you can use either interrupt, but it is usual
 > in this case to disable the TAIFG via TAIE since TACCR0 is faster to
 > process. If they are both left enabled - this is a common mistake - you
get
 > a spurious TAIFG interrupt which in fact does nothing other than cause an
 > interrupt - every single time TAR rolls over from CCR0 to 0. This of
course
 > wastes power.
 >
 > Note the use of the intermediary LocalTAIV variable; this allows multiple
 > interrupts to be processed within one interrupt function overhead, should
 > such a situation ever occur. That does not include the TACCR0 interrupt,
 > which as you note has a separate vector. This doesn't actually help
much,
 > unless you expect interrupts close together, since it means all interrupts
 > then have the additional overhead of first latching this value. However,
it
 > can stop you missing such an event entirely, since the first read of TAIV
 > clears all the interrupt flags. A line such as "if (TAIV & mask)
,,,"
 > therefore clears all the flags currently set, but you only get to process
 > just one of them.
 >
 > Here is a typical interrupt handler pair for Timer_A. Note how the TAIE
bit
 > is cleared in case it ever happens as a precaution, since our real code is
 > in the other handler.
 >
 > Initialise:
 >
 > This is a mistake, but try it:
 >     // Select ACLK in continuous up mode with overflow interrupt enabled
 >     TACTL = TASSEL0 | MC_1 | TAIE;
 > This is what we really wanted:
 >     // Select ACLK in continuous up mode with overflow interrupt disabled
 >     TACTL = TASSEL0 | MC_1;
 >
 >     CCTL0 = CCIE;   // Enable CCR0 interrupt
 >     CCR1 = Trip_1;
 >     CCTL1 = CCIE;
 >     CCR2 = Trip_2;
 >     CCTL2 = CCIS0 | CCIE;
 >
 > // 0xFFF2 Timer A CC0
 >
 > void isr_timerA_cc0(void) __interrupt[TIMERA0_VECTOR]
 > {
 > /*
 >   * Timer A0 interrupt
 >   *
 >   * TimerA Up Mode
 >   * ============= >   * The up mode is used if the timer period must be
different from 0FFFFh
 >   * counts.
 >   * The timer repeatedly counts up to the value of compare register
TACCR0,
 >   * which defines the period. The number of timer counts in the period is
 >   * TACCR0+1. When the timer value equals TACCR0 the timer restarts
 >   * counting from zero. If up mode is selected when the timer value is
 >   * greater than TACCR0, the timer immediately restarts counting from
zero.
 >   *
 >   * The TACCR0 CCIFG interrupt flag is set when the timer equals the
TACCR0
 >   * value. The TAIFG interrupt flag is set when the timer counts from
TACCR0 to
 >   * zero.
 >   */
 >
 >     // blah blah
 >     LPM3_EXIT;        // Exit Low Power Mode 3
 > }
 >
 > // 0xFFF0 Timer A3 CC1-2, TA
 >
 > void isr_timerA_cc1_2(void) __interrupt[TIMERA1_VECTOR]
 > /*
 >   * Timer A3 interrupts
 >   *
 >   * The TAIFG interrupt flag is set in up mode when the timer counts from
 > TACCR0
 >   * to zero.
 >   */
 > {
 >     uint16 LocalTAIV;
 >
 >     // Only read TAIV once per interrupt action within the switch since
the
 >     // read of the register clears the hardware flags
 >     while (LocalTAIV = TAIV)
 >     {
 >        switch(LocalTAIV)          // Timer A Interrupt Vector Word
 >        {
 >        default:
 >        case 0:       // no interrupt ready
 >           // blah blah
 >           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >           break;
 >
 >        case 2:       // CCR1 - ADC time-to-read interrupt
 >           // blah blah
 >           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >           break;
 >
 >        case 4:       // CCR2 - RTC interrupt, typically every 1 second
 >           // blah blah
 >           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >           break;
 >
 >        case 10:      // TAIFG
 >           NaughtyNaughty++;
 >           TACTL &= ~TAIE;         // Disable timer A overflow
interrupt to
 > reduce power
 >           // LPM3_EXIT;           // Exit Low Power Mode 3 if required
 >           break;
 >        }
 >     }
 > }
 >
 > Hugh
 >
 >
 > At 15:59 09/09/2005 -0400, you wrote:
 >
 > Greg, I happen to think that the word "overflow" is missused
here
 > TAIFG will be set anytime TAR is zero. This means that one clock
 > after the count reaches CCR0 the TAR is reset to zero thus setting the
 > TAIFG! This much is clear. But now an other  problem occurs.
 > I can not see the CCIFG set although TAR is equal to CCR0!
 > And so, I am full circle where I started :(
 >
 > I can see the timing drawing in the UM whereCCIG is depicted as a
 > very narrow pulse, much smaller that a clock cycle. Is this meaning
 > that CCIFG is reset immediately and I really can not see it set once
 > in the ISR. If this is so, why describe it as a user accessible flag?
 >
 > Alex.
 >
 > ----- Original Message -----
 > From: "Greg Maki" <gmaki@gmak...>
 > To: <msp430@msp4...>
 > Sent: ay, September 09, 2005 2:39 PM
 > Subject: Re: Fw: [msp430] TAIFG Take 3.
 >  >
 >  > The TAIFG is used to indicate that TimerA has overflowed. TimerA
will
 >  > never overflow since you are using the CCR0 register and the timer
in
UP
 >  > mode. Every time it reaches the CCR0 value, the CCIFG will be set
and
 >  > the timer will get reset back to zero. When the the vector to
TIMER_A0
 >  > is taken, your CCIFG will get reset.
 >  >
 >  > Hope this helps,
 >  >
 >  > Greg