Fastest possible speed on IntervalTimer

hemsy

Active member
This program should toggle the LED at pin 13. I've played with values for the timer period in 0.1 microsecond increments. Below a certain value, the LED stops toggling (evident on a scope), and the Teensy hangs up (button has to be pushed in order to get back into program mode, my informal indication that I've done something wrong).

About 0.7 microseconds on Teensy 3.6
About 1.6 microseconds on Teensy 4.0

I assume these details are due to how the microcontrollers handle interrupts. It creates a bit of a dilemma, since I want to run an ADC at 1 MHz, but also want the horsepower of the T4.0 board. Right now my ADC runs nicely at 250 kHz inside an IntervalTimer loop, and I'd like to replace it with a 1 MHz part, plus use the Teensy 4.0 for a screaming fast FFT.

Code:
IntervalTimer myTimer;

volatile int i;

void timerISR(){
  i++;
}

void setup() {
  pinMode(13, OUTPUT);
  myTimer.priority(0);
  myTimer.begin(timerISR, 1.5);
}

void loop() {
  while(1) digitalWriteFast(13, i%2);
 
Yes it looks like the current code restricts it to 1.5us... That is if you look at the begin method with floating point:
On T4
Code:
	bool begin(void (*funct)(), float microseconds) {
		if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
		uint32_t cycles = (float)(24000000 / 1000000) * microseconds - 0.5;
		if (cycles < 36) return false;
		return beginCycles(funct, cycles);
	}
On T3.6 it has similar code:


So: (float)(24000000 / 1000000) * microseconds - 0.5; is 24*1.5 = 36...
And it errors out if < 36...

Code:
	bool begin(void (*funct)(), float microseconds) {
		if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
		uint32_t cycles = (float)(F_BUS / 1000000) * microseconds - 0.5;
		if (cycles < 36) return false;
		return beginCycles(funct, cycles);
	}
But it is based off of F_BUS instead of 24mhz.

Now on T4, I believe the PIT clock is currently configured to be OSC clock as you will see in startup.c
Code:
	CCM_CSCMR1 = (CCM_CSCMR1 & ~CCM_CSCMR1_PERCLK_PODF(0x3F)) | CCM_CSCMR1_PERCLK_CLK_SEL;
	// UARTs run from 24 MHz clock (works if PLL3 off or bypassed)
There appears to be the ability to choose a different system clock here, BUT my guess it will impact tons of things.
(Page 1072 in the PDF file).

So I would probably not touch...
This is not a subsystem I have touched much, but not sure how much it would impact the system if the if (cycles < 36) return false;
constraint was changed down to: if (cycles < 24) return false;
Which could give you microsecond... But again I have not tried it, not sure if there are constraints elsewhere, but it appears like it just stuffs it into a hardware register at that point....
 
I'm afraid you won't get much faster than this and even that generates a significant load on the T4. Here https://forum.pjrc.com/threads/57959-Teensy-4-IntervalTimer-Max-Speed some information on the performance of the interval timer. Unfortunately the access to the timer registers quite slow. Together with the new combined interrupt request of the PIT timers this leads to a surprisingly low performance of the timers. The GPT is slightly better since it has a dedicated interrupt for each timer.

If somebody has some tricks to improve the timer performance I would be very interested in it.

Here some background info from Joseph Yiu https://community.arm.com/developer/ip-products/processors/f/cortex-m-forum/10389/dmb-dsb-isb-on-cortex-m3-m4-m7-single-core-parts (scroll down to the discussion about slow peripherals)
 
Thanks for the help! Is this an area where I should be exploring the use of DMA? Admittedly it's something I haven't played with yet.
 
As far as I know, getting data at a high, fixed rate of speed is what DMA is intended for.
 
Back
Top