Timing - TeensyUser/doc GitHub Wiki

wip (luni)

Libraries

IntervalTimer

IntervalTimer uses interrupts to call a function at a precise timing interval.

TeensyTimerTool

The TeensyTimerTool is a library that provides a generic, easy to use interface to the hardware timers of the PJRC Teensy boards

Low level access to the timers

Teensy 3.x timers

PIT- Periodic Interval Timer

4 independent 32bit timer modules. Each module has its own IRQ

FTM & TPM - Flex Timer Module

Number of FTM/TPM modules and number of channels per module depends on the Model -> add table

Teensy 4.x timers

TMR (QUAD)

4 TMR modules, each module contains 4 independent timers which share one IRQ

Here a simple example showing how to use channel 2 from TMR module 3 to generate a periodic interrupt.

IMXRT_TMR_t& module = IMXRT_TMR3;
IMXRT_TMR_CH_t& channel = module.CH[2];

void ISR(){
    channel.CSCTRL &= ~TMR_CSCTRL_TCF1;                          // we do not need to check if channel flag is set since we disabled all other channels
    digitalToggleFast(LED_BUILTIN);
    asm volatile("dsb");
}

void TMR_start(u_int16_t reload)
{
    for (unsigned i = 0; i < 4; i++) module.CH[i].CTRL = 0x0000; // disable all channels

    attachInterruptVector(IRQ_QTIMER3, ISR);                     // attach ISR to module interrupt (note: ISR must handle all 4 channels)
    NVIC_ENABLE_IRQ(IRQ_QTIMER3);

    channel.LOAD = 0x0000;                                       // load on compare -> 0
    channel.COMP1 = reload;                                      // comapare values
    channel.CMPLD1 = reload;
    channel.CNTR = 0x0000;                                       // set counter to zero
    channel.CSCTRL |= TMR_CSCTRL_TCF1EN;                         // enable interrupt

    channel.CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(0b1111) | TMR_CTRL_LENGTH; // start timer using prescaler: 7->1/128; internal clock source

}

void setup(){
    pinMode(LED_BUILTIN, OUTPUT);
    TMR_start(0xFFFF);                                            // max reload value
}

void loop(){
}

Please note that the TMR timer modules are also used for PWM generation. Using them will disable PWM on the corresponding pins.

PIT - Periodic interval timer)

One timer module with four independent 32bit channels. All channels share one ISR

GPT - General purpose timer

Two timer modules with one 32bit channel per module.

Here a simple example how to use GPT1 for a 1us (microsecond) timer witch toggles the pin 23 on the Teensy 4.1.

void GPT1_GPT_IRQHANDLER(void)
{
    GPT1_SR = GPT_SR_OF1;
    digitalToogleFast(23);
    // GPIO6_DR_TOGGLE = (1 << 25); // even faster.....
    asm volatile("dsb");
}

int main(void)
{
    pinMode(23, OUTPUT);

    uint32_t us = 1;

    CCM_CCGR1 |= CCM_CCGR1_GPT(CCM_CCGR_ON);     //enable clock for General Purpose Timer 1
    GPT1_CR = 0;
    GPT1_PR = 0;
    GPT1_SR = 0x3F;                              // clear all prior status
    GPT1_IR = GPT_IR_OF1IE;                      // enable GPT1 COMPARE 1 Interrupt
    GPT1_CR = GPT_CR_EN | GPT_CR_CLKSRC(1);      // sets timer clock to 24 MHz (Teensy 4)
    GPT1_OCR1 = 24000000 / 1000000 * us - 1 ;    // set compare value

    attachInterruptVector(IRQ_GPT1, GPT1_GPT_IRQHANDLER);
    NVIC_SET_PRIORITY(IRQ_GPT1, 0);
    NVIC_ENABLE_IRQ(IRQ_GPT1);

    for(;;)
    {
    }
}

Important in this example is the use of asm volatile("dsb") at the end of the ISR. Without that, the ISR will finish before the interrupt flag (first commend in the ISR) is cleared and the ISR will be called again, immediatly after leaving it. The result on the oscilloscope is, the pin goes down after ~60ns and not after 1us as expected.