32-bit Counter Driven by an External 10MHz clock (Teensy 4.0) - Feasible?

Thanks in advance for your help with this!

I'd like to use a Teensy 4.0 to implement a 32-bit counter driven by an external 10 MHz clock - the clock source would be a Rubidium Frequency Standard.

The counter would be free-running, and when an input pin goes high, the current 32-bit counter value would be captured and sent to another device via a serial port.

So basically, I just want the Teensy to send me the current 32-bit timestamp whenever the event occurs.

It looks like this should be a fairly straightforward project(?) Are there any issues I should be concerned about - or should I just order a Teensy 4.0 and start coding :)

Thanks again,
John
 
This is basically what the FreqMeasure library does. It captures the timer on every rising edge. So that part should be pretty easy. The timer clocks from the 150 MHz peripheral clock. In this case, you would normally see it capture 15, but you would get occasional 16 or 14 if Teensy's crystal varies relative to the reference 10 MHz.

Sending 10 million 32 bit numbers per second is a lot of bandwidth. The USB port can probably do about half this much, if connected to a fast PC running efficient software. The ordinary non-USB serial ports have a maximum baud rate of 6 Mbit/sec, which is far too slow to transmit so much.
 
This is basically what the FreqMeasure library does. It captures the timer on every rising edge. So that part should be pretty easy. The timer clocks from the 150 MHz peripheral clock. In this case, you would normally see it capture 15, but you would get occasional 16 or 14 if Teensy's crystal varies relative to the reference 10 MHz.

Sending 10 million 32 bit numbers per second is a lot of bandwidth. The USB port can probably do about half this much, if connected to a fast PC running efficient software. The ordinary non-USB serial ports have a maximum baud rate of 6 Mbit/sec, which is far too slow to transmit so much.

Hi Paul - Thanks for your quick response!

I'll take a look at the FreqMeasure library - sounds like that should get me started - but what I want to do is a little different than what you described...

I want the timer CLOCK SOURCE to be the external 10MHz Rubidium Clock - so the timer would increment at a 10MHz rate. And the events that I want to timestamp will be 1 or 2 minutes apart, so bandwidth on the serial port shouldn't be an issue.

Are there any hardware issues using an external pin for the timer clock source instead of the 150MHz periperal clock?
 
Update:
After doing some searching on the forum and the Processor Reference Manual, it appears the GPT2 clock input (GPT2_CLK) and capture control input (GPT2_Capture1) are easily accessible on the Teensy 4.0 board. Just ordered a Teensy 4.0, so should be able to do some testing in a few days! :)

The goal of my project is to see if I can detect the small changes in gravity due to the position of the sun and moon. These changes due to gravity, "g," and are what cause tides. I'm measuring the period of a pendulum which is inversly proportional to "g."

I actually started this project 10 (!) years ago and had to put it on hold due to life events that had a higher priority. The pendulum is driven by a "motor" (coil and magnet) that give it a small kick on every pass. I learned early on that the biggest error source was the length of the pendulum changing due to temperature, so it's now inside a temperature controlled box. A recent revelation was that I need to integrate the period over multiple cycles in order to have enough resolution to see the small (10^-7) variations in gravity. Previously, I was only looking at individual (1s nominal) periods and I see now that with a 10MHz reference, there was no way I could detect changes that small.

My Rubidium reference is supposedly accurate on the order of 10^-11, so that should be good enough. The big adventure will be finding what other sources of error turn up! :)
 
Rubidium clocks have good short term stability, but don't do that well long term. Over what time period are you requiring stability. For a detailed explanation search NIST papers. If you are effectively integrating over a long time period then you may need a long term stable clock. See Clock Characterization Tutorial by David Allen.
 
here is small sketch to test GPT with external clock (pin 14) and and capture with pin 15
Code:
// GPT2 external clock (GPS 8 mhz) into pin 14,   PPS captured to pin 15
//https://forum.pjrc.com/threads/54265-Teensy-4-testing-mbed-NXP-MXRT1050-EVKB-(600-Mhz-M7)?p=193217&viewfull=1#post193217
// CLKSRC 1 24mhz or 150mhz  3 external  4 32khz
// 1062 capture pin 15  Serial3 Rx    test with GPS pps or pwm on pin 14
// GPT2 capture 1 GPIO_AD_B1_03   Alt 8
// external pin is 14 GPIO_AD_B1_02 ALT8  (Frontside - A0) Serial3 Tx

void setup() {
  Serial.begin(9600);
  while (!Serial);
  delay(2000);
  Serial.println("ok");
  pinMode(13, OUTPUT);

  //  analogWriteFrequency(14, 100);  // test with PWM
  //  analogWrite(14, 128); // jumper pwm 14  to pin 15  Serial3 on T4B2 breakout
  // Connect GPS 1PPS signal to pin 15 (GPIO_AD_B1_03)
  IOMUXC_GPT2_IPP_IND_CAPIN1_SELECT_INPUT = 1;  // remap GPT2 capture 1
  IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03 = 8; // GPT2 Capture1
  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_03 = 0x13000; //Pulldown & Hyst
  // external clock pin 14
  IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02 = 8;
  IOMUXC_GPT2_IPP_IND_CLKIN_SELECT_INPUT = 1;
  // uncomment following for 150mhz, required if external > 8mhz
  CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL; // turn off 24mhz mode
  CCM_CCGR0 |= CCM_CCGR0_GPT2_BUS(CCM_CCGR_ON) |
               CCM_CCGR0_GPT2_SERIAL(CCM_CCGR_ON);  // enable clock
  GPT2_CR = 0;
  GPT2_PR = 0;
  GPT2_SR = 0x3F; // clear all prior status
  GPT2_IR = GPT_IR_IF1IE;
  GPT2_CR = GPT_CR_EN | GPT_CR_CLKSRC(3) |   // SRC 1 24 or 150mhz  3 external clock
            GPT_CR_FRR | GPT_CR_IM1(1);
  attachInterruptVector(IRQ_GPT2, capture);
  NVIC_ENABLE_IRQ(IRQ_GPT2);
}


