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.

counting up timer for start()/stop() use

Other Parts Discussed in Thread: TM4C123GH6PM

I'm trying to implement a set of routines that allow me to time between two points in execution.  A function, start(), is called at the first point and another function, stop(), is called at the second point in execution.  The double returned by stop() is supposed to compute the time measured (i.e. counted) since start() was called.

I always get 0 from stop(), and upon debugging it further I see that the timer value is zero.  I've been experimenting with several uses of the timers and everytime I try to use Up Counting it doesn't work, so I'm missing something.  For example I experimented with a timeout style timer and used up counting and set match register.  It wasn't until I did load Set and down counted that it worked.  But here I feel I really need to be able to count up.  Any advise/suggestions?

Thanks.

void init() {
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
    ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER3);    //
    ROM_TimerConfigure(TIMER3_BASE, TIMER_CFG_ONE_SHOT_UP);
    ROM_TimerControlStall(TIMER3_BASE, TIMER_A, true) ;  
}

void start() {
    ROM_TimerDisable(TIMER3_BASE, TIMER_A) ;
    ROM_TimerLoadSet(TIMER3_BASE, TIMER_A,0) ;
    ROM_TimerEnable(TIMER3_BASE, TIMER_A) ;
}

double stop() {
    ROM_IntDisable(INT_TIMER3A);
    ROM_TimerIntDisable(TIMER3_BASE, TIMER_TIMA_TIMEOUT) ;
    ROM_TimerDisable(TIMER3_BASE, TIMER_A) ;
    uint32_t count = ROM_TimerValueGet(TIMER3_BASE, TIMER_A) ;
    return (double(double(count)/double(ROM_SysCtlClockGet()))) ;  // forcing  double just in case there's an issue w compiler
}

