Jump to content
jayaura

SMCLK cant drive 2 peripherals?

Recommended Posts

Dear all,

 

I am an AVR atmega8 refugee, and msp's clocking scheme seems pretty feature rich (not to mention complex!). I am using MSP430G2 launchpad (g2553). This program uses TImerA, and hardware UART with interrupt. It runs at 1Mhz from DCO. And the peripherals take clock from SMCLK.

 

The UART just echos whatever it receives. The timer generate 500ms delay, and toggles the red and green leds on board

 

http://pastebin.com/yApLyFbu

 

The problem is, I can only have one peripheral at a time using the SMCLK. If I have the above code running exactly as it is, the timer will correctly run and toggle the leds as expected, but the UART echo wont work.

 

If I comment out line 8,

TACTL = TASSEL1; //set SMCLK as source - TASSELx = 10

(which means timer is not turned-on at all, right?) then UART echo works.

 

So is it something wrong with my code, or is it like that with the MSP430G2253 ?

 

 

--

Thanks and Regards,

Aurabindo

Share this post


Link to post
Share on other sites

You can clock as many peripherals as you like from the same source, but they all have to be configured consistently. Presumably your UART expects SMCLK at a frequency that is different from the one you use for TA0. Change the UART configuration to match and it'll work fine.

Share this post


Link to post
Share on other sites

Thank you for the response @@pabigot, but I cant figure out what exactly I'm supposed to change in UART. It doesnt have any prescaler setting. AFAIK, just has a clock select (which is SMCLK in my case), and the Baud rate control registers, UCA0BR0 and UCA0BR1. Those values are constants, for a particular baud rate I believe. Though Timer has one independent prescaler, my setting is no prescaling (1).

 

It seems I can have a global prescaler for SMCLK, but will equally change the timer's clock too. What exactly are you proposing to change?

,

Share this post


Link to post
Share on other sites

In your "init_timer_A" function, try setting the value for TACCR0 *before* enabling the timer (the TACTL |= MC0 line) and see if the behavior changes.

 

Still its not working;

 

TACCR0 = 25000; // since clk = 1MHhz => 25us count
TACTL = TASSEL1; //set SMCLK as source - TASSELx = 10
TACTL |=  TAIE; //enabe timer_A interrupt
//TACCTL0 |= OUTMOD2; // Toggle mode - OUTMODx = 100
TACCTL0 |= CCIE; //enable interrupt for capture/compatre;
TACTL |= MC0; // Set Up mode (upto TACCR0) - MCx = 01

But the weird thing is, this time, if I uncomment line starting TACCR0, (first one), UART works  :sad:

Share this post


Link to post
Share on other sites

Okay I found a solution. But my conscience says that fix is *impossible*, but for some reason, its working!!!

 

This is the setting that's working (both UART and Timer). What did the trick is, change the line:

TACTL = TASSEL1 | MC0 | TAIE; 

to

TACTL = TASSEL1 | MC0; 

So dont enable the timer interrupt. Then timer interrupt routines will work!  :wacko:  :blink:  :ohmy:

 

Please someone should help me explain why its so! The full code which works is http://pastebin.com/HtP5yfDW

 

 

Share this post


Link to post
Share on other sites

 

Okay I found a solution. But my conscience says that fix is *impossible*, but for some reason, its working!!!

 

This is the setting that's working (both UART and Timer). What did the trick is, change the line:

TACTL = TASSEL1 | MC0 | TAIE; 

to

TACTL = TASSEL1 | MC0; 

So dont enable the timer interrupt. Then timer interrupt routines will work!  :wacko:  :blink:  :ohmy:

 

Please someone should help me explain why its so! The full code which works is http://pastebin.com/HtP5yfDW

 

 

 

Oh, right... TACCTL0 |= CCIE already enables an interrupt for that CCR, and then TACTL's TAIE enables a different interrupt (for when the timer resets) I think.  I'm guessing the "default interrupt if the user hasn't defined one" is something that's screwing you up (like resetting the chip).

Share this post


Link to post
Share on other sites

Oh, right... TACCTL0 |= CCIE already enables an interrupt for that CCR, and then TACTL's TAIE enables a different interrupt (for when the timer resets) I think.  I'm guessing the "default interrupt if the user hasn't defined one" is something that's screwing you up (like resetting the chip).

 

Great! :)

 

But still, thats timer's problem, right? Why would that mess with UART? It must be some kinda reset like you mentioned, but how do I go about finding what exactly its happening inside the chip?

 

I havent used gdb yet. Will it be *theoritically* possible to know whats happening inside if I use it?

Share this post


Link to post
Share on other sites

Great! :)

 

But still, thats timer's problem, right? Why would that mess with UART? It must be some kinda reset like you mentioned, but how do I go about finding what exactly its happening inside the chip?

 