volatile uint32_t delta, captured;

void capture() {
  static uint32_t prior = 0;
  uint32_t ticks = GPT2_ICR1;
  GPT2_SR = GPT_SR_IF1;
  delta = ticks - prior;
  prior = ticks;
  asm("dsb");
  captured = 1;
}

void loop() {
  if (captured) {
    Serial.println(delta);
    captured = 0;
  }
}

I tested with a signal generator at 10mhz to Teensy pin 14 and GPS PPS as trigger on pin 15 so I could measure accuracy of generator.
 
Last edited:
Rubidium clocks have good short term stability, but don't do that well long term. Over what time period are you requiring stability. For a detailed explanation search NIST papers. If you are effectively integrating over a long time period then you may need a long term stable clock. See Clock Characterization Tutorial by David Allen.

Thanks for that insight and pointer! It seems NIST has lots of relavant information for this kind of stuff - I also found this paper: https://www.nist.gov/system/files/documents/calibrations/ie79-7.pdf . Table 1 shows typical stability for commercial Rubidium clocks at 10^-13 @ 1 day and 10^-10 @ 1 year, so I think I'm still "in the ballpark." :)

If I can get all the other(!) error sources under control, I should be able to see tidal variations in gravity over a period of a few days.

BTW, I've got the Teensy 4.0 code running now for the 32-bit counter and external clock. I'm away from home this weekend, but I'll post the code here next week. Just running tests now, but last Friday with the 1PPS signal from the Rubidium standard connected to the Capture input, it showed exactly 10,000,00 counts every second for several hours. That is, unless I key up my HF ham radio transmitter! But that's not surprising - and I can deal with that! :)
 
Here's the (working) test code. Not sure how to get this to display in the message body(?)
 

Attachments

  • FPC_Counter_Test_2.ino
    1.6 KB · Views: 16
You can paste in sketch with code tags (click on #)
Code:
// Code to test Teensy 4.0 GPT2 Counter with External Clock

void setup()
{
    // Setup USB serial port so we can print the timer value
    Serial.begin(115200);

    // Configure GPT2 external clock on pin 14 (GPIO_AD_B1_02)
    pinMode(14, INPUT);
    IOMUXC_GPT2_IPP_IND_CLKIN_SELECT_INPUT = 1;
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02 = 8;
    
    // Configure GPT2 capture signal on pin 15 (GPIO_AD_B1_03)
    pinMode(15, INPUT);
    IOMUXC_GPT2_IPP_IND_CAPIN1_SELECT_INPUT = 1; 
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03 = 8; 
    
    // Configure GPT2 clocks    [COLOR="#0000FF"]
    CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL; // turn off 24mhz mode[/COLOR]
    CCM_CCGR0 |= CCM_CCGR0_GPT2_BUS(CCM_CCGR_ON)  /* Enable GPT2 clocks */
           |  CCM_CCGR0_GPT2_SERIAL(CCM_CCGR_ON); 

    // Configure GPT2 registers
    GPT2_CR = 0;          /* Disable for configuration */
    GPT2_SR = 0x3F;       /* Clear status flags */
    GPT2_CR               /* Setup Control Register */           
      |= GPT_CR_IM1(2)    /* Capture input on falling edge */ 
      |  GPT_CR_CLKSRC(3) /* Use External clock on pin 14 */
      |  GPT_CR_EN;       /* Enable timer */
}

uint32_t oldSample = 0;
uint32_t newSample;
uint32_t delta;

void loop()
{
    // Print delta when a capture occurs
    if(GPT2_SR & GPT_SR_IF1){         /* Check for flag */
      newSample = GPT2_ICR1;          /* Get new sample */
      delta = newSample - oldSample;  /* Calculate delta */
      Serial.println(delta);          /* Print delta */
      oldSample = newSample;          /* Update oldSample */
      GPT2_SR |= GPT_SR_IF1;          /* Clear flag */
    }
}

In my testing, for external clock frequency greater than 8 MHz, one needs to enable 150MHz bus clock (see CCM_CSCMR1 ), or maybe 6MHz was the threshold? T4 reference manual says: "The External Clock frequency is limited to < 1/4 frequency of the Peripheral Clock (ipg_clk) for proper GPT operations."

In my generator tests, I was able to run GPT external clock up to 66 MHz. Need short jumpers for high frequency tests.
 
Last edited:
BTW, I've got the Teensy 4.0 code running now for the 32-bit counter and external clock. I'm away from home this weekend, but I'll post the code here next week. Just running tests now, but last Friday with the 1PPS signal from the Rubidium standard connected to the Capture input, it showed exactly 10,000,00 counts every second for several hours. That is, unless I key up my HF ham radio transmitter! But that's not surprising - and I can deal with that! :)

Re: GPS PPS frequency

with Rubidium 10mhz to pin 14 and a GPS PPS to pin 15, what response do you see? Do you have a GPS with external antenna and good view of sky?
 
Back
Top