My environment: Linux, LM4f120, CCS 5.2, etc.

  • When the timer is configured to count up, it starts from 0 when enabled, and counts up to the value in the load value register.  As soon as it reaches the load value, it resets the timer value to 0, and triggers the interrupt.  So, when you read the timer value, it is always 0.  Also, I haven't confirmed this, but I suspect since the load value is 0, the timer never actually counts, since it reaches the load value immediately.

    I would suggest configuring the timer in periodic mode, enabling it in the init function, allowing it to always run.  Then, in the "start" function, simply read the value of the timer, saving it in to a global variable, and in the stop function, capture the new value and use the two values to compute the difference.

    --Bobby

  • Thanks Bobby,

       I may have to try your approach but I don't understand why my original strategy wouldn't work, as described in general timers not specific to LM4F120:

    o choose a register size that would not overflow for my max time period, given my clock, i.e. use 32-bit or 64-bit timers

    o on start(), set counter to zero, have it increment, then enable counter---don't need interrupts

    o on stop(), stop counter, read counter and use it to compute elapsed time based on freq of clock.

    And, this is what I attempted with the code snippets.  This should work.  

    I think YOU might have pin pointed my problem.  The Peripheral Lib guide doesn't state what registers the TimerLoadSet() and TimerLoadGet() operate on.  I assumed it was the timer's counter.  But, I don't see a "set counter" operation.  I suspect the counters can only be cleared implicitly, i.e. on enable?  

    OK, so maybe I should adjust my understand:

    o *LoadSet/Get - load registers that will be used to reload counter. 

    o *MatchSet/Get - holds value to be compared

    o *ValueGet - is current counter value

    o *Prescale and *PrescaleMatch set/get - depends up/down, but basically extend above in their respective manner.

    Assuming the above is a more correct understanding, what causes counter to clear? 

    Thanks

  • The only suggestion I've found in the forum on reseting/clearing a timer counter is to do the following while timer is disabled:

    ROM_TimerLoadSet(TIMER3_BASE, TIMER_A,0xFFFFFFFF) ;

    The Stellaris ROM user's guide suggested that if the timer is "running" and the above call is made then the counter will be loaded from the load register immediately.

    Update: Based on the insight Bobby provided regarding *LoadSet(), I stopped trying to set it to 0 in start(), as shown in my original snippet.  Result is better.  I'm reading the count but since I'm not resetting the counter on start() measured time just jumps by the interval I'm measuring.

    I need to know how to reset the counter.

    Thanks

  • Hello Tim,

    In your original setup, why don't you read the value first, then disable the timer.  Set your variable as a global an elimante the return value.

    I would suspect that the timer starts from zero when it is enabled and reset to zero when disabled when used in the mode you are using.

    Thanks,

  • Your code is almost correct.  When the timer is configured as a one-shot timer in count up mode, the timer value starts at 0, and counts up till it matches the value in the load register.  When this timeout event occurs, the timer value is reset to 0, and the timeout event interrupt is triggered (if enabled).  What is happening with your setup is that the timeout occurs immediately (since the timer value starts at 0, and the load register is also 0).  So the timer value always reads 0.

    Two things need to be modified in your code.  First, in the start() function, change the TimerLoadSet value from 0 to 0xFFFFFFFF.  This will allow the timer to count up to its maxium value before resetting to 0.

    Second, the timer value needs to be reset to 0.  Normally, in one-shot mode, the timer is allowed to run until it reaches the event and triggers the interrupt.  Reaching the timeout event will automatically reset the timer value to 0.  However, in this case, the timer will not reach the event (unless timed process exceeds 0xFFFFFFFF system clock cycles).  Clearing the timer enable bit (by calling the TimerDisable() function also does NOT clear the timer.  There are two Timer value registers.  One of these registers is a read-only register (GPTMTAR), and is the value that is returned by the TimerValueGet() API.  The second register is a read-write register (GPTMTAV), and is not exposed in the Timer API (since writing this register is not a typical use-case for a one-shot timer).  When the TAV register is written, the TAR register is updated on the next clock cycle.

    So, in your code, you need to #include "inc/hw_timer.h", and add the following statement to your start() function, after the timer is disabled, before you re-enable it.

    HWREG(TIMER3_BASE + TIMER_O_TAV) = 0;

    This should allow your code to start working.

    As a side note, the calls to disable the timer interrupts, and to disable the timer in the stop() function are probably not necessary, and would add additional "error" to your timing calculation.

    I hope this explanation helps.  Let me know if something is still not clear.

    --Bobby

  • greenja said:
    In your original setup, why don't you read the value first, then disable the timer.  Set your variable as a global an elimante the return value.

    First, if you are suggesting I should read the counter first then I would agree and will do that eventually assuming no bad side effects.  This code was intended to be used to explore my understanding and it did the job in terms of helping me realize that I was making bad assumptions or was misinformed.    Once I learn what I need to know I will implement more efficient and robust routines for start()/stop().

    Second, if you are suggesting I read, compute the time, and then just assign to a global variable instead of returning the measured time then I disagree.   But, thanks for the suggestion. 

    greenja said:
    I would suspect that the timer starts from zero when it is enabled and reset to zero when disabled when used in the mode you are using.

    I wish the peripheral api worked this way or was this clear but I don't think what you suggest is correct.  Please offer a reference that supports this or offer a snippet you have tested and works in this manner.  the only missing piece of info I need is how to reliably clear the counter.

    Thanks

  • I hate to sound obnoxious but "Bingo!!"  That did it.  It does affect a reset.

    Regarding interrupt related calls, yes they are result of cut/paste.

    Thanks!!

  • Hello Tim,

    Glad to see that you resolved the issues.  I was merely making suggestions.  I have been away for Stellaris for a few years now and there is a possibility of using it in a possible project.  So you can say I'm just snooping around to see what's going on.

    Past projects included a LCR meter and I vaguely remember how the timing was measured.  I do remember that if a timer was stopped in certain modes that when you started it up again it was reset to zero and that is how I measured the difference in time.  Read the value, stop timer, start timer then subtract, or something along those lines.  The subtraction was done in the loop.

    Thanks,

  • hii bobby

    for TM4C123GH6PM , what are the API's to reset count value of TIMER0A?

    regards

    prashant

  • Hello Prashant,

    Which mode of operation are you planning to use for the Timers?

    Regards

    Amit

  • hii amit

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlDelay(3);
    TimerDisable(TIMER0_BASE,TIMER_A);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
    TimerEnable(TIMER0_BASE, TIMER_A);

    TimerLoadSet(TIMER0_BASE, TIMER_A, 0x00FFFFFF);

     

    i am using periodic up mode.

    can you please see the post.  http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/368827/1296877.aspx#1296877

     

     

    prashant

  • Hello Prashant,

    I went through the other post. It seems what you need to do is use the timer in Input Time Capture Mode rather than periodic Mode. This way the Edge Capture will be logged by the timer which the CPU can then read in the ISR. The Counter will always keep on running and you would need to subtract the new count from the previous count value to get the time difference between two edges.

    What you would need to be particularly careful about is that at rollover of the counter the current value will be less than the previous value (assuming it is count up time capture) and do the arithemetic of

    (LOAD-previous)+current to get the time difference

    Regards

    Amit

  • hii amit

    is there any way to reset the count value?

    Prashant

  • Hello Prashant,,

    I haven't used the Periodic Mode timer in this mode. I believe if the timer does not respond to on the fly change. It would need to be TimerDisable, change the load value and then TimerEnable

    In case that does not work, then I would need to see how to get it in this mode (will take longer timer than moving to edge time mode which is meant for frequency measurement operation)

    Regards

    Amit

  • Thank you amit. now i am taking count difference and getting correct measurement.

    Regards

    prashant