Jump to content
Sign in to follow this  
smiffy

Debugging A Timer

Recommended Posts

I think I am starting to get my head around the basics of Timer_A, but I have run into the problem of finding if it is actually working and, if not, why not.

 

The target device is an MSP430AFE253. I can't find any Timer_A references in the specific datasheet (SLAS701A,) so am treating the MSP430x2xx Family User Guide (SLAU144) as being definitive. I'm reading this in conjunction with the excellent "MSP430 Microcontroller Basics" by John H. Davies, pub. Elsevier.

 

I have a 1.8432MHz crystal attached to the device, and it is this frequency that I wish to use to clock the counter via SMCLK, which will be running as an up counter.

 

First question: do I get the crystal frequency on SMCLK just by having it connected, or is there some sort of hardware initialisation that I have to do first? I'm unable to work this out from the documentation. [My familiarity is with AVR devices, where clock sources sometimes have to be selected.]

 

For the purposes of testing, I'm dividing the clock by 8, and sending an interrupt every time the timer reaches 0xFFFF. The initialisation code I've used for this is:

#include 
#include 
/* big snip */
TACTL=TASSEL_2 + MC_1 + ID_3;
/* I could just set it to overflow, but this number will be changing. */
TACCR0=65535;
TACCTL0|=CCIE;
eint();

 

I then set up an ISR (I'm working with gcc, by the way):

interrupt (TIMERA0_VECTOR) tisr(void) 
{
 /* If this worked, something should happen every
    3-4 seconds.*/
 counter++;
 if (counter==10)
 {
  /* Do something here. */
   counter=0;
 }
} 

 

In the "do something" section, I'm turning on an LED. As this is happening - and the turn-on code works elsewhere - I'm assuming that the ISR is never getting invoked.

 

Second question: does the above code look right for what I am trying to achieve, or have I misunderstood something?

 

Now - assuming that I've got everything right so far - here's where I think the problem may lie: I am using the version of msp430-gcc linked from the Hackaday LaunchPad Linux How-To article. It doesn't support my CPU, so I am compiling with the mmcu CFLAG for the msp430x2012. I don't know how much consistency there is through the family, but have considered the possibility that the peripheral control registers in that device and the one I am using may not have the same addresses.

 

Third question: if different parts have different peripheral control register locations - and so I don't have to build my own gcc just yet - can I include my own header file for the part, imported from one of the TI Windows tools, possibly by modifying io.h? Or does the mmcu CFLAG muck this up?

 

Sorry if I sound a little vague, but I *am* a little vague - I'm unfamiliar with MSP430s and really don't know where I should be looking to fix this.

Share this post


Link to post
Share on other sites

Thank you! So I *do* have to select the crystal oscillator. I'll have a read of the application note in the morning and also see if that startup code gets things working.

Share this post


Link to post
Share on other sites
I have a 1.8432MHz crystal attached to the device, and it is this frequency that I wish to use to clock the counter via SMCLK, which will be running as an up counter.

There may be genuine reasons to involve SMCLK here, but for the sake of argument let's assume this is not what you want :).

 

So as you probably noticed already, there are a number of clock sources as well as a number of clocks in the '430. Clocks include MCLK, SMCLK and ACLK (and also a small handful of peripheral clocks, like BRCLK for the USCI baud rate clock generator and whatnot); clock sources include DCO, VLO, LFXT1 and XT2.

 

On PUC, the as-yet uncalibrated DCO runs at around 1.1MHz (varies relatively "wildly" between devices of even the exact same type), and LFXT is a dud (I think). By saying

DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;

DCO gets calibrated from factory data, making it a pretty good stable 1MHz source.

 

LFXT (XT) comes to life if you explicitly poke it with a stick (see previous post) and VLO is just there humming along.

 

Still barely after PUC, now we have several clock sources running, and have a number of clocks hanging in limbo. Not quite, though. By default configuration, MCLK and SMCLK are sourced from DCO, and ACLK is sourced from the VLO -- so at this stage MCLK and SMCLK are running at 1MHz, and ACLK runs at whatever the VLO runs at (it's around 12 kHz, but it's not factory calibrated AFAIR, and the min-max range is quite big).

 

Now it's time to wire the clock sources to the actual clocks as the current application needs it. (This is also the time when you start peeking at the peripheral documentations.)

 

For lack of information in this arena, let's say that running your CPU at 1 MHz is OK with you. This is pretty much what's happening at this stage; also peripherals that use SMCLK (or MCLK if there's any) as their clock run at 1 MHz too.

 

Your stated need however is Timer_A running at your external xtal's 1.84 MHz. Look at the family guide section 12.3.1 TACTL. What you see is that Timer_A can use several clock sources, among them ACLK and SMCLK (TACLK and INCLK I'm not familiar with, so I'll just generously pretend they don't exist for now :)).

 

