EmbeddedRelated.com
Forums

MSP430F149 resets during code execution

Started by Mikael Bertelsen March 31, 2010
Hi all,

I'm having a little problem with my MSP430F149 using both IAR and Code
Composer.

When running a simple program (shown below) my MSP keeps resetting. I cannot
see any changes in the SFR that could indicate anything, and my watchdog is
on hold.

My intention is to run a software RTC, mostly to play around with
interrupts. When the interrupt on TimerA triggers, a counter (RTCCount) is
incremented, and the counter can be used for something useful later on.
TimerA is sourced from a 32kHz crystal on LFXT1.

I can see that the RTCCount variable reaches 4 or 5 before the reset, and
this is done by setting a breakpoint where P1.0 is toggled (in the
IncrementRTCSeconds()-function).

And by setting a breakpoint at initClk_32khz() in main, I can see that the
MSP restarts the main (resets).

I would really appreciate any help to point me in the right direction.

Cheers,

Mike

[Code] #include // Prototype definitions void initClk_32khz(void); void initACLK(void); void initTimerA(void); void IncrementRTCSeconds(void); // Global variables volatile unsigned long RTCCount; int main(void) { RTCCount = 0; // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; initClk_32khz(); initACLK(); initTimerA(); // Enable interrupts _BIS_SR(GIE); // For debugging only. P1DIR = 0xFF; P1SEL = BIT1; while(1) { } } void initClk_32khz(void) { BCSCTL1 |= XT2OFF; // Turning off XT2 BCSCTL1 &= ~XTS; // LF-mode IFG2=0; /* reset interrupt flag register 1 */ IFG1=0; /* reset interrupt flag register 2 */ do { /*wait in loop until crystal is stable*/ IFG1&=~OFIFG; } while(OFIFG&IFG1); } void initACLK(void) { // ACLK is naturally sourced by LFXT1 // ACLK divider BCSCTL1 &= ~DIVA0; // Divide by 1 BCSCTL1 &= ~DIVA1; // Divide by 1 } void initTimerA(void) { // Reset/clear the timer TACTL |= TACLR; // Stop the timer TACCR0 = 0x0; // Selecting ACLK as clock source TACTL |= TASSEL0; TACTL &= ~TASSEL1; // Clock divider TACTL &= ~ID0; // Divide by 1 TACTL &= ~ID1; // Divide by 1 // Mode control TACTL |= MC0; // Up mode TACTL &= ~MC1; // Up mode // Compare mode TACCTL0 &= ~CAP; // Interrupts TACTL |= TAIE; // Enable TimerA interrupt TACCTL0 |= CCIE; // Compare interrupt enable // Clear the interrupt flag TACTL &= ~TAIFG; TACCTL0 &= ~CCIFG; // Start the timer TACCR0 = 32767; } void IncrementRTCSeconds(void) { RTCCount++; P1OUT ^= 0x01; // Toggle P1.0 } // Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void TimerA_interrupt (void) { IncrementRTCSeconds(); } [/Code]



Beginning Microcontrollers with the MSP430

I can't see immediately what is causing the reset, I must admit I
haven't really looked. C on micros looks so unnatural to me it's a bit
like dyslexia.

however I have a few comments, meant to be useful.

Firstly why not simply increment the RTCCount in the ISR and toggle the
bit. Calling a separate function from within the ISR is messy, and
unnecessary.

