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.

Timer missing interrupts

Other Parts Discussed in Thread: SYSBIOS, TM4C1294NCPDT

CCS: Version: 6.1.2.00015
Tiva Eval Board: EK_TM4C1294XL
TivaWare_C_Series-2.1.2.111
xdctools_3_31_01_33_core

Hello,

I have a Timer (timer 0) configured to interrupt once every 256 microseconds (I realize this is fast).

It occasionally misses an interrupt (approx 7 per minute).

How do I know?
  The ISR adds 256 to a variable.
  Over time if I compare this value to what is returned by Timestamp_get64 (divided by 120), they diverge.

The ISR is very short.
My code is not disabling hardware interrupts.

I am using configuration to create the Timer instnace.

Elsewhere in the program, a UART is being used, tasks are running and Clocks (as opposed to Timers) are
being used to time things for the tasks.  I am using TIRTOS drivers for all of these.
Note: Dramatically increasing the serial load does not seem to increase the dropout frequency.

This timer performs the most important function in the system, sampling data that must be gathered
at that frequency.

Does something in the TIRTOS kernel disable interrupts for that long?

What can I do to make certain these are not being missed?

Thanks,
Greg Winters

  • Greg Winters45 said:
    I have a Timer (timer 0) configured to interrupt once every 256 microseconds (I realize this is fast).

    256 microseconds should be OK.  The default Clock in SYS/BIOS uses 1000 microseconds/tick, which is at least in the same "order".

    Greg Winters45 said:
    Does something in the TIRTOS kernel disable interrupts for that long?

    The TI-RTOS kernel (called SYS/BIOS) itself would not disable interrupts for anything near 256 microseconds, but I'm not sure about the drivers which are not part of SYS/BIOS itself.  I will look around and get back to you on that topic.

    The SYS/BIOS benchmarks include an entry for "Interrupt Latency", which translates to the longest period during which SYS/BIOS disables interrupts.  For the ARM M4F architecture, the Interrupt Latency is 135 CPU cycles. You can find this and other benchmarks in:

    <TI-RTOS INSTALL DIR>\products\bios_<BIOS VERSION #>\packages\ti\sysbios\benchmarks\doc-files\M4F_times.html

    Greg Winters45 said:
    What can I do to make certain these are not being missed?

    The M4F target has zero latency interrupts, perhaps one of those would perform better. Would that be a possibility for you?

    Regards,

    - Rob

  • I agree that zero latency interrupts sound like the ticket, but I am having difficulty finding clear documentation on how to use that feature.

    In the 'SYS/BIOS for Stellaris Devices' wiki it tells how to setup a HWI handler so that if you choose priority zero it will go to the zero latency interrupt.

    Vector #35 is Timer-0A.  I had previously created a SYS/BIOS Timer object for Timer-0 using config.

    I expect that I have to do something different to use a timer in conjunction with an HWI instance?

    I deleted the static configuration for timer 0, but compilation fails with "Timer interrupt 35 already in use!"

    What else is using vector 35?

    How do I create a timer to use in conjunction with an HWI instance?

  • Greg Winters45 said:

    I deleted the static configuration for timer 0, but compilation fails with "Timer interrupt 35 already in use!"

    What else is using vector 35?

    I found that the Clock module is configuring a Timer for the Clock tick and it uses Timer 0, which as you point out, uses vector 35.

    The Clock module settings has a field named "Timer Control" in which you can change the Timer Id.  It is probably currently set to ANY for you.  I tried changing this to use Timer 1 but found that Timer 1 was already in use, so I chose Timer 2, which seemed to work.  I was then able to configure a Hwi from ti.sysbios.family.arm.m3 to use vector 35 and priority 0.  I don't see a way to connect a Timer instance to this Hwi, nor a way to configure a Timer instance's interrupt priority, so in order to follow this path you would need to manually program the timer.

    I spoke with a colleague about this and he was surprised to see that you're missing ticks from your 256 microsecond interrupt, and wanted to hear more detail about your method of determining that your clock is drifting.  Can you expand on that?

    Would you be able to measure your 256 microsecond clock against some outside source to test the drift?  I'm mostly trying to rule out a problem with your measurement standard of Timestamp_get64() / 120.  Is the divide by 120 due to your CPU clock speed of 120 MHz?

    It would be useful for me to see your application configuration file (.cfg file), can you attach that?

    Regards,

    - Rob

  • I would be delighted to be shown that my methodology for determining divergence is faulty!

    To that end I have created a very minimal project that demonstrates the issue (attached).

    Since I based my application by starting with the 'Bigtime C++' example, I did the same thing again but basically just have a timer running and a task that periodically looks for a difference between the timer time and what the time stamper returns..

    Just set a breakpoint on the line after the test if the divergence exceeds 512 (I think the line currently increments the delta variable just to have a line to stop on).

    It should stop on the breakpoint withing 10 - 15 seconds.

    And yes, I divide the timestamp by 120 because of the CPU clock rate being 120MHz.

    1307.TimerTest.zip

  • I think I have figured this out...

    The free running counter incrementing at 120MHz does not miss a tick.  

    A timer set in continuous mode loaded with 256 microseconds worth of ticks, decrements to zero, interrupts the CPU and is reloaded with 256.

    The issue is that this 'reloading' takes a small number of CPU cycles, which over time becomes apparent as a divergence from the perfect free running counter.

    So no timer ticks are being missed, but I can't use the time stamper separately as an indication of 'where I am currently within the 256uS window'.  This is sad, but I can live with it.

    There are no gaps in the sensor readings which is paramount.

    I am suggesting this as answer, please verify if you concur.

  • Greg Winters45 said:

    A timer set in continuous mode loaded with 256 microseconds worth of ticks, decrements to zero, interrupts the CPU and is reloaded with 256.

    The issue is that this 'reloading' takes a small number of CPU cycles, which over time becomes apparent as a divergence from the perfect free running counter.

    I've been reading up on this timer in the Tiva TM4C1294NCPDT Microcontroller Data Sheet.  It mentions that the period reload happens in the next cycle after the countdown reaches 0, and is then started in the cycle after that.  This leads me to believe that to achieve a period of 256 you should use either 256 - 1 or 256 - 2 for the period.  Can you try changing your period to 255 and see if this timer is now in sync with the free running counter?  If that still diverges, please try 254.

    in general, a periodic timer needs to be just that - truly periodic without any non-deterministic latencies in setting up the next period.

    Here's the section from the Data Sheet that speaks to what I was mentioning above (from section 13.3.3.1 One-Shot/Periodic Timer Mode):

    When the timer is counting down and it reaches the timeout event (0x0), the timer reloads its start value from the GPTMTnILR and the GPTMTnPR registers on the next cycle. When the timer is counting up and it reaches the timeout event (the value in the GPTMTnILR and the optional GPTMTnPR registers), the timer reloads with 0x0. If configured to be a one-shot timer, the timer stops counting and clears the TnEN bit in the GPTMCTL register. If configured as a periodic timer, the timer starts counting again on the next cycle.

    Here's a link to the Data Sheet: www.ti.com/.../tm4c1294ncpdt.pdf

    Regards,

    - Rob

  • The 'cycles' that they speak of here are CPU cycles (at 120MHz) not microseconds. So it is not possible to offset for something that small.
  • My guess is that if I added a microsecond every 60 interrupts (120/2) I could keep track of where things were, but that starts to get convoluted.
  • Greg Winters45 said:
    The 'cycles' that they speak of here are CPU cycles (at 120MHz) not microseconds. So it is not possible to offset for something that small.

    Your SYS/BIOS Timer can be created with PeriodType_COUNTS assigned to Timer_Params.periodType.  You could then calculate the correct count to represent 256 microseconds.  This is what SYS/BIOS is doing under the covers when you use PeriodType_MICROSECS (the default).  A period of 256 microseconds would be realized with a count of 0x7800 for a 120 MHz timer count, and indeed I see SYS/BIOS using this for the actual timer period register.  If my assumption that the period register should be programmed with "count - 1" is correct then perhaps using
    Timer_Params.periodType = PeriodType_COUNTS;
    Timer_Params.period = 0x77ff;
    might correct the drift.  If that turns out to be the case, then I will file a bug for SYS/BIOS regarding this.

    Regards,

    - Rob

  • That worked like a charm, thanks!
  • That's good to hear, I will file a bug for this.

    Thanks very much for your careful analysis and sharp insight into the period register reload delay, it would have taken a lot more digging on my part before focusing on that angle.

    Thanks & Regards,

    - Rob