Now let's stop for a moment and digest this information: you can use your xtal as the ACLK clock source, and you can use ACLK as the Timer_A clock source. Sure, you can involve SMCLK, but that also means you slow down (or in this case speed up) every other peripheral that uses SMCLK to 1.84 MHz, so you take the no-shortcuts route and make Timer_A use ACLK directly (TACTL |= TASSEL_2).

 

Now, the question "why?!" might spring to mind. To answer that, remembering that the '430 is designed to be a low-power device, let's look at Fig. 2-9 in the family guide. What you see there is how do various clocks and basic peripherals work in the various low power modes.

 

For this application (running Timer_A on the external xtal) we started at LPM1 (lowest LPM where SMCLK is still active), and built our way down to LPM3 (lowest LPM there ACLK is still active), which, according to the 'AFE2x3 data sheet directly translates into several tens-fold less current consumption (OK, so this is a very generous statement, but you get the point).

 

This is my best current understanding of the '430 clock system and some of the principles behind it (possibly presented confusingly :)), so there's a little chance it's off here and there (though I've so far been able to get by on these assumptions), more experienced parties are cordially invited to correct me :).

Share this post


Link to post
Share on other sites

Thanks for solving one of the design problems that I thought I would have to address further down the road :) I suppose if I stated what I'm actually building, it might all make a bit more sense. Like why I'm using a weird (actually Baud rate) crystal. Power consumption IS an issue, as this thing is going to be running off batteries. However, simply by using an MSP430 device in place of the power-hungry AVR in my original prototype, I will be pulling far, far, less current without doing anything fancy.

 

In a nutshell, the MSP430 drives the (hacked) stepper motor of a regular quartz clock, so that the hands don't go round once every 12 hours (except in test mode,) but once per Tropical Year, Synodic Month, or other period I care to define. (I an accommodate 4 modes including test mode, selected by a pair of jumpers on the board.)

 

This is the project blog, which I really MUST update, now that I've got Version 2 under way. http://solsticeclock.co/about

 

The reason for using a 1.8432MHz crystal is that this is the slowest, inexpensive, crystal MHz-range crystal I can get from my distributor (Element14.) 32kHz is too slow to get the resolution I need to get the ticks happening at the right time and then there is a HUGE gap in available components up to 1.8432MHz. I'm sure that Mouser or Digikey could come up with something, but they charge and arm and both legs in freight to Australia unless you are spending $$$ per order.

 

So, that's WHAT and WHY. Now to get the thing working ;)

 

My init code is now starting to look like this:

 /* Crystal oscillator ON. */
BCSCTL1&=~XT2OFF;
/* XTS commented out: "This bit is reserved in the MSP430AFE2xx devices."*/
/* BCSCTL1|=XTS; */
/* This is a 1-3MHz crystal. */
BCSCTL3|=XT2S_1+LFXT1S_1;

 

Trying to figure how to route the crystal oscillator into ACLK, I'm not entirely sure that I can. Quoth "Basic Clock Module+ Introduction:"

Share this post


Link to post
Share on other sites

Well, nothing happened. This is my clock/timer setup code:

 

void init_timer(void)
{
 unsigned int i=0;

 /* Crystal oscillator ON. */
 BCSCTL1&=~XT2OFF;
 /* XTS commented out: "This bit is reserved in the MSP430AFE2xx devices."*/
 /* BCSCTL1|=XTS; */
 /* This is a 1-3MHz crystal. */
 BCSCTL3|=XT2S_1+LFXT1S_1;

 /* Wait for XO to stabilise. */
 do
 {
   IFG1 &= ~OFIFG;           
   for (i = 0xFFF; i > 0; i--); 
 }
 while (IFG1 & OFIFG); 

 /* SMCLK runs off XO. */
 BCSCTL2|=SELS;

 /* Clear timer. */
 TACTL|=TACLR;
 /*    SMCLK      UP     /8  */
 TACTL=TASSEL_2 + MC_1 + ID_3;

 /* Divide 1,843,200 by 8, then count to 65535 - 
    about 3.51Hz. */

 /* Set upper limit, enable interrupt. */
 TACCR0=65535;
 TACCTL0|=CCIE;
 eint();
}

interrupt (TIMERA0_VECTOR) tisr(void) 
{
 P1OUT&=~SPARE;
} 

 