On a similar vein you are initialising peripherals one bit at a time,
much better to use a MOV and set them up in one hit. ie BSCTL1 = xyz.
(the convolute syntax in bit manipulation is one of the ugliest things
about C on embedded, ie

BSCTL1 |= XT2OFF is ugly compared to BIS.B #XT2OFF,BSCTL1
BSCTL1 &= ~XTS is even uglier compared to BIC.B #XTS,BSCTL1

but simpler than this is BSCTL1 = XT2OFF which implicitly clears XTS
while setting XT2OFF

Looking at your code again, and assuming that C does nothing 'under the
bonnet' to skirt this. The timerA0 ISR vector is a common vector shared
by TimerA1, A2 (A3 & A4 if available) and TIMER OVERFLOW. TAIV is
provided for this express purpose.

In assembler the normal form is to do the following:-

TA_ISR:

ADD &TAIV,PC ;ADDING THE VECTOR VALUE TO THE pc JUMPS TO THE
APPROPRIATE VECTOR
RETI ;0 IS A NULL PENDING INT
JMP TA_1INT ;HANDLE TA-1 INTERRUPT
JMP TA_2INT
RETI ;3 & 4 CAN'T OCCUR
RETI

/* Timer_A-0 is a 1 SEC timebase, used by the RTC only */

TA_OVF: ;DROPS HERE ON TAIV = 10
INCD &TIME ;MAINTAIN RTCC
ADDC #0,&TIME+2
XOR.B #LED,&P1OUT
RETI

from posts here I understand that people handle this in various ways,
probably a switch (anyway it'll look ugly! ;@}), but I suggest that
this is the source of your resets

Cheers

Al
Mikael Bertelsen wrote:
> Hi all,
>
>
>
> I'm having a little problem with my MSP430F149 using both IAR and Code
> Composer.
>
> When running a simple program (shown below) my MSP keeps resetting. I cannot
> see any changes in the SFR that could indicate anything, and my watchdog is
> on hold.
>
>
>
> My intention is to run a software RTC, mostly to play around with
> interrupts. When the interrupt on TimerA triggers, a counter (RTCCount) is
> incremented, and the counter can be used for something useful later on.
> TimerA is sourced from a 32kHz crystal on LFXT1.
>
> I can see that the RTCCount variable reaches 4 or 5 before the reset, and
> this is done by setting a breakpoint where P1.0 is toggled (in the
> IncrementRTCSeconds()-function).
>
> And by setting a breakpoint at initClk_32khz() in main, I can see that the
> MSP restarts the main (resets).
>
>
>
> I would really appreciate any help to point me in the right direction.
>
>
>
> Cheers,
>
> Mike
>
>
>
> [Code] > > #include > > // Prototype definitions > > void initClk_32khz(void); > > void initACLK(void); > > void initTimerA(void); > > void IncrementRTCSeconds(void); > > > > // Global variables > > volatile unsigned long RTCCount; > > > > int main(void) > > { > > RTCCount = 0; > > > > // Stop watchdog timer to prevent time out reset > > WDTCTL = WDTPW + WDTHOLD; > > > > initClk_32khz(); > > initACLK(); > > initTimerA(); > > > > // Enable interrupts > > _BIS_SR(GIE); > > > > // For debugging only. > > P1DIR = 0xFF; > > P1SEL = BIT1; > > > > while(1) > > { > > } > > } > > > > void initClk_32khz(void) > > { > > BCSCTL1 |= XT2OFF; // Turning off XT2 > > BCSCTL1 &= ~XTS; // LF-mode > > > > IFG2=0; /* reset interrupt flag register 1 */ > > IFG1=0; /* reset interrupt flag register 2 */ > > > > do { > > /*wait in loop until crystal is stable*/ > > IFG1&=~OFIFG; > > } while(OFIFG&IFG1); > > } > > > > void initACLK(void) > > { > > // ACLK is naturally sourced by LFXT1 > > > > // ACLK divider > > BCSCTL1 &= ~DIVA0; // Divide by 1 > > BCSCTL1 &= ~DIVA1; // Divide by 1 > > } > > > > void initTimerA(void) > > { > > // Reset/clear the timer > > TACTL |= TACLR; > > > > // Stop the timer > > TACCR0 = 0x0; > > > > // Selecting ACLK as clock source > > TACTL |= TASSEL0; > > TACTL &= ~TASSEL1; > > > > // Clock divider > > TACTL &= ~ID0; // Divide by 1 > > TACTL &= ~ID1; // Divide by 1 > > > > // Mode control > > TACTL |= MC0; // Up mode > > TACTL &= ~MC1; // Up mode > > > > // Compare mode > > TACCTL0 &= ~CAP; > > > > // Interrupts > > TACTL |= TAIE; // Enable TimerA interrupt > > TACCTL0 |= CCIE; // Compare interrupt enable > > > > // Clear the interrupt flag > > TACTL &= ~TAIFG; > > TACCTL0 &= ~CCIFG; > > > > // Start the timer > > TACCR0 = 32767; > > } > > > > void IncrementRTCSeconds(void) > > { > > RTCCount++; > > P1OUT ^= 0x01; // Toggle P1.0 > > } > > > > // Timer A0 interrupt service routine > > #pragma vector=TIMERA0_VECTOR > > __interrupt void TimerA_interrupt (void) > > { > > IncrementRTCSeconds(); > > } > > [/Code]
>
>
>
>
>
>
I fully agree with Al. But I have to say that Mikael's code is better than most others that I have seen.

Most of those others have no idea how the hardware works and just copy and modify certain "sample code" which they have no idea how it works either. And those "sample codes" are full of the ills that Al pointed out.

Back to Mikael. I think you enable two interrupts and have code to service only one of them. You do not need TAIE in TACTL. Or else, you have to write another ISR. I am surprised that it does not crash right away.

The way you wait for the crystal oscillator to start is not correct either. But that is not the cause of the reset.

-- OCY

--- In m..., OneStone wrote:
>
> I can't see immediately what is causing the reset, I must admit I
> haven't really looked. C on micros looks so unnatural to me it's a bit
> like dyslexia.
>
> however I have a few comments, meant to be useful.
>
> Firstly why not simply increment the RTCCount in the ISR and toggle the
> bit. Calling a separate function from within the ISR is messy, and
> unnecessary.
>
> On a similar vein you are initialising peripherals one bit at a time,
> much better to use a MOV and set them up in one hit. ie BSCTL1 = xyz.
> (the convolute syntax in bit manipulation is one of the ugliest things
> about C on embedded, ie
>
> BSCTL1 |= XT2OFF is ugly compared to BIS.B #XT2OFF,BSCTL1
> BSCTL1 &= ~XTS is even uglier compared to BIC.B #XTS,BSCTL1
>
> but simpler than this is BSCTL1 = XT2OFF which implicitly clears XTS
> while setting XT2OFF
>
> Looking at your code again, and assuming that C does nothing 'under the
> bonnet' to skirt this. The timerA0 ISR vector is a common vector shared
> by TimerA1, A2 (A3 & A4 if available) and TIMER OVERFLOW. TAIV is
> provided for this express purpose.
>
> In assembler the normal form is to do the following:-
>
> TA_ISR:
>
> ADD &TAIV,PC ;ADDING THE VECTOR VALUE TO THE pc JUMPS TO THE
> APPROPRIATE VECTOR
> RETI ;0 IS A NULL PENDING INT
> JMP TA_1INT ;HANDLE TA-1 INTERRUPT
> JMP TA_2INT
> RETI ;3 & 4 CAN'T OCCUR
> RETI
>
> /* Timer_A-0 is a 1 SEC timebase, used by the RTC only */
>
> TA_OVF: ;DROPS HERE ON TAIV = 10
> INCD &TIME ;MAINTAIN RTCC
> ADDC #0,&TIME+2
> XOR.B #LED,&P1OUT
> RETI
>
> from posts here I understand that people handle this in various ways,
> probably a switch (anyway it'll look ugly! ;@}), but I suggest that
> this is the source of your resets
>
> Cheers
>
> Al
> Mikael Bertelsen wrote:
> > Hi all,
> >
> >
> >
> > I'm having a little problem with my MSP430F149 using both IAR and Code
> > Composer.
> >
> > When running a simple program (shown below) my MSP keeps resetting. I cannot
> > see any changes in the SFR that could indicate anything, and my watchdog is
> > on hold.
> >
> >
> >
> > My intention is to run a software RTC, mostly to play around with
> > interrupts. When the interrupt on TimerA triggers, a counter (RTCCount) is
> > incremented, and the counter can be used for something useful later on.
> > TimerA is sourced from a 32kHz crystal on LFXT1.
> >
> > I can see that the RTCCount variable reaches 4 or 5 before the reset, and
> > this is done by setting a breakpoint where P1.0 is toggled (in the
> > IncrementRTCSeconds()-function).
> >
> > And by setting a breakpoint at initClk_32khz() in main,
> > I can see that the > > MSP restarts the main (resets).
> > I would really appreciate any help to point me in the
> > right direction.
> > Cheers,
> >
> > Mike
> >
> > [Code] > > #include > > // Prototype definitions > > void initClk_32khz(void); > > void initACLK(void); > > void initTimerA(void); > > void IncrementRTCSeconds(void); > > // Global variables > > volatile unsigned long RTCCount; > > int main(void) > > { > > RTCCount = 0; > > // Stop watchdog timer to prevent time out reset > > WDTCTL = WDTPW + WDTHOLD; > > initClk_32khz(); > > initACLK(); > > initTimerA(); > > // Enable interrupts > > _BIS_SR(GIE); > > // For debugging only. > > P1DIR = 0xFF; > > P1SEL = BIT1; > > while(1) > > { > > } > > } > > void initClk_32khz(void) > > { > > BCSCTL1 |= XT2OFF; // Turning off XT2 > > BCSCTL1 &= ~XTS; // LF-mode > > IFG2=0; /* reset interrupt flag register 1 */ > > IFG1=0; /* reset interrupt flag register 2 */ > > do { > > /*wait in loop until crystal is stable*/ > > IFG1&=~OFIFG; > > } while(OFIFG&IFG1); > > } > > void initACLK(void) > > { > > // ACLK is naturally sourced by LFXT1 > > // ACLK divide > > BCSCTL1 &= ~DIVA0; // Divide by 1 > > BCSCTL1 &= ~DIVA1; // Divide by 1 > > } > > void initTimerA(void) > > { > > // Reset/clear the timer > > TACTL |= TACLR; > > // Stop the timer > > TACCR0 = 0x0; > > // Selecting ACLK as clock source > > TACTL |= TASSEL0; > > TACTL &= ~TASSEL1; > > // Clock divider > > TACTL &= ~ID0; // Divide by 1 > > TACTL &= ~ID1; // Divide by 1 > > // Mode control > > TACTL |= MC0; // Up mode > > TACTL &= ~MC1; // Up mode > > // Compare mode > > TACCTL0 &= ~CAP; > > // Interrupts > > TACTL |= TAIE; // Enable TimerA interrupt > > TACCTL0 |= CCIE; // Compare interrupt enable > > // Clear the interrupt flag > > TACTL &= ~TAIFG; > > TACCTL0 &= ~CCIFG; > > // Start the timer > > TACCR0 = 32767; > > } > > void IncrementRTCSeconds(void) > > { > > RTCCount++; > > P1OUT ^= 0x01; // Toggle P1.0 > > } > > // Timer A0 interrupt service routine > > #pragma vector=TIMERA0_VECTOR > > __interrupt void TimerA_interrupt (void) > > { > > IncrementRTCSeconds(); > > } > > [/Code]

Hello Mike,

My first thought was that an interrupt is triggering that you aren't
servicing. Interrupts
without ISRs point to the reset vector. This has gotten me many times but
it's one of
the first things I look for when I see regular unexplained resets. In your
code you are servicing
TIMERA0_VECTOR (0xFFEC) but not TIMERA1_VECTOR (0xFFEA). TIMERA0 is for
TACCR0, and TIMERA1 is for CCR1,CCR2,TAIFG.

I could be wrong, and I'm not sure why RTCCount would reach 4 or 5 if this
was the case,
but could it be that when TA overflows and the TIMERA1 ISR is called you
instead jump to
reset because you don't have an ISR for it?

tl;dr: Try adding an ISR for TIMERA1_VECTOR and see if your reset goes away.

Otherwise, MSPs are really sensitive to their supply, blame the hardware!
;-)
(Then take a nap, then try to find the problem again. Then blame the
hardware again.
Rinse, repeat. This is most "effective" when you did not design the
hardware. YMMV.)

Hope this helps,

Jeff

On Wed, Mar 31, 2010 at 5:44 AM, Mikael Bertelsen wrote:

> Hi all,
>
> I'm having a little problem with my MSP430F149 using both IAR and Code
> Composer.
>
> When running a simple program (shown below) my MSP keeps resetting. I
> cannot
> see any changes in the SFR that could indicate anything, and my watchdog is
> on hold.
>
> My intention is to run a software RTC, mostly to play around with
> interrupts. When the interrupt on TimerA triggers, a counter (RTCCount) is
> incremented, and the counter can be used for something useful later on.
> TimerA is sourced from a 32kHz crystal on LFXT1.
>
> I can see that the RTCCount variable reaches 4 or 5 before the reset, and
> this is done by setting a breakpoint where P1.0 is toggled (in the
> IncrementRTCSeconds()-function).
>
> And by setting a breakpoint at initClk_32khz() in main, I can see that the
> MSP restarts the main (resets).
>
> I would really appreciate any help to point me in the right direction.
>
> Cheers,
>
> Mike
>
> [Code] > > #include // Prototype definitions > > void initClk_32khz(void); > > void initACLK(void); > > void initTimerA(void); > > void IncrementRTCSeconds(void); > > // Global variables > > volatile unsigned long RTCCount; > > int main(void) > > { > > RTCCount = 0; > > // Stop watchdog timer to prevent time out reset > > WDTCTL = WDTPW + WDTHOLD; > > initClk_32khz(); > > initACLK(); > > initTimerA(); > > // Enable interrupts > > _BIS_SR(GIE); > > // For debugging only. > > P1DIR = 0xFF; > > P1SEL = BIT1; > > while(1) > > { > > } > > } > > void initClk_32khz(void) > > { > > BCSCTL1 |= XT2OFF; // Turning off XT2 > > BCSCTL1 &= ~XTS; // LF-mode > > IFG2=0; /* reset interrupt flag register 1 */ > > IFG1=0; /* reset interrupt flag register 2 */ > > do { > > /*wait in loop until crystal is stable*/ > > IFG1&=~OFIFG; > > } while(OFIFG&IFG1); > > } > > void initACLK(void) > > { > > // ACLK is naturally sourced by LFXT1 > > // ACLK divider > > BCSCTL1 &= ~DIVA0; // Divide by 1 > > BCSCTL1 &= ~DIVA1; // Divide by 1 > > } > > void initTimerA(void) > > { > > // Reset/clear the timer > > TACTL |= TACLR; > > // Stop the timer > > TACCR0 = 0x0; > > // Selecting ACLK as clock source > > TACTL |= TASSEL0; > > TACTL &= ~TASSEL1; > > // Clock divider > > TACTL &= ~ID0; // Divide by 1 > > TACTL &= ~ID1; // Divide by 1 > > // Mode control > > TACTL |= MC0; // Up mode > > TACTL &= ~MC1; // Up mode > > // Compare mode > > TACCTL0 &= ~CAP; > > // Interrupts > > TACTL |= TAIE; // Enable TimerA interrupt > > TACCTL0 |= CCIE; // Compare interrupt enable > > // Clear the interrupt flag > > TACTL &= ~TAIFG; > > TACCTL0 &= ~CCIFG; > > // Start the timer > > TACCR0 = 32767; > > } > > void IncrementRTCSeconds(void) > > { > > RTCCount++; > > P1OUT ^= 0x01; // Toggle P1.0 > > } > > // Timer A0 interrupt service routine > > #pragma vector=TIMERA0_VECTOR > > __interrupt void TimerA_interrupt (void) > > { > > IncrementRTCSeconds(); > > } > > [/Code]
>
>
>
>
>


Hello again,

I solved the problem, or rather Jeff and OCY solved my problem :-)

Indeed, it was a problem with the TimerA1-interrupt, and my solution was
to disable the interrupt by removing the
TACTL |= TAIE;

Thank you OneStone, for your comments about C and its ability to
manipulate bits - or the lack of these abilities.

I really appreciate your help, so thank you very much!

Cheers,
Mike

Good to hear you're on your way. I overlooked the independence of TAIE and
CCIE, baahh. Thanks OCY.

I was going to let this go but no, no, no. C does not lack any ability to
manipulate bits. C on a micro does not, intrinsically, look "unnatural" or
"ugly". If you started off in asm and you write a whole lot of it, it's
natural to be biased against other languages. The problem isn't with C, it's
with the human. Cognitive bias is well-documented in homo_sapien-errata.pdf.
Now if Al replies with some substantive criticism of C I would be happy to
hear it. Otherwise, take this as an example of that powerful bias we all
experience and fight to avoid repeating it so that we don't make the same
mistake in ten years when people are writing code in $FOO_THAT_IT_NOT_C
(which we/I will, but at the very least we should try not to).

Personal example:
Java is ugly. Java looks cluttered. Java does so many things that don't make
sense. C makes perfect sense.

switch()s can be ugly, sure. Bad code looks ugly. Are switch()s
intrinsically ugly? No.
If you're using switch() in ISRs in IAR, look up __even_in_range() to
generate more efficient code. I haven't used CCE so I don't know if there's
an equivalent but I wouldn't be surprised. Sure beats an "ugly"
implementation in asm, eh? ;UNLESS YOU LIKE COMMENTS LIKE THIS :-)

var>>2, var<<2, var & 0x02, var | 0x02, var ^ 0x02
|=, &=, >>=, <<=, ^These things look totally natural to me. Is there actually something wrong
with them or are you just not as familiar with them as you are the asm
equivalents? Ah-ha. Human.
On Wed, Mar 31, 2010 at 1:56 PM, Mikael W. Bertelsen wrote:

> Hello again,
>
> I solved the problem, or rather Jeff and OCY solved my problem :-)
>
> Indeed, it was a problem with the TimerA1-interrupt, and my solution was
> to disable the interrupt by removing the
> TACTL |= TAIE;
>
> Thank you OneStone, for your comments about C and its ability to
> manipulate bits - or the lack of these abilities.
>
> I really appreciate your help, so thank you very much!
>
> Cheers,
> Mike
>
>
>


