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.

Misuse of SCS in recommended code to read asynchronous timer counter

Other Parts Discussed in Thread: MSP430F5438A

The 5xx/6xx user's guide (slau208k) and other discussion in this forum suggests that the best way to reliably read a timer counter when the timer clock is asynchronous to MCLK is to use a capture register and trigger the capture in code by toggling CCIS0 of the corresponding control register.  The text description and example code from the user's guide is:

Captures can be initiated by software. The CMx bits can be set for capture on both edges. Software then sets CCIS1 = 1 and toggles bit CCIS0 to switch the capture signal between VCC and GND, initiating a capture each time CCIS0 changes state:

  MOV #CAP+SCS+CCIS1+CM_3,&TA0CCTL1 ; Setup TA0CCTL1, synch. capture mode, Event trigger on both edges of capture input.
  XOR #CCIS0,&TA0CCTL1              ; TA0CCR1 = TA0R

This is incorrect because of the inclusion of SCS in the example TA0CCTL1 configuration.

Documentation says: Setting the SCS bit synchronizes the capture with the next timer clock.

Real-world (verified to my satisfaction with the MSP430F5438A) says: Setting the SCS bit synchronizes the capture with the next falling edge of the timer clock (slightly different).  A capture will occur even if the input signal has returned to its original state before a clock transition occurred.

When SCS is set the CCR register is not loaded from TA0R until a falling edge is observed on the timer clock.  If the timer clock is asynchronous to and slower than MCLK, the value of TA0CCR1 immediately after the XOR above will not necessarily be TA0R, nor is it true that a capture is initiated each time CCIS0 changes state.