I havent used gdb yet. Will it be *theoritically* possible to know whats happening inside if I use it?

 

No, the x2xx user's guide tells you.

12.2.6.1 TACCR0 Interrupt
The TACCR0 CCIFG flag has the highest Timer_A interrupt priority and has a dedicated interrupt vector as shown in Figure 12-15. The TACCR0 CCIFG flag is automatically reset when the TACCR0 interrupt request is serviced.

TACTL |= TAIE is a separate interrupt from the TACCTL0 |= CCIE interrupt, per the documentation.  You only have an ISR defined for TIMER0_A0_VECTOR, which is the interrupt vector for TACCR0.

 

From msp430g2553.h near the end:

#define TIMER0_A1_VECTOR    (0x0010)  /* 0xFFF0 Timer0)A CC1, TA0 */
#define TIMER0_A0_VECTOR    (0x0012)  /* 0xFFF2 Timer0_A CC0 */

TIMER0_A1_VECTOR is what fires when the timer resets back to 0 when TAIE is set in TACTL.  With no ISR defined there, I'm presuming the CPU branches to the default ISR which is reset (haven't confirmed that but I think that's it).

 

If you want to prove this, try defining a simple TIMER0_A1_VECTOR interrupt function that blinks an LED or something and re-enable the TAIE in TACTL.  Actually this function doesn't have to do anything really... it can be blank, just so that it exists and ties up the TIMER0_A1_VECTOR interrupt vector slot so it doesn't get assigned to the default vector handler.

Share this post


Link to post
Share on other sites

No, the x2xx user's guide tells you.

12.2.6.1 TACCR0 Interrupt
The TACCR0 CCIFG flag has the highest Timer_A interrupt priority and has a dedicated interrupt vector as shown in Figure 12-15. The TACCR0 CCIFG flag is automatically reset when the TACCR0 interrupt request is serviced.

TACTL |= TAIE is a separate interrupt from the TACCTL0 |= CCIE interrupt, per the documentation.  You only have an ISR defined for TIMER0_A0_VECTOR, which is the interrupt vector for TACCR0.

 

From msp430g2553.h near the end:

#define TIMER0_A1_VECTOR    (0x0010)  /* 0xFFF0 Timer0)A CC1, TA0 */
#define TIMER0_A0_VECTOR    (0x0012)  /* 0xFFF2 Timer0_A CC0 */

TIMER0_A1_VECTOR is what fires when the timer resets back to 0 when TAIE is set in TACTL.  With no ISR defined there, I'm presuming the CPU branches to the default ISR which is reset (haven't confirmed that but I think that's it).

 

If you want to prove this, try defining a simple TIMER0_A1_VECTOR interrupt function that blinks an LED or something and re-enable the TAIE in TACTL.  Actually this function doesn't have to do anything really... it can be blank, just so that it exists and ties up the TIMER0_A1_VECTOR interrupt vector slot so it doesn't get assigned to the default vector handler.

 

 

My bad!, I didnt check the comment on the interrupt vector definition.

 

I guess I breezed though that part of the datasheet. Thank you very much :) Its all clear now

Share this post


Link to post
Share on other sites

Thank you for the response @@pabigot, but I cant figure out what exactly I'm supposed to change in UART. It doesnt have any prescaler setting. AFAIK, just has a clock select (which is SMCLK in my case), and the Baud rate control registers, UCA0BR0 and UCA0BR1. Those values are constants, for a particular baud rate I believe. Though Timer has one independent prescaler, my setting is no prescaling (1).,

The baud rate setting is constant for converting an input clock at a particular rate to a specific baud rate. If you were using a different clock rate for your timer, you would need to calculate different baud rate settings.

 

Glancing at your code, it appears you are using the same clock rate (I didn't check whether the baud or timer settings are right). I don't see you setting up to use the LF crystal, so the DCO rate may be inaccurate, resulting in the UART timing being off and so failing to communicate with the PC.

 

Or, since you can communicate with UART sometimes, it could be that high-frequency timer interrupts are interfering with responsiveness. Or there's a timer configuration issue, which spirilis is helping diagnose.

 

In short, though, the problem is in your code. The MSP430G2553 is perfectly capable of using SMCLK with a UART and a timer simultaneously, which really is all I wanted to point out.

Share this post


Link to post
Share on other sites

I don't see you setting up to use the LF crystal, so the DCO rate may be inaccurate, resulting in the UART timing being off and so failing to communicate with the PC.

 

If it was an RC osc, I would've used an oscillator. But since its DCO, its supposed to be more stable. I never got any issue yet with SMCLK from DCO @ 1Mhz for 9600 bps. Didnt try higher freqs.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...