We're never going to agree, and it isn't a bias based on my earlier
experience. I programmed in C on the PC for many years, and on main
frame machines. For a microprocessor, which it was desgined for, C makes
sense. For a microcontroller, which it wasn't designed for, the language
has been contorted to fit. I have been using C for over 30 years, and
assembler for slightly longer, so I am quite familiar with the
contortionist act of clearing 1 bit by effectively ANDing with the
inverse of that bit, and all the other odd looking things C does. It
doesn't make it any more natural.

Since microcontrollers are designed for interfacing directly to the real
world, they are optimised for this function with the inclusion of
instructions to manipulate data at the single bit level, and to react to
events in real time, hence the inclusion of interrupt specific
functions. C was designed for a mini-computer operating system, and
reflects this in its instruction set and structure. The additions
leveraged into C to handle the differences in these environments are not
even standard. In many cases compiler vendors are free to implement as
they wish. So if I were writing a PC based data analyser for one of my
data loggers then I'd certainly write it in C, (maybe not, the last
'real time' data analysismodule I wrote to analyse complex data was
written in Excel) but while coding for real world apps I'd rather write
in asm, and maintain intimate control.

of course it is easy to write ugly code in any language, but I think it
is much easier to write ugly inefficient code in C for a micro,
especially when you have no hardware knowledge. the idea of isoltaion
from the hardware is one of the C features that is promoted as being
'good', yet from the many hundreds of examples I see here and in other
forums it leads to really poor inefficient code. take Mikeals tiny
program. Subroutine calls out of an ISR, multiple statements when 1
would do, etc etc. Without an intimate knowledge of the compiler and the
hardware it is very difficult to write clean efficient code, and that
would seem to defeat the objective behind using C. I know many modern
compilers can optimise many common issues, but not all, and, again
knowledge of the compilers optimisation process is needed to achieve the
best results. All I need to know about the assembler is that it has no
bugs in translation of the source, ie it selects the correct address
modes etc. Other than that it is irrelevant.