As there is always the possibility that there's something wrong with the XO, I also tried setting the SMCLK source to the DCO (calibrated per Gordon's note) - and I still don't see the ISR getting invoked. I've also tried putting the P1OUT&=~SPARE after the "wait for XO to stabilise" bit in case the oscillator fault is never clearing - but that worked just fine.

 

So, have I still got something wrong in my code, or could this be a problem with building for the wrong part, I wonder?

Share this post


Link to post
Share on other sites

Assuming the XT2 setup is right (I forgot you are not using a G, that's why I got carried away in the previous post ;), the rest looks just about right...

 

Try backtracking to the minimal example. You can also check the XT (might need minor modifications, but the theory is solid), indeed problems may lie therein, though really, your board looks too good for this to be the case... (Flux residue perhaps? Bad cap settings? Stray capacitance from the traces? That I can't really see on the picture... Put some blinky after the Wait for XO to stabilise block and see if it really does.)

Share this post


Link to post
Share on other sites

Thanks. I'll test the minimal example tomorrow.

 

Tomorrow I'll also stop being lazy, walk the two metres to the other side of my office, plug onto a battery pack and put the crystal test point to my scope and frequency counter! If hardware issues possible, test the hardware way...

Share this post


Link to post
Share on other sites
Put some blinky after the Wait for XO to stabilise block and see if it really does.)

 

Oh, yes, I did that earlier - I set the test LED to turn on after the XO stabilised loop - it did. (After a scarcely perceptible delay.)

Share this post


Link to post
Share on other sites
  /* This is a 1-3MHz crystal. */
 BCSCTL3|=XT2S_1+LFXT1S_1;

Hm. [tipdf]SLAU144[/tipdf](H) p.285 says LFXT1Sx bits are reserved on the 'AFE2xx parts, except for 10, which is VLO, how about a try without this bit then?

 

I'm running out of ideas :).

Share this post


Link to post
Share on other sites

Let's try eliminating the crystal oscillator from the equation and use the DCO instead. Putting my code aside for the moment, I have modified the simple example given to feed SMCLK from the DCO, feed the timer from SMCLK (so I'm still going via SMCLK, but with a totally internal clock source.) LED is initialised OFF, ISR turns it ON. This should mean that everything is happening internally, no external hardware is getting involved.

 

#include 
#include 

interrupt (TIMERA0_VECTOR) t_isr(void)
{
 /* Turn on LED. */
 P1OUT &=~ BIT6;
}

int main(void)
{
 /* Watchdog off. */
 WDTCTL = WDTPW | WDTHOLD;

 /* DCO -> 1MHz */
 BCSCTL1 = CALBC1_1MHZ;
 DCOCTL = CALDCO_1MHZ;

 /* MCLK runs off DCO, undivided. */
 BCSCTL2 = SELM0 | DIVM0;

 /* SMCLK also runs off DCO, undivided. */
 BCSCTL2 |= SELS | DIVS0;

 /* Set LED port as output, set it high
    (LED off.)
 */
 P1DIR |= BIT6;
 P1OUT |= BIT6;

 /* Clear timer. */
 TACTL |= TACLR;

 /*      SMCLK     Up    Divide by 1. */
 TACTL = TASSEL2 | MC1 | ID_3;

 TACCR0 = 65535;
 TACCTL0 |= CCIE;

 eint();

 while(1)
 {
   ;
 }
}

 

Would you believe it, the ISR is STILL not invoked. I can only think that I've either got a bad peripheral control register mapping (I'll check the addresses against the MSP430x2012) or - somehow - interrupts aren't enabling.

Share this post


Link to post
Share on other sites

I just modified the code (reverse the on/off of the LED and changed the LED pin) to run on another LaunchPad loaded with an MSP430G2211. Same story - ISR isn't getting invoked.

 

Maybe it's time to stop using macros and start setting registers by the numeric addresses from the datasheets.

Share this post


Link to post
Share on other sites

Think I've got the right one at least on the G series - I've got the G series device working by changing the timer to use ACLK and ACLK to run off the VLO. (The same changes don't work on the AFE device.)

 

I want to get the LaunchPad device working off the DCO next to see where the break in the process is (works with ACLK/VLO, not SMCLK/DCO.) Think I'll leave that for the morning when I'm feeling a little more fresh - I'll go write some Verilog now. It seems an absolute doddle after wrangling recalcitrant peripherals ;)

Share this post


Link to post
Share on other sites
Let's try eliminating the crystal oscillator from the equation and use the DCO instead[...]

 

 /* SMCLK also runs off DCO, undivided. */
 BCSCTL2 |= SELS | DIVS0;

SELS = 1 will make SMCLK run off XT2/LFXT, not DCO.

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.

Sign in to follow this  

×
×
  • Create New...