🛠 Timers matériels, interruptions imbriquées et FASTRUN : la vitesse Cortex-M4
Objectives
Move away from delay and polling: the Teensy 3.2 hides a true real-time powerhouse — a Nested Vectored Interrupt Controller (NVIC) with priorities, 16 general-purpose DMA channels, a suite of timers (PDB, CMT, LPTMR, 4 PIT counters, PWM FTM timers), the FASTRUN keyword for executing functions from RAM, and a dual 32-bit bus (simultaneous instruction fetch + data). This tutorial blinks LED 13 using a hardware IntervalTimer and measures the gains of a tight toggle loop.
Hardware
- 1 Teensy 3.2 (the orange LED on pin 13 is sufficient)
- Optional: oscilloscope or logic analyzer on a free pin to measure frequencies
Complete Code
digitalToggle and the IntervalTimer class are documented on the PJRC shop page (sections Digital Output Pins / Timing):
#include <IntervalTimer.h>
IntervalTimer t1;
volatile bool flashing = false;
void flash { // execute depuis un timer materiel, pas la boucle
digitalToggle(13); // broche 13 = LED orange integrée
}
void setup {
pinMode(13, OUTPUT);
t1.priority(0); // attention : sur Teensy, 0 = priorite LA PLUS haute
t1.begin(flash, 500000); // appelle flash toutes les 500 ms (en us)
}
void loop {
// Pour la vitesse brute, digitalToggle en boucle serrée bat les paires
// digitalWrite ; pour une forme d'onde précise, pilotez une broche PWM.
}
Speeding Up the Code
- digitalToggle in a tight loop: the fastest digital output in the Arduino API; for absolute maximum speed, direct access to K20 registers is possible — the pin → port bit mapping must then be taken from the MK20DX256 manual (K20P64M72SF1RM.pdf) and the card7a pinout card.
- FASTRUN:
FASTRUN void myFunction { ... }places the function in the 64 KB of RAM (faster than flash, 256 KB at 192 MB/s with a 256-byte cache). - Overclocking: the core is rated at 72 MHz but is officially overclockable to 96 MHz (techspecs table) — the clock comes from a 16 MHz crystal multiplied by a PLL.
- Interrupt priorities: the NVIC supports nesting (a higher-priority interrupt interrupts a lower-priority one) —
t1.priority(0)is the highest here, following Teensy convention. - DMA (16 channels): move blocks (SPI, ADC, UART, memory) without CPU — OctoWS2811 and the Audio library are prime examples.
Expected Verification
LED 13 blinks at exactly 1 Hz, even if loop is busy with a calculation loop — proof that the hardware timer works independently. Comment out flash in the code: the LED stays fixed, and your main code continues. On an oscilloscope connected to a freely toggling pin, measure the maximum frequency, then compare it with digitalToggle driven by an IntervalTimer at 1 µs.
Common Errors
- Getting the priority direction wrong: on Teensy, 0 = highest (contrary to the intuition "0 = none").
- Doing long operations inside an interrupt or timer routine:
delay, heavySerial.print→ cascading blocks; keep ISRs short and use a volatile flag. - Forgetting
volatileon variables shared between ISR andloop: the compiler optimizes them away, and your flag never changes "magically". - Putting ALL code in FASTRUN: RAM is 64 KB, flash is 256 KB — only place critical functions in RAM.
- Confusing timer groups: the 4 PITs, LPTMR, PDB, CMT, and FTMs do not share the same pins or uses (the LPTMR is optimized for ultra-low power).
- Expecting identical behavior after overclocking to 96 MHz: check libraries that depend on timing (bit-banging, calibrated delays).
Other tutorials for this board
- Premiers pas sur la Teensy 3.2 : Teensyduino, HalfKay et premier Blink
- Broches, ADC 13 bits, DAC 12 bits et PWM : dompter les E/S de la Teensy 3.2
- Un instrument MIDI USB en 10 minutes : Bounce, boutons et règle d'or du drain
- Audio Shield SGTL5000 : boucle stéréo 44,1 kHz et outil de conception graphique
- OctoWS2811 : piloter 8 rubans WS2812 en parallèle par DMA (presque zéro CPU)
- Intégration produit : alimentation VIN/VUSB, régulateur 250 mA, RTC à quartz et EEPROM
Code examples for this board
clignotante.inoArduinotouche-capacitive.inoArduinoanalogique-12-bits.inoArduinomidi-piano.inoArduinopwm-respiration.inoArduinoservo-angle.inoArduino