This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Reading Timer A value without stopping it

Other Parts Discussed in Thread: MSP430G2553

Hi,

I'm running MSP430G2553 TimerA from a 32768 Hz watch crystal.  When an event happens on one of the micro pins, I want to read the value of TimerA.  The micro core itself is running from DCO a lot faster (4 MHz).

The User Guide says that it is best to read the value in TA1R when the clock is stopped, to avoid a race condition.  Apart from wondering what this race condition is (does it mean the micro or timer might spuriously start running wildly, or does it mean that the value of TA1R might be read while it is in the middle of changing, possibly changing several bits somewhat wildly?), I'm wondering what the safest way to deal with this would be.

I don't really want to stop the timer to read it as it could inhibit a valid increment of the timer, if the 32768 Hz crystal just happens to flip over at that moment.  As the period of this is some 30.5 us, that's quite a significant error that could be introduced.

Another suggestion in the User Guide is to read it a number of times and take a majority vote.  Has anyone tried this with success?  How many times should it be read?

I was thinking to read it twice (reads 1 and 2) and if the values are the same, then all well and good - use that value.  But if the values are different, then do another read (no 3) and compare this with no 2.  If they are the same, then use the value of number 3 read (or 2, since they are the same).  But if no 3 is different to no 2, is it worth comparing it to no 1 read and, if they are the same, using this value?  It would seem a bit cavalier to use no 1 read to corroborate no 3 read if the intervening read says something different.

Also, is three reads enough?  I suppose it depends on how quickly the timer flips over from one count to another, with no 'rubbish' counts in between.  (More likely if many bits are changing simultaneously.)  It may also depend on the speed of the micro and how quickly it can 'grab' reads.  Could it be read so quickly that two successive reads give the same result, while it is in fact 'in process' of changing and the values read are not valid?

Anyone with any experience on this?  I'd be grateful to know!

  • Tony Payn said:
    I'm running MSP430G2553 TimerA from a 32768 Hz watch crystal.  When an event happens on one of the micro pins, I want to read the value of TimerA.

    You would want to use timer capture mode for this application.

  • Hello Ilmars

    Thanks for your suggestion.  I had thought about this but my pin which triggers the timer read is not able to be routed to the capture input.

    Would you advocate triggering a capture in software in response to the pin activity?  I have an interrupt routine responding to changes on the pin.  Should I get this interrupt routine to implement a software capture? I'd want to do this without going into a capture interrupt routine.  Could I just, in my pin-change interrupt routine, just set a software capture and then read the value of the capture register immediately?  If I could be sure the capture register contained the value immediately, then that would be fine.

    Thanks

    Tony

  • Tony Payn said:
    but my pin which triggers the timer read is not able to be routed to the capture input.

    Can't be so. Out of wires or solder or what? :)

    Tony Payn said:
    Would you advocate triggering a capture in software in response to the pin activity?

    Sure you can initiate capture by software but if you care about precision then hardware capture is way you shall really consider

  • Tony Payn said:
    I was thinking to read it twice (reads 1 and 2) and if the values are the same, then all well and good - use that value.  But if the values are different, then do another read (no 3) and compare this with no 2.

    Since you have a good difference in clock rates between CPU and timer, just make it easy and always read it three times consecutively and do the majority vote. Less logic to decide when to read twice vs three times.

    I don't think you can ever see the case where 1 & 3 agree but 2 doesn't. So it is 1, 2, & 3 match, 1 & 2 match, or 2 & 3 match.

    psuedo-code:

    x1 = TAR;
    x2 = TAR;
    x3 = TAR;
    
    if (x1 == x2)
      value = x1;
    else if (x2 == x3)
      value = x3;
    
    

  • In a way, I suppose I am.  The board is already laid out and the pin signal is P2.2.  This can only be used as a capture input on TA1.1, but I am using that capture/compare unit already for another unrelated purpose.  Only TA1.2 is free, but P2.2 isn't able to be assigned to TA1.2.

    That's why I was looking for a software method to read the timer value.

    I could probably swap the two capture/compare units since TA1.1 is only used for internal timing purposes.  And using the capture/compare unit to do the capture rather than doing it in software would avoid the delay overhead of switching into the pin interrupt routine before doing my software reads of the timer value, improving accuracy as your post states.  I was curious about the race condition and the correct method to read the timer though, if it had to be done this way.

  • If TA1.2 is not being used but the signal you want to capture is at P2.2, you could use software to make TA1.2 to capture TA1R in TA1CCR2.

  • Tony Payn said:
    my pin which triggers the timer read is not able to be routed to the capture input.

    You can do it in software by switching the capture input between VCC and GND:

    TA0CCTL1 = MC_1|CCIS_2|CAP; Capture on rising edge, capture input is GND
    [...]
    TA0CCTL1 = TA0CCTL1 |= CCIS1; // switch capture input to VCC, causes trigger
    TA0CCTL1 = TA0CCTL1 &= ~(CCIS1); // switch back to GND
    x = TA0CCR1; // read captured timer value.

    The majority vote is a good idea too, but it can be simplified:

    while(!(x==TA0R)) x=TA0R;

    This will read TA0R until two consecutive identical reads. Works only if MCLK much faster than TA0CLK. But this is known at design time.

  • Jens-Michael Gross said:
    while(!(x==TA0R)) x=TA0R;

    That has a subtle bug in it, since the goal is to make sure we don't get bits in the middle of changing due to the clock rate mismatch.

    That code will make the comparison x==TA0R first... but what is the initial value of x?
     In other words, what if the uninitialized value (or initialized for that matter) of x is equal to TA0R when it is in a transition of bits (the condition we are trying to avoid)?

    Answer is that the while loop exits without reading TA0R into x and you have a possible erroneous reading.

    Better answer is

    x=TA0R;
    while(!(x==TA0R)) x=TA0R;

  • If I use c, I would skin the cat with::
    do x=TA0R; while (x!=TA0R);

  • old_cow_yellow said:
    If I use c, I would skin the cat with::
    do x=TA0R; while (x!=TA0R);

    Well, that's another way. I guess it depends on whether you've had your morning coffee (and woken all the brain cells up yet) or not.

    :-)

  • Assembler gurus could use the IAR macro I set up.
    Pause_Routine                               ; example
                tarcopy &TA1CCR2
                add.w   #TA1second/20,&TA1CCR2  ; add the pause before mainloop is run
                ret

    ;---------- M A C R O S ---------
    tarcopy     macro   address
                local gettarmatch
    gettarmatch mov.w   &TA1R,R15           ; trash register
                cmp.w   R15,&TA1R
                jne     gettarmatch
                mov.w   R15,address
                endm

  • Brian Boorman said:
    That has a subtle bug in it

    You're right, if coincidentally, x should have the same initial value that is falsely read from TAR in the comparison, then this value will be taken as correct.

    Chances are very low. However, pre-initializing x with either TAR or with a value that can't be a 'wrong answer' (like '1', since a wrong answer always has the low byte 0 and the high byte by 1 too low) will prevent this, as small as this chance might be.

  • Many thanks to all for your suggestions, I am clear on the best way to do this now.

    Being new to using the 'Verify Answer' buttons etc, I've just verified the last one in the thread but I don't mean to imply that other suggestions were not equally useful to me, I've learned something from all of them.

    Thanks again

    Tony

  • You can verify multiple posts, and as well un-verify them, if appropriate.

**Attention** This is a public forum