Finally, again, back to Mikael. Disabling TAIE isn't really the
solution, or the best one.

Your program set the count up to CCR0 mode. this is intended for use by
the TAIE interrupt and forces an interrupt on overflow of TAR past CCR0.
The TAIE interrupt then occurs every 32768 ticks. What you did wrong was
to also enable the CCR0 interrupt at the same time, so that an interrupt
occurs to the unhandled TimerA-0 interrupt at TAR = 32767, then a second
interrupt occurred to the wrongly handled TimerA generic Interrupt at
TAR = 0. I don't know if your compiler would have routed the CCIE
related interrupt, but I doubt it very much, as this is a aseparate
vector (again highlighting the danger of NOT handling every interrupt
vector).

So you should have disabled the CCIE interrupt, then correctly handled
the TIMERA generic interrupt by using TAIV. Not to do so means that an
inadvertent interrupt flagged into TAIV causes clock errors. As
implemented the reset would have occurred due to a call to the TIMERA-0
vector that was unhandled, resulting in FFFF being placed in that
vector, which is an illegal address for an interrupt.

To maintain the ability to freely use the remaining two timers, without
having to adjust them for the shortened count in TAR you could have
implemented this using TA-0 and adding 32768 to CCR0 in the ISR, thus
the timer would overflow every 2 seconds, but count in seconds, and TA-1
and 2 are still available for pulse timing etc, or you could have done
the same using TA-2, and that keeps TA-0 free to implement PWM

