Running a timer off an external clock signal on Teensy 4.1?

darkextratoasty

New member
Can any of the timers within the Teensy 4.1 be incremented using an external clock signal, rather than the internal oscillator clock?
My goal is to have a timer running off an external 10MHz square wave signal. I could then have a pulse on a different pin, for example a 1PPS signal from a GPS receiver, trigger an interrupt that grabs the current value of the externally driven timer as a timestamp for when that pulse arrived. The idea here is to have a system for timestamping a pulse with a resolution of 100nS (10MHz clock), but I would like to be able to run the timer off an external signal so that I can use a much more accurate clock than the teensy's onboard oscillator.
  1. Is it possible at all to run any of the timers in the Teensy 4.1 off an external clock?
  2. If so, is it reasonable to expect an ISR that reads the value of a timer and stores it into a variable to run within a handful of nanoseconds before the next external clock cycle increments the timer again.
  3. Does my approach make sense fundamentally, or is there a better way to do this?
  4. If so, would it still make sense with say, ten different trigger pulses?

Also, I apologize if this has been answered before, I wasn't able to find anything, but that could easily be due to my ignorance of keywords to use in my searching.
 
Quick answers

Is it possible at all to run any of the timers in the Teensy 4.1 off an external clock?

I believe the GPT timers might able to do this. In the reference manual, see Figure 52-2 on page 3015, and section 52.3.1 on page 3016.

The GPT timers are also 32 bits wide, which is much simpler than dealing with only 16 bits that overflows so quickly.


  1. Does my approach make sense fundamentally, or is there a better way to do this

You would probably want to use the GPT input capture feature. The hardware can capture its current count entirely in hardware, and then give you an interrupt so you can leisurely read the captured value without adding any software latency to the measurement. See 52.3.2 on page 3016.
 
Some pin mapping info which might help:

GPT2_CLK is on pin 14 (AD_B1_02 mux = ALT8)
GPT2_CAPTURE1 is on pin 15 (AD_B1_03 mux = ALT8)
GPT2_CAPTURE2 is on pin 40 (AD_B1_04 mux = ALT8) - Teensy 4.1 only
 
I believe the GPT timers might able to do this. In the reference manual, see Figure 52-2 on page 3015, and section 52.3.1 on page 3016.
It indeed appears that they will do exactly what I'm looking for.
GPT input capture feature
That is a tremendously helpful feature.
Some pin mapping info which might help:

GPT2_CLK is on pin 14 (AD_B1_02 mux = ALT8)
GPT2_CAPTURE1 is on pin 15 (AD_B1_03 mux = ALT8)
GPT2_CAPTURE2 is on pin 40 (AD_B1_04 mux = ALT8) - Teensy 4.1 only
I was just about to start searching for this information.

Thank you for the quick, very helpful answer Paul. Now I need to do some research to figure out how to configure GPT2 to clock off an external signal, how to load GPT2's value into a register on a capture signal, and how to read that register once it's stored said value.
 
One small gotcha... before you access any of the GPT2 registers, enable its clocks by setting the CCM_CCGR0_GPT2_BUS and CCM_CCGR0_GPT2_SERIAL bits in the CCM registers.
 
To configure the input pins, you'll need to write to the mux registers and also the select input registers.

IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02
IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03
IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_04

IOMUXC_GPT2_IPP_IND_CAPIN1_SELECT_INPUT
IOMUXC_GPT2_IPP_IND_CAPIN2_SELECT_INPUT
IOMUXC_GPT2_IPP_IND_CLKIN_SELECT_INPUT
 
The quad timers can also run off an external signal, up to a frequency of bus clock / 2 (typically 75MHz). They're 16-bits, but multiple timers can be cascaded to get 32-bits.
 
One small gotcha... before you access any of the GPT2 registers, enable its clocks by setting the CCM_CCGR0_GPT2_BUS and CCM_CCGR0_GPT2_SERIAL bits in the CCM registers.
...
To configure the input pins, you'll need to write to the mux registers and also the select input registers.

IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02
IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03
IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_04

IOMUXC_GPT2_IPP_IND_CAPIN1_SELECT_INPUT
IOMUXC_GPT2_IPP_IND_CAPIN2_SELECT_INPUT
IOMUXC_GPT2_IPP_IND_CLKIN_SELECT_INPUT
Once I figure out how to do all that in Arduino code, I'll be sure to keep that little gotcha in mind 😅
The quad timers can also run off an external signal, up to a frequency of bus clock / 2 (typically 75MHz). They're 16-bits, but multiple timers can be cascaded to get 32-bits.
I might end up using both the GPTs and quad timers, ideally I'd like to have eight different trigger pulses, but with each GPT having only two capture pins, it seems I might be limited to four triggers using just the GPTs. I could OR the trigger pulses and have each capture pin connected to multiple triggers. That would probably work if the triggers are sufficiently far apart, but I'd worry about them being too close and the second trigger overwriting the capture register's value before I got the chance to read the value from the first trigger. If the quad timers have similar capture input features, then I could use two cascaded sets of two timers to get an additional two 32-bit timers. If I'm lucky, that might get me eight capture input pins, one for each trigger pulse. However, it seems that I've got a lot of reading and experimenting ahead of me before I can say if that actually works or not.
 
Back
Top