Reply by Hugh Molesworth●September 9, 20052005-09-09
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
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
>
>
>
Reply by Hugh Molesworth●September 9, 20052005-09-09
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
Reply by Onestone●September 9, 20052005-09-09
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
>
>
>
>
>
>
>
>
>
>
Reply by Hugh Molesworth●September 9, 20052005-09-09
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
Reply by ●September 9, 20052005-09-09
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
Reply by ●September 9, 20052005-09-09
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
>
>
>
Reply by Onestone●September 9, 20052005-09-09
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
>
>
>
>
>
>
>
>
>
>
Reply by ●September 9, 20052005-09-09
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
>
>
>
Reply by Greg Maki●September 9, 20052005-09-09
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