Cheers

Al
Jeff Roberts wrote:
> Good to hear you're on your way. I overlooked the independence of TAIE and
> CCIE, baahh. Thanks OCY.
>
> I was going to let this go but no, no, no. C does not lack any ability to
> manipulate bits. C on a micro does not, intrinsically, look "unnatural" or
> "ugly". If you started off in asm and you write a whole lot of it, it's
> natural to be biased against other languages. The problem isn't with C, it's
> with the human. Cognitive bias is well-documented in homo_sapien-errata.pdf.
> Now if Al replies with some substantive criticism of C I would be happy to
> hear it. Otherwise, take this as an example of that powerful bias we all
> experience and fight to avoid repeating it so that we don't make the same
> mistake in ten years when people are writing code in $FOO_THAT_IT_NOT_C
> (which we/I will, but at the very least we should try not to).
>
> Personal example:
> Java is ugly. Java looks cluttered. Java does so many things that don't make
> sense. C makes perfect sense.
>
> switch()s can be ugly, sure. Bad code looks ugly. Are switch()s
> intrinsically ugly? No.
> If you're using switch() in ISRs in IAR, look up __even_in_range() to
> generate more efficient code. I haven't used CCE so I don't know if there's
> an equivalent but I wouldn't be surprised. Sure beats an "ugly"
> implementation in asm, eh? ;UNLESS YOU LIKE COMMENTS LIKE THIS :-)
>
> var>>2, var<<2, var & 0x02, var | 0x02, var ^ 0x02
> |=, &=, >>=, <<=, ^> These things look totally natural to me. Is there actually something wrong
> with them or are you just not as familiar with them as you are the asm
> equivalents? Ah-ha. Human.
> On Wed, Mar 31, 2010 at 1:56 PM, Mikael W. Bertelsen wrote:
>
>>
>> Hello again,
>>
>> I solved the problem, or rather Jeff and OCY solved my problem :-)
>>
>> Indeed, it was a problem with the TimerA1-interrupt, and my solution was
>> to disable the interrupt by removing the
>> TACTL |= TAIE;
>>
>> Thank you OneStone, for your comments about C and its ability to
>> manipulate bits - or the lack of these abilities.
>>
>> I really appreciate your help, so thank you very much!
>>
>> Cheers,
>> Mike
>>
>>
>>
>
>
>
I always include a section of code that captures all the possible interrupt vectors that aren't used anywhere else. This way, if some unexpected interrupt happens, you know. You can have it do something useful, like toggle a bit rapidly so you can see activity, or display a message, or just hang the processor so you can do a manual break. All the vectors call one routine with the vector number, so you can tell which vector tripped. It has been a big help to me.

#pragma vector = TIMERB1_VECTOR
__interrupt void TIMERB1_VECTORz( void )
{
VectorProblem( TIMERB1_VECTOR);
}

#pragma vector = COMPARATORA_VECTOR
__interrupt void COMPARATORA_VECTORz( void )
{
VectorProblem( COMPARATORA_VECTOR);
}

/* etc, for all other unclaimed vectors */

void VectorProblem( unsigned_byte param)
{
vector_thing = param;

//set breakpoint here
if( IntrErrCount++ == 1 )vector_thing++;
}

Lloyd
--- In m..., "Mikael W. Bertelsen" wrote:
>
> Hello again,
>
> I solved the problem, or rather Jeff and OCY solved my problem :-)
>
> Indeed, it was a problem with the TimerA1-interrupt, and my solution was
> to disable the interrupt by removing the
> TACTL |= TAIE;
>
> Thank you OneStone, for your comments about C and its ability to
> manipulate bits - or the lack of these abilities.
>
> I really appreciate your help, so thank you very much!
>
> Cheers,
> Mike
>