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.

TM4C1294NCPDT: TIMER5 in Capture mode: no overflow ("TIMEOUT") Interrupt generated

Part Number: TM4C1294NCPDT


Hi,

I want to measure the frequency of a square wave signal (around 25 Hz).

Hardware setup is given and not done by me. I used to do this on a different micro by counting the overflows of a 16 Bit counter and taking into account 2 captured values from 2 consecutive positive edges.

So I set up TIMER5 A in split / 16 Bit / upcounting "Input Edge Time Mode"

My init code looks like this (actual GPIO config done by pinmux tool elsewhere, I detect capture interrupts so the GPIO setup is fine)

void TimerCCPInit(void)
{
    // Timer peripheral enable
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);

    // Wait for the Peripheral to be ready for programming
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER5));

    // disable Timer
    TimerDisable(TIMER5_BASE,TIMER_BOTH);

    // Timer clock source = system clock (high precision 120 MHz)
    TimerClockSourceSet(TIMER5_BASE,TIMER_CLOCK_SYSTEM);

    // Timer in split mode (2x 16 Bit, Up counting, Capture mode)
    TimerConfigure(TIMER5_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP);

    // set Timer event type for Timer A to positive edge count
    TimerControlEvent(TIMER5_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);

    // set Timer prescaler to 4, resulting in 120Mhz : 4 => 30Mhz Timer clock
    // in UP Counting mode the prescaler provides the MSB of the count value (pseudo 24bit mode)
    TimerPrescaleSet(TIMER5_BASE, TIMER_A, 4);

    // upper limit for TIMEOUT interrupt in up counting mode
    TimerLoadSet(TIMER5_BASE, TIMER_A, 0xFFFF);

    // register Timer5A handler
    TimerIntRegister(TIMER5_BASE, TIMER_A, Timer5AIntHandler);

    // enable capture interrupt
    TimerIntEnable(TIMER5_BASE, TIMER_CAPA_EVENT | TIMER_TIMA_TIMEOUT);

    // enable timer
    TimerEnable(TIMER5_BASE, TIMER_A);

}

I expect the handler to be called either on a capture event (which works) and on the counter overflowing from 0xFFFF to 0x0000 (the datasheet states in paragraph 13.4.4 in the last sentence "In Input Edge Timing mode, the timer continues running after an edge event has been detected,
but the timer interval can be changed at any time by writing the GPTMTnILR register and clearing
the TnILD bit in the GPTMTnMR register. The change takes effect at the next cycle after the write."


So I would assume it also rolls over and generates a TIMEOUT interrupt.

My Handler code looks like this:

void Timer5AIntHandler(void)
{
    // get masked interrupt state as we need to check if its a capture
    // or an overflow interrupt
    uint32_t InterruptFlags = TimerIntStatus(TIMER5_BASE, true);

    // check for capture interrupt
    if(InterruptFlags & TIMER_CAPA_EVENT)
    {


        // read capture value
        uiTimer5CaptureValue = TimerValueGet(TIMER5_BASE, TIMER_A);

        // if it was a capture interrupt, clear interrupt flag
        TimerIntClear(TIMER5_BASE, TIMER_CAPA_EVENT);

        uiTimer5Overflows = 0;

        // toggle D73 green on each capture
        bLEDToggleFlag++;

        if(bLEDToggleFlag & 0x01)
            GPIOPinWrite(LED_D73_GREEN_N_PORT,LED_D73_GREEN_N_PIN,0);
        else
            GPIOPinWrite(LED_D73_GREEN_N_PORT,LED_D73_GREEN_N_PIN,LED_D73_GREEN_N_PIN);
    }

    if(InterruptFlags & TIMER_TIMA_TIMEOUT)
    {
        TimerIntClear(TIMER5_BASE, TIMER_TIMA_TIMEOUT);
        uiTimer5Overflows++;
    }
}

The LED on my frontpanel flickers with half the 25Hz as expected, if I set a breakpoint I see uiTimer5CaptureValue (some global variable not shown above) is set each time to the current capture value.

If I set a breakpoint in the lower branch that checks for the TIMER_TIMA_TIMEOUT, it never gets triggered, also I see the variable stuck at zero.

What am I missing here?

Markus

  • Hi Markus,
    Please find a similar question that was answered in this post. e2e.ti.com/.../467936

    Basically, in capture mode the timeout interrupt is not generated.
  • Great so another peripheral in this chip that is "broken" :-(

    First encountered I2C buggy and doesn't work in non-interrupt driven mode (see errata), 2nd one cannot read the current pin state on an open-drain output (which makes bitbang I2C impossible and is actually used for a ton of applications) and now even the most basic timer modes don't work as one would expect.

    Any suggestion on how to emulate the missing overflow interrupt with a second timer preferably without routing the input signal to additional inputs on the chip?

    Markus
  • Hi Markus,

    One way to generate both the capture and timeout interrupt is to use a second timer in periodic mode with the same parameters as the Event Time Capture Mode and use the GPTMSYNC register to sync them up. The second timer in periodic mode can be used to generate the Timeout Interrupt.
  • Could that be the corresponding "B" Timer? In my case TIMER5B? It's split anyhow and I would have no use for it otherwise.
    The syncing is done in software only? E.g. I don't need to route additional wires?