Hi all,
i'm wanting to do 48-bit timing on a Teensy 4.0. The only way i can do that is to use the QUADTimers and cascade them. After testing the QUADTimers i was able to determine that they run at 150MHz and based on the largest value i will need to use i have decided to run the timer at a pre-scaler of 1 with 3 timer channels cascaded. See code below.
I've based my code on this post...
https://forum.pjrc.com/threads/61462-Teensy4-QuadTimer-as-64-bit-counter?highlight=cascade+timer
I've gotten the QTimer and it's ISR to run ok and i can get it to run for the lengths of time i need. The counter values being printed to the serial port all look good. The problem i am having is trying to figure out how to get a timer to activate an ISR at the right time. As you can see in the code below, i have a function named calcBinary(). This function is my way of trying to get the binary values for each timer to match a value of 9,000,000,000 clock ticks. This is just a test value within my expected range. The printout of the values for the 3 timers works fine (16-bits binary) and i get an accurate result that matches my own calculations. These binary values would be used for compare matching. The problem is that all 3 timer channels would then be compare matching and activating their interrupts when they get a match. I just want 1 of the 3 channels to activate an ISR.
So how do i go about doing that? I don't want to have any code in the loop() function as that would negate the point of running hardware timers in the first place. I want accuracy in the low nanoseconds. With a 150MHz timer clock i can get 6.67r nanoseconds per timer clock tick which is great. That will produce nice, stable and accurate square waves.
Does anyone (maybe manitou?) have a suggestion for me to figure out when a certain number of timer clock ticks have passed?
Any help is appreciated.
Also, what does the code below do?
Cheers
NM
i'm wanting to do 48-bit timing on a Teensy 4.0. The only way i can do that is to use the QUADTimers and cascade them. After testing the QUADTimers i was able to determine that they run at 150MHz and based on the largest value i will need to use i have decided to run the timer at a pre-scaler of 1 with 3 timer channels cascaded. See code below.
I've based my code on this post...
https://forum.pjrc.com/threads/61462-Teensy4-QuadTimer-as-64-bit-counter?highlight=cascade+timer
I've gotten the QTimer and it's ISR to run ok and i can get it to run for the lengths of time i need. The counter values being printed to the serial port all look good. The problem i am having is trying to figure out how to get a timer to activate an ISR at the right time. As you can see in the code below, i have a function named calcBinary(). This function is my way of trying to get the binary values for each timer to match a value of 9,000,000,000 clock ticks. This is just a test value within my expected range. The printout of the values for the 3 timers works fine (16-bits binary) and i get an accurate result that matches my own calculations. These binary values would be used for compare matching. The problem is that all 3 timer channels would then be compare matching and activating their interrupts when they get a match. I just want 1 of the 3 channels to activate an ISR.
So how do i go about doing that? I don't want to have any code in the loop() function as that would negate the point of running hardware timers in the first place. I want accuracy in the low nanoseconds. With a 150MHz timer clock i can get 6.67r nanoseconds per timer clock tick which is great. That will produce nice, stable and accurate square waves.
Does anyone (maybe manitou?) have a suggestion for me to figure out when a certain number of timer clock ticks have passed?
Any help is appreciated.
Also, what does the code below do?
Code:
IMXRT_TMR_t * TMR4 = (IMXRT_TMR_t *)&IMXRT_TMR4;
#define IRQ_QTIMERx IRQ_QTIMER4
Code:
#include <SPI.h>
#include <elapsedMillis.h>
IMXRT_TMR_t * TMR4 = (IMXRT_TMR_t *)&IMXRT_TMR4;
#define IRQ_QTIMERx IRQ_QTIMER4
elapsedMillis freerunTimer;
uint32_t timed = 0;
uint16_t countTimeMillis = 0;
uint16_t prevCountTimeMillis = 0;
void my_isr() {
TMR4->CH[1].CSCTRL &= ~(TMR_CSCTRL_TCF1); // clear
countTimeMillis = freerunTimer;
Serial.println("my_isr() CALLED !!!");
}
void setup() {
Serial.begin(115200);
Serial.println("=================");
Serial.println(" Teensy 4 Timers ");
Serial.println("=================");
// set up QuadTimer4
CCM_CCGR6 |= CCM_CCGR6_QTIMER4(CCM_CCGR_ON); // enable QTMR4 clock
TMR4->CH[0].CTRL = 0; // stop
TMR4->CH[1].CTRL = 0; // stop
TMR4->CH[2].CTRL = 0; // stop
TMR4->CH[0].CNTR = 0; // set count to 0
TMR4->CH[1].CNTR = 0; // set count to 0
TMR4->CH[2].CNTR = 0; // set count to 0
TMR4->CH[0].COMP1 = 0xffff; // send count signal to next counter on overflow at 0xffff
TMR4->CH[1].COMP1 = 0xffff; // send count signal to next counter on overflow at 0xffff
TMR4->CH[2].COMP1 = 0xffff; // send count signal to next counter on overflow at 0xffff
TMR4->CH[0].CMPLD1 = 0xffff;
TMR4->CH[1].CMPLD1 = 0xffff;
TMR4->CH[2].CMPLD1 = 0xffff;
TMR4->CH[2].CTRL = TMR_CTRL_CM (7); // Count Mode: Cascaded counter mode
TMR4->CH[2].CTRL |= TMR_CTRL_PCS(5); // Primary Count Source: CH[1] output
TMR4->CH[1].CTRL = TMR_CTRL_CM (7); // Count Mode: Cascaded counter mode
TMR4->CH[1].CTRL |= TMR_CTRL_PCS(4); // Primary Count Source: CH[0] output
TMR4->CH[0].CTRL = TMR_CTRL_CM (1); // Count Mode: Count rising edges of primary source
TMR4->CH[0].CTRL |= TMR_CTRL_PCS(8); // Primary Count Source: IP bus clock divide by 1 prescaler
attachInterruptVector(IRQ_QTIMERx, my_isr);
TMR4->CH[1].CSCTRL &= ~(TMR_CSCTRL_TCF1); // clear
TMR4->CH[1].CSCTRL |= TMR_CSCTRL_TCF1EN; // enable interrupt
NVIC_ENABLE_IRQ(IRQ_QTIMERx);
calcBinary();
freerunTimer = 0;
}
void calcBinary() {
uint64_t thisNumber = 9000000000;
uint16_t timer1Number = thisNumber;
uint16_t timer2Number = thisNumber >> 16;
uint16_t timer3Number = thisNumber >> 32;
Serial.print("timer1Number = ");
Serial.print(timer1Number);
Serial.print(", ");
Serial.println(timer1Number, BIN);
Serial.print("timer2Number = ");
Serial.print(timer2Number);
Serial.print(", ");
Serial.println(timer2Number, BIN);
Serial.print("timer3Number = ");
Serial.print(timer3Number);
Serial.print(", ");
Serial.println(timer3Number, BIN);
}
void loop() {
if (countTimeMillis != prevCountTimeMillis) {
Serial.println("TMR4->CH[1] OVERFLOW ");
Serial.print("countTimeMillis = ");
Serial.println(countTimeMillis);
prevCountTimeMillis = countTimeMillis;
}
Serial.println(TMR4->CH[0].CNTR);
Serial.println(TMR4->CH[1].CNTR);
Serial.println(TMR4->CH[2].CNTR);
Serial.println();
delay(200);
}
Cheers
NM