You can use the TeensyTimerTool for this. It provides a generic interface to the hardware timers (TMR, GPT, PIT) and 20 software timers. Since the coupling of the timer peripherals to the ARM core is rather inefficient, the software timers might be a better fit for sub micro second interrupts. If you prefer the hardware timers I suggest to use a GPT timer (also supported by the lib). You can configure it to use a 150MHz clock instead of the standard 24MHz clock. So something like 2MHz interrupt rate should be feasible.
Documentation can be found here: https://github.com/luni64/TeensyTimerTool/wiki
Answer from luni64 on Stack ExchangeYou can use the TeensyTimerTool for this. It provides a generic interface to the hardware timers (TMR, GPT, PIT) and 20 software timers. Since the coupling of the timer peripherals to the ARM core is rather inefficient, the software timers might be a better fit for sub micro second interrupts. If you prefer the hardware timers I suggest to use a GPT timer (also supported by the lib). You can configure it to use a 150MHz clock instead of the standard 24MHz clock. So something like 2MHz interrupt rate should be feasible.
Documentation can be found here: https://github.com/luni64/TeensyTimerTool/wiki
I had a similar problem with the Teensy 3.5. I found that using the "Periodic Interrupt Timer (PIT)" let me generate interrupt every 300 ns. I imagine that with a Teensy 4.0, it must be possible to generate an interrupt every 100 ns. Here is the code which works for me on my Teensy 3.5, with comments in french and some references in the comments. I test the signal on an oscilloscope.
// ex00305_Timer_pit0_isr_rapide.ino
/*
FONCTIONNE TRES BIEN
Le signal n'est pas très stable, mais acceptable.
J'imagine que d'autres routines d'interruption perturbe la précision, comme la routine millis()
L'instruction suivante améliore la stabilité. visiblement.
NVIC_SET_PRIORITY(IRQ_PIT_CH0, 0);
Le but est de tester l'utilisation du Timer1 .c.f
/home/bg/Arduino/Teensy/Teensy_3_5_manual_K64P144M120SF5RM.pdf
Page 1083, Chapter 41 : "Periodic Interrupt Timer (PIT)"
Pour la gestion des timers PIT, c.f.
====================================
https://github.com/loglow/PITimer/blob/master/PITimer.cpp
********************************************************************************** */
#define PINOUT1 34
#define LEDRED 24
#define LEDYELLOW 25
#define LEDGREEN 26
volatile byte bEtat = 0;
void setup() {
//============
pinMode(PINOUT1, OUTPUT);
digitalWriteFast(PINOUT1, HIGH);
pinMode(33, OUTPUT);
pinMode(34, OUTPUT);
pinMode(LEDRED, OUTPUT); digitalWriteFast(LEDRED, LOW);
pinMode(LEDYELLOW, OUTPUT); digitalWriteFast(LEDYELLOW, LOW);
pinMode(LEDGREEN, OUTPUT); digitalWriteFast(LEDGREEN, LOW);
//if (SIM_SCGC6_PIT == 0b100000000000000000000000) digitalWriteFast(LEDYELLOW, HIGH);
SIM_SCGC6 |= SIM_SCGC6_PIT; // C.f. page 317. PIT Clock Gate Control SIM_SCGC6_PIT == 0b100000000000000000000000
// C.f. : /home/bg/.arduino15/packages/teensy/hardware/avr/1.58.1/cores/teensy3/kinetis.h
// #define NVIC_ENABLE_IRQ(n) (*((volatile uint32_t *)0xE000E100 + ((n) >> 5)) = (1 << ((n) & 31)))
// enable IRQ Interrupt
NVIC_SET_PRIORITY(IRQ_PIT_CH0, 0); // Haute priorité, pour ne pas être perturbé par d'autres interrupt. Amélioration visible !
NVIC_ENABLE_IRQ(IRQ_PIT_CH0);
PIT_TCTRL0 = 3; // 0b011; // enable Timer 0 interrupts ; start Timer 0 IRQ_PIT_CH0 == 48 Dans #elif defined(__MK64FX512__)
//if (IRQ_PIT_CH0 == 48) digitalWriteFast(LEDGREEN, HIGH);
// Efface le flag du timer, pour permettre d'autres interruptions, nécessaire au départ
PIT_TFLG0 = 1;
// L'ordre des instruction a de l'importance !
//""""""""""""""""""""""""""""""""""""""""""""
PIT_MCR = 0; // turn on PIT
//PIT_LDVAL0 = 600-1; // == 10 micro secondes setup timer 0 for xxx cycles Fréqu = 60 MHz dt = 16.666 ns
//PIT_LDVAL0 = 120-1; // == 2 micros second
//PIT_LDVAL0 = 60-1; // == 1 micros second
//PIT_LDVAL0 = 30-1; // == 500 ns
//PIT_LDVAL0 = 24-1; // == 400 ns
//PIT_LDVAL0 = 21-1; // == 350 ns
//PIT_LDVAL0 = 20-1; // == 333 ns
//PIT_LDVAL0 = 18-1; // == 300 ns
PIT_LDVAL0 = 120-1;
} // setup
void loop() {
//===========
} // loop
void pit0_isr() { // C.f. mk20dx128.c
//===============
// J'espère pouvoir gérer un temps
// Efface le flag du timer, pour permettre d'autres interruptions
// Doit être mis en début de routine !!!
PIT_TFLG0 = 1;
if (bEtat) {
digitalWriteFast(PINOUT1, HIGH);
//digitalWriteFast(LEDRED, HIGH);
bEtat = 0;
}
else {
bEtat = 1;
digitalWriteFast(PINOUT1, LOW);
//digitalWriteFast(LEDRED, LOW);
}
} // pit0_isr