T3.6 - Using an external clock for FTM timers

Status
Not open for further replies.

TelephoneBill

Well-known member
I was delighted yesterday when I stumbled upon a new feature that you can implement with Teensy 3.6 (K66) that you could not easily do with Teensy 3.1 (K20). This is to use an External Clock Signal with any of the FTM timers.

For example, suppose you have a 10 MHz sq wave from another electronic module (OCXO or similar), and you want to divide that signal by an integer value such as 10,000 to produce a 1 KHz sq wave (or any other integer up to 65,536). Or maybe you wish to accurately count the number of pulses from an external source using one of the FTM timers. This is now very simple to achieve with the enhanced port/pins multiplexing features available within T3.6.

If you study the table in para 11.3.1 (page 184) of the K66 Reference Manual, you may note a number of entries for two signals named FTM_CLKIN0 and FTM_CLKIN1 (e.g. PTB16 and PTB17). These same signals were also present with the K20 Reference Manual but only at PTA18 and PTA19, and because these same chip signal pins were also used for the external 16 MHz clock module, then they were NOT available for the end user. The K66 chip with Teensy 3.6 still uses PTA18 and PTA19 for the 16 MHz clock module, but now the signals FTM_CLKIN0 and FTM_CLKIN1 are repeated elsewhere in the table, so that they are available.

The following code gives a working practical example of dividing 10 MHz by 10,000 to produce 1 KHz. It uses FTM1 and outputs on CH0. If you choose to use some other external clock frequency, the reference manual warns you to ensure that the frequency does not exceed one quarter of the "System Clock" by which is meant the Peripheral Bus Clock of 60 MHz.

Note that the choice of FTM_CLKIN0 or FTM_CLKIN1 is made within the SIM_SOPT4 register (para 13.2.5, page 241). My example uses FTM_CLKIN0. If you run this code, you will see the LED blink 4 times as the Setup routine is executed, then each pass of the Main Loop will simply blink the LED twice in quick succession. The FTM timers operate without any intervention from the Main Loop, once configured and enabled in the Setup code.

Code:
//Teensy36 - Test Count of External Pulses
//========================================
// Author: TelephoneBill
// Date: 14 DEC 2016 - This T36 program counts 3 volt clock pulses from an external source (e.g. 10 MHz OCXO).
// Notes: The program uses the FTM_CLKIN0 signal input pin available on PTB16 (Teensy Pin 0) when configured for ALT4. This pin
// can accept external input pulses to be used by any of the FTM timers as a clock signal. FTM channels can then be used in the
// normal way to either measure a count value at a defined instant or to output a digital signal on attaining a count value. In
// this example, the 10 MHz input pulses are divided by a factor of 10,000 to give a 1 KHz square wave output on FTM1_CH0.
//
// Pins: Teensy Pin 0 (PTB16 ALT4) = FTM_CLKIN0 = 10 MHz from OCXO.
//       Teensy Pin 16 (PTB0 ALT3) = FTM1_CH0 = 1 KHz sq wave output (toggled).
// 
//declarations
#include  <stdint.h>
#define  LED_ON     GPIOC_PSOR=(1<<5)
#define  LED_OFF    GPIOC_PCOR=(1<<5)
int FTM1MODCount, LoopCount;