I have only checked Timer_B on the MSP430F5438A, so other timer peripherals may behave differently.

  • Peter Bigot said:
    Setting the SCS bit synchronizes the capture with the next falling edge of the timer clock (slightly different).

    Well, the falling edge is commonly considered the start of a new clock cycle, so it is the natural synchronization point and perhaps considered to be implicitely said. However, it might be different and explicitely stating it would be a good idea. It may not be important when using an internal, periodical clock source, but on an external one, polarity may be important.

    Peter Bigot said:
    When SCS is set the CCR register is not loaded from TA0R until a falling edge is observed on the timer clock.

    I completely agree. In my own applications I never considered setting SCS at all. After all, an asynchronous, immediate capture is the intention of this workaround.

    Well, if the tiemr clock is significantly slower than MCLK, you can use
    while(x!=TAR) =TAR;
    to get a reliable reading.
    And if both clocks are similar (or the time clock is even higher) but not synchronous, then it won't make a differene whether SCS is set or not, the capture will take place before you can read the result.
    It's the case when the timer clock is in the order of 25-50% of MCLK where the use of SCS is an issue.

    I'll add this to my list of documentation comments. However, I just forwarded my collection for the 5x family users guide, so it will take some time before I'm ready to submit the next bunch.

  • Jens-Michael Gross said:
    Setting the SCS bit synchronizes the capture with the next falling edge of the timer clock (slightly different).

    Well, the falling edge is commonly considered the start of a new clock cycle, so it is the natural synchronization point and perhaps considered to be implicitely said. However, it might be different and explicitely stating it would be a good idea. It may not be important when using an internal, periodical clock source, but on an external one, polarity may be important.[/quote]

    Interesting, since the timer counter is incremented on the rising edge and the figures in the Timer_A section usually start with the timer clock low, which seems misleading if you're right.

    Jens-Michael Gross said:
    When SCS is set the CCR register is not loaded from TA0R until a falling edge is observed on the timer clock.

    I completely agree. In my own applications I never considered setting SCS at all. After all, an asynchronous, immediate capture is the intention of this workaround.

    Well, if the tiemr clock is significantly slower than MCLK, you can use
    while(x!=TAR) =TAR;
    to get a reliable reading.

    [/quote]Or something like that, yes, though in the forum post I linked to that solution was explicitly rejected in favor of using the capture solution.  So I thought it important to raise the issue.

    It's unfortunate that there's no solution that produces a reliable read with both faster and slower clocks.  IMO word access to the timer counter as data ought to be reliable, even if it takes extra logic to make it happen.

    Jens-Michael Gross said:
    I'll add this to my list of documentation comments. However, I just forwarded my collection for the 5x family users guide, so it will take some time before I'm ready to submit the next bunch.

    Hopefully TI also tracks errata reported by others and it'll get fixed along with your list.

  • Ignore this; the documented technique without using SCS ought to be reliable regardless of relative rates, though it's still less desirable than fixing it in hardware.

    Peter Bigot said:
    It's unfortunate that there's no solution that produces a reliable read with both faster and slower clocks.  IMO word access to the timer counter as data ought to be reliable, even if it takes extra logic to make it happen.

  • Peter Bigot said:
    Interesting, since the timer counter is incremented on the rising edge and the figures in the Timer_A section usually start with the timer clock low, which seems misleading if you're right.

    Indeed, for compare mode and most other operations, the rising edge triggers the action.
    Since my university days, the 'natural' clock 'active' edge is the falling edge. Maybe because in TTL logic, the default (open) state is high due to internal pullups. On CMOS logic, there is no default state and open state is indeterminate. So personally, I usually assume the falling edge being the active edge. Well, on a symmetrical, periodical clock source, of unknown synchronization, it is rather unimportant (time is relative), so I never had a reason to dig into this further.

    However, in capture mode, the falling edge is indeed the active edge, as shown in Fig. 17-10, when the SCS bit is set. If you noticed the risign edge in previous diagrams, this is indeed surprising. But documented.

    Peter Bigot said:
    while(x!=TAR) =TAR;

    Or something like that,[/quote]
    You're right that the capture mode solution wihtout SCS will always work. However, it requires a free CCR unit. On many MSPs, there are plenty of timers, but with few CCRs (2 or 3) only. So requiring one for reliably reading TAR isn't nice. The while loop will work up to TACLK<=MCLK/10 and doesn't require a CCR unit. And, as it doesn't require programming of the CCR, it is shorter and faster.

    I agree that a double-buffered TAR that allows reading while it is updated would be a good thing. But not as simple as it might seem. Especially as it adds quite some (always active) logic to the timer, which increases operating current.
    The PxIFG register for port interrupts did have similar problems. The PxIV register solved it. But port interrupts don't happen at every timer tick, so the additional logic is mostly inactive and doesn't increase current.

    Peter Bigot said:
    Hopefully TI also tracks errata reported by others and it'll get fixed along with your list.

    Well many of my reports have beeen made their way into newer versions of the datasheets or users guides. (Well, I don't know whether it ws my report or whether they were already noticed and scheduled when I reported them)
    Including the issue that was bringing me here originally. (for this one, I got direct feedback and was noticed that the already scheduled release of the new users guide was delayed to add it)

    Well, I checked the users guide again, and, technically, the use of SCS in the example isn't wrong at all. The example is not for realiably reading the TAR value, but for manually triggering a capture in general. If you want to manually trigger a capture interrupt on the next (falling, or with inverted external clock, rising) clock edge, the example in 17.2.4.1  is okay as it is. It's just (as so often) the lack of exhaustive documentation (includingthe intention of the example and possible or implicitely used side-effects) that makes it misleading.

  • Jens-Michael Gross said:

    You're right that the capture mode solution wihtout SCS will always work. However, it requires a free CCR unit. On many MSPs, there are plenty of timers, but with few CCRs (2 or 3) only. So requiring one for reliably reading TAR isn't nice. The while loop will work up to TACLK<=MCLK/10 and doesn't require a CCR unit. And, as it doesn't require programming of the CCR, it is shorter and faster.

    I don't find it to be shorter or faster.  In BSP430 I reserve a CC register for this purpose (with an option to redefine or disable the feature), so the initialization is done once when the timer is set up.   Then the capture is a single XOR instruction and I use the CCR instead of the TAR as the result.  No jumps, no multiple reads, no comparisons, so it's faster and shorter and captures the counter correctly regardless of the underlying timer clock.

    Jens-Michael Gross said:
    Well, I checked the users guide again, and, technically, the use of SCS in the example isn't wrong at all. The example is not for realiably reading the TAR value, but for manually triggering a capture in general. If you want to manually trigger a capture interrupt on the next (falling, or with inverted external clock, rising) clock edge, the example in 17.2.4.1  is okay as it is. It's just (as so often) the lack of exhaustive documentation (includingthe intention of the example and possible or implicitely used side-effects) that makes it misleading.

    If we're talking about the "Capture Initiated by Software" paragraph, the text doesn't mention triggering a capture interrupt and the code doesn't set CCIE, so it's a stretch to say it's OK as an example of manually triggering a capture interrupt.  Instead it talks about capturing the timer counter and says a capture is initiated on each CCIS0 change, which is simply not true with SCS.  The comment claims the XOR has the effect of copying TA0R into TA0CCTL1, which is also untrue.  From my perspective that moves from "misleading" to "wrong", especially since it's in a section that discusses capture in general, not  synchronous capture specifically.

    A lot of fuss over something that probably only happened because somebody editing the document saw "Setting the SCS bit to synchronize the capture signal with the timer clock is recommended" and updated the example without understanding how it worked.  I agree the example needs a better description of when you would want to use this pattern, since it is the only robust solution to the unpredictable results issue noted up in 17.2.1.

  • Peter Bigot said:
    the initialization is done once when the timer is set up.

    Well, if you need it at many places and set it up once, you're right. If you only need it at one place (which likely is the normal case), it makes no difference to code size whether it is set up at program start or when required. Of course if it is setup at program start, the setup is not executed multiple times and therefore faster. At the expense of a CCR unit that is locked throughout the whole application.
    But these are implementation details. And it's the codrs jb to deterine what fits better.

    Peter Bigot said:
    the text doesn't mention triggering a capture interrupt

    Indeed. It is a stub anyway. However, it is about manually triggering a capture, and what purpose will a manual capture serve (except for the purpose we're talking about, which is also nowhere mentioned there) when you don't want to capture the next event when it happens?
    That's what I meant when talking about intentions.

    Peter Bigot said:
    Instead it talks about capturing the timer counter

    Well, that's what capture mode is about, independent of purpose.
    Peter Bigot said:
    and says a capture is initiated on each CCIS0 change, which is simply not true with SCS.
    Initiated, not performed. The text continues that the capture will happen even if the trigger is already reset when the clock edge comes.

    Peter Bigot said:
    The comment claims the XOR has the effect of copying TA0R into TA0CCTL1, which is also untrue.

    Well, at the end it does. Just not instantly. that's what capture mode does: copying TAR to CCRx.

    Peter Bigot said:
    especially since it's in a section that discusses capture in general, not  synchronous capture specifically.

    For asynchronous capture, the text is true without doubt. It's just that the example uses a special case (fitting the timing diagram, whcih is also for the special case of synchronous capture) while the text describes the rather generic case.
    I'm with you that thsi is misleading (at best).

    Peter Bigot said:
    something that probably only happened because somebody editing the document saw "Setting the SCS bit to synchronize the capture signal with the timer clock is recommended" and updated the example without understanding how it worked.

    Well, that's the common case: those who do the documentation aren't those who did the design. And even if the original engineer did the initial description, those who make it into a document often enough have no clue about the details. That's where 'division of work' often leads.
    We see the same problem with out company website and the 'design' for the new software version. The 'designer' had no clue about what our company did, and didn't care. He designed a website that looks, well, average, with the usual lacebook or goggle buttons, but doesn't give the visitor a clue about what we're really doing. And for the content, he just asked questions and added the result isntead of figuring out himself what#s going on and how to present it best.
    And the design someone made for the new software version looks pleasant, but is next to impossible to implement. Like an Escher picture that's easy to draw but difficult to model in 3D then.

    Even more, I guess this case of asynchronous reading of TAR is a rather unusual case (at least in the TI labs). Normally, you either wait for an event or doN't care for the current timer count. And the typical application where it is used is when the timer counts on 32kHz while MCLK is 1MHz or more and the while loop does fine. So most likely nobody bothered to thoroughly check it until someone noticed a problem in a real application.

    There are reasons why there is a long revision list on the users guides. And adding new module descriptions is only one of them. Fixing bugs another one, and not less important or frequent :)

**Attention** This is a public forum