Flex Timer for input event capture at full system clock rate

Status
Not open for further replies.

kyranzor

Member
Hello,

I have a quick question about the capabilities of the Teensy 3.2 and/or 3.6 (if there's a difference) Flex Timer module and configuring them for event capture mode.

I have read the datasheet a enough to see that it LOOKS like I can set the clock source for the 16-bit flex timer counter to be the system clock (lets say 120Mhz for T 3.2, 180Mhz->240Mhz for T 3.6) with a pre-scalar of 1, meaning it runs at full speed. Is this correct?

I'd like to trigger interrupts on both the flex timer overflowing (so I can increment some variable to keep track of how many times the 16-bit clock has wrapped) and on rising edge event capture (to go and read the FTMx_COUNT register and reset it). I'm trying to measure the passing of time between two 60Hz edges as precisely as possible, so I can compute the phase error to extreme accuracy..

The timer will overflow many many times in the 16.666ms period between edges, but that's okay as long as I can count the overflows.

Is what i'm trying to do possible? Is there a better way to do it with the Teensy hardware?
 
Consider having the input line interrupt on the rising edge, as a highest-priority interrupt, and grabbing the SYSTICK value. In your interrupt handler, grab SYSTICK first thing, and then re-enable interrupts at that level, so that if your two clock inputs are in close phase you minimize timing jitter induced by your own interrupt handling.

Keep in mind that the signal edges have the worst signal-to-noise ratio at any time during the waveform. I would integrate this over a few samples to smooth sampling jitter by keeping a running average.
 
I'm trying to quantify jitter in a single pulse-train, not between multiple inputs, does that change anything? As in, I know it's meant to be exactly 60Hz, and as the clock edges trip the event capture every 16.666ms I read the count value and compute phase, and difference between computed phase and the perfect 60Hz would probably be put in an array and printed after a certain period of time testing (like, 1000 samples or something for now).

Oh and my colleague was saying that whenever he reads the Systick register it's always in multiples of 4 clock ticks, is that normal? We normally do things by regular input interrupt and immediately read SYSTICK as you say, but it always seems to be 4 tick granularity.
 
The manual is very poorly done with generic chapters copied together, important information scattered everywhere and highly misleading stuff.

FTM is not clocked by the system clock, it's clocked by the bus clock (normally 48MHz for T3.2, 60Mhz for T3.6). K66 manual, '45.1.2 External Clock Options':
By default each FTM is clocked by the internal bus clock (the FTM refers to it as system clock).
...


FreqMeasureMulti does exactly what you described. Using FTM input capture is the most accurate way.
 
Oh dear, that difference is huge and cuts it pretty close for the sort of resolution I was hoping to get... Still, it's worth a shot and I have a few T 3.6's hanging around so thanks for the info and the link tni
 
Brooks, I am trying to measure jitter down to tens of nanoseconds, so any sampling delays or possible interrupt latency is unacceptable, that's why I had the idea to try the hardware timer module where it latches the systick (or equivalent) at a hardware level, and then any time in the next 16ms I can come around and look at the value and clear it for the next edge.

The expected phase jitter is in the region of 2,000 or less nanoseconds at the stage that I care about the jitter (steady state motor control).
 
Oh and my colleague was saying that whenever he reads the Systick register it's always in multiples of 4 clock ticks, is that normal? We normally do things by regular input interrupt and immediately read SYSTICK as you say, but it always seems to be 4 tick granularity.
SYSTICK has single clock granularity:
Code:
FASTRUN void setup() {
    Serial.begin(115200);
    delay(1000);

    (void) SYST_CVR;
    noInterrupts();
    uint32_t start = SYST_CVR;
    uint32_t end = SYST_CVR;
    interrupts();
    Serial.printf("Elapsed (0 nop): %u\n", start - end);

    noInterrupts();
    start = SYST_CVR;
    asm volatile ("nop");
    end = SYST_CVR;
    interrupts();
    Serial.printf("Elapsed (1 nop): %u\n", start - end);

    noInterrupts();
    start = SYST_CVR;
    asm volatile ("nop");
    asm volatile ("nop");
    end = SYST_CVR;
    interrupts();
    Serial.printf("Elapsed (2 nop): %u\n", start - end);
}

void loop() {}

Output:
Elapsed (0 nop): 1
Elapsed (1 nop): 2
Elapsed (2 nop): 3
 
trying to measure jitter down to tens of nanoseconds, so any sampling delays or possible interrupt latency is unacceptable, that's why I had the idea to try the hardware timer module where it latches the systick (or equivalent) at a hardware level

That's exactly how FreqMeasure works using FTM input capture. Except it's F_BUS as mentioned previously.

As far as I know, there's no hardware capture mechanism for either systick or the DWT cycle counter. Even if you try to build this with the DMA controller, and even if you can get the DMA controller to access stuff within the ARM core, you'll get some jitter due to bus arbitration.

FTM input capture is your best option.
 
Status
Not open for further replies.
Back
Top