void setup() {
  // put your setup code here, to run once:
  //initialise general hardware
  PORTC_PCR5 = PORT_PCR_MUX(0x1); // LED PC5 pin 13, config GPIO ALT1
  GPIOC_PDDR = (1<<5);            // make this an output pin
  LED_OFF;                        // start with LED off

  //initialise variables
  FTM1MODCount = 4999;            //4999 modulus for each output half cycle (toggle)

  //initialise FTM_CLKIN0 and Flextimer 1 CH0
  FTM1_MODE = 0x05;   //set write-protect disable (WPDIS) bit to modify other registers
    //FAULTIE=0, FAULTM=00, CAPTEST=0, PWMSYNC=0, WPDIS=1, INIT=0, FTMEN=1(no restriction FTM)
  FTM1_SC = 0x00;     //set FTM1 Status/Control to zero = disabled (enabled later in setup)
  FTM1_CNT = 0x0000;  //reset count to zero
  FTM1_MOD = FTM1MODCount;
  FTM1_C0SC = 0x14;   // CHF=0, CHIE=0 (disable interrupt, use software polling), MSB=0 MSA=1, ELSB=0 ELSA=1 (output compare - toggle), 0, DMA=0

  //enable FTM1 interrupt within NVIC table
  NVIC_ENABLE_IRQ(IRQ_FTM1);

  //configure Teensy port pins  
  PORTB_PCR16 |= 0x400;  //MUX = FTM_CLKIN0 ALT4 on Chip Pin 95 (FTM1_CH0) = Teensy Pin 0
  PORTB_PCR0 |= 0x300;   //MUX = FTM1_CH0 ALT3 on Chip Pin 81 (FTM1_CH0) = Teensy Pin 16
  
  //initialise SIM_SOPT4
  SIM_SOPT4 = 0x00000000; //uses FTM_CLKIN0 for external clock signals
  
  //enable external clock (10 MHz), no prescale
  FTM1_C0V = 0;   //compare value = 0
  FTM1_SC = 0x58; //(Note - FTM1_SC [TOF=0 TOIE=1 CPWMS=0 CLKS=11 (external clocks enabled) PS=000 [no prescale divide])

  //blink 4 times
  Blink();
  delay(400);
  Blink();
  delay(400);
  Blink();
  delay(400);
  Blink();
  delay(400);
} //end of setup

// ISR routine for FlexTimer1 Module
extern "C" void ftm1_isr(void) {
  if ((FTM1_SC & FTM_SC_TOF) != 0) {  //read the timer overflow flag (TOF in FTM1_SC)
    FTM1_SC &= ~FTM_SC_TOF;           //if set, clear overflow flag
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  LoopCount++;
  if (LoopCount == 1000000) {
    LoopCount = 0;
    Blink();    
    delay(200);
    Blink();
  }
}

//SUBROUTINES
//===========
//Blink Routine
void Blink() {
  //blink the LED
  LED_ON;
  delay(10);
  LED_OFF;
  delay(10);
}
 
Thanks for that demo code, I would like to try it out! Given this is all done in the timer block hardware, not software, I assume the edge jitter on the output is no greater than that of the original input signal(?) But, I suppose all input and output signals are first synchronized to the internal bus clock.
 
Last edited:
That was my hope too :), but my initial scope display has probably confirmed your last comment.

When I use a 1pps from my Rubidium source (FE5680B) to trigger the scope on Trace1, the displayed 10 MHz signal (Morion OCXO) on Trace 2 has no appreciable jitter that I can witness using 50 ns/cm timebase. To see the 1 KHz on Trace3, I had to reduce the timebase to 500uS/cm - too coarse immediately to see. When I changed the trigger to be 1 KHz on Trace3, I did see uniform jitter on the 10 MHz signal of Trace2, and it appeared to be about 20nS wide.

This appears to confirm your suggestion that input/output will be synchronised to the internal bus clock. This presumably would cause jitter at the 60 MHz Peripheral Bus rate - 16 nS.

===

By the way, I had a thought to use this "External Clock" technique to increase the accuracy of my UBlox NEO-7M GPS 1pps (very cheap on eBay - $11 inc postage). My next experiment is to set an External Clock from a 10 MHz Double OCXO, and then employ four identical UBlox NEO7 GPS modules - each giving their own 1pps - and to connect these 1pps outputs to several FTM channels monitoring the External Clock, to "time freeze" a count value. I can then use some maths to compute drift in the Double OCXO (averaged over the four UBlox devices - with discard on outsiders?).

With a 4-averaged control calculation computed, then the idea is to use one of the Teensy 3.6 DACs in ultra fine control to regulate the Double OCXO frequency (both with 4096 voltage levels and dither control).

Why use four NEO-7Ms? First - they are ridiculously cheap. Second - this YouTube (https://youtu.be/2KboGLDADOA) indicates that three NEO-7Ms placed side by side don't always instantly agree with each other. The problem seems to be "gaining or losing a satellite from lock" can skew the internal timing. Occasionally this can be very significant. Using a "voting technique", I'm hoping for a better precision answer.

Another interesting fact using this "External Clock" idea is that I can configure some modules to monitor US GPS, other Russian GLONASS, and maybe even add in UK MSF contribution.
 
Last edited:
Yes, I think any micro has to synchronize its inputs to its own clock. To avoid jitter on output, you would have to make your reference frequency directly drive the microcontroller clock itself. That's what I did in this PIC project anyway: http://www.bealecorner.com/pcb/dd1/
 
This is probably why the ref manual stipulates that the External Clock frequency be less than one quarter of the Peripheral Bus Clock ?? (I suspect that this same "phenomena" is also apparent in the YouTube video with the UBlox 1pps?)

From your last comment, I'm wondering if the FTM jitter could be reduced by synchronising the Peripheral Bus Clock (60 MHz) using the OSC0_CR digital capacitor "dither" adjustment technique to the 10 MHz OCXO External Clock? Hmm, might be worth testing this - tweaking the dithering rate manually to get the Teensy crystal temporarily synched to the OCXO... I'll try it and see what happens...
 
Interesting update.

I edited the kinetis.h file to overclock cpu to 240 MHz and the FBUS clock (for peripherals) to 120 MHz. The effect was to reduce the jitter on the 10 MHz trace (when triggering from the 1 KHz trace = FTM1 CH0 toggle output) down to just over 8 nanoSecs.

This is just as expected from a 120 MHz peripheral clock rate (period = 8.3 nanoSecs).
 
Another interesting update.

This time I used the internal bus clock and Flextimer FTM0 to generate a 1 KHz sq wave output on Teensy pin 25 via channel CH2 (Alt F3). I used a MODULUS value of 59,999 which with the "toggle action" of CH2 divides the peripheral bus clock by 120,000 (2 times 60,000 effectively) and as the bus clock is 120 MHz then this results in an output frequency of exactly 1 KHz.

To gauge the accuracy of this signal, I compare it on a scope against a precision external 10 MHz OCXO oscillator (checked against a Rubidium standard). I adjusted the frequency slightly of the 1 KHz (which was the scope trigger) by altering the bus clock rate in order to get EXACT synchronism of the two signals (stationary traces on the scope). This was done by slowly tuning the Teensy 3.6 crystal module frequency (16 MHz) using the digital capacitors set to a value of "0x02", and then carefully "breathing on the module casing" to increase its ambient temperature. For a few moments, the 10 MHz trace became completely stationary on screen, allowing me to take a snapshot of the amount of jitter.

The result is shown in the picture below. Trace3 (purple) is the leading edge of the 1 KHz and the timebase is 10 nanoSecs per cm. Trace 2 (light blue) is the stationary 10 MHz OCXO signal. Notice that there is almost zero jitter on the 10 MHz trace (less than 2 nanoSecs). This validates the previous comments that if the bus clock is fully synchronised to an external signal, then there will be no effective jitter caused by the internal clocking rate.

JitterOn10MHzTrigger1KHz.jpg
 
Is there any reason why pins 7 and 9 on a Teensy 3.6 would not accept a clock pulse?

My response is in the context of this subject of "T3.6 - Using an external clock for FTM timers". If you are not using FTM timers, then my comment won't be relevant for you.

As far as I can see from the schematic diagram for T3.6, pins 7 and 9 are associated with PTD2 and PTC3. If you have not studied the "schematic" to see which pins are associated with which ports then please do - it's very informative (use Google to find it).

The table in para 11.3.1 for these port pins of PTD2 and PTC3 (page 190 and page 188 of the K66 Reference Manual) does not have an option for these port pins to be configured as FTM_CLOCKIN0 or FTM_CLOCKIN1. So in terms of using these pins to accept an external clock for the FTM timers, then it just ain't possible. That was the point of paragraph 3 in the post #1 above.

When you see the schematic, look at Teensy pin 0 and see how this is associated with PTB16 - then you will see what I'm indicating. PTB16 can be configured as FTM_CLOCKIN0 as page 188 of the reference manual shows.

(I suspect you may really be wanting to ask a different question - but the schematic is still useful).
 
Status
Not open for further replies.
Back
Top