🛠 Comprendre la mémoire : 2 Mo de flash, 1 Mo de RAM TCM/DMA, EEPROM émulée et LittleFS
Objectives
The memory architecture of the Teensy 4.0 is its greatest strength — and its main porting pitfall. The NXP chip has no embedded flash: the program lives in an external Winbond W25Q16JV SPI flash of 2 MB (1984 KB usable — the top 64 KB store the emulated EEPROM and the LED-blink fallback program), executed via a 65536-byte cache at 66 MB/s. On the RAM side: 1024 KB total, split between RAM1 (TCM, single-cycle access via 64-bit ITCM/DTCM bus) and RAM2 (optimized for DMA). You will learn the placement keywords and the emulated EEPROM.
Placement Keywords
- FASTRUN: explicit placement of code in RAM1 (the compiler already places critical code there by default — single-cycle access, the fastest).
- FLASHMEM: force a function into flash (saves RAM, access via cache).
- PROGMEM / F: constant data in flash, outside of RAM.
- DMAMEM: data in RAM2, where DMA peripherals (USB, SDIO, audio) work best.
Complete Code
// Démonstration des zones mémoire + EEPROM émulée.
#include <EEPROM.h>
const char message[] PROGMEM = "constante en flash (F pour les littéraux)";
DMAMEM uint16_t tamponDMA[1024]; // RAM2 : idéal pour le DMA
FASTRUN void cheminCritique { // code dans RAM1 (TCM)
for (uint32_t i = 0; i < 1024; i++) tamponDMA[i] = i * 3;
}
void setup {
Serial.begin(9600);
Serial.println((const char*)message);
// EEPROM : 1080 OCTETS émulés dans la flash (pas de vraie EEPROM !)
uint8_t compteur = EEPROM.read(0);
compteur++;
uint32_t t0 = micros;
EEPROM.update(0, compteur); // écriture : le code S'ARRÊTE un instant
uint32_t duree = micros - t0;
Serial.printf("session %u, écriture EEPROM = %u us\n", compteur, duree);
}
void loop { cheminCritique; delay(1000); }
For files (logs, audio samples), the remaining flash is used via LittleFS: SD.begin(BUILTIN_SDCARD) targets the SDIO connector on the bottom pads, while LittleFS forms the free flash zone — same File API.
Expected Verification
The session counter survives power loss (1080 persistent bytes). Measuring micros around EEPROM.update shows the micro-execution stall documented by PJRC: writing from flash interrupts the code — to be banned from a real-time audio loop. Compare the duration of a cheminCritique loop with and without FASTRUN to feel the difference between TCM and cached flash.
Common Errors
- Writing to the EEPROM on every loop iteration: not only does it stall execution, but it wears out the flash — write only on value change (EEPROM.update does this, EEPROM.put does not).
- Believing you have 2048 KB of program space: it is 1984 KB, the top 64 KB are reserved (EEPROM + restore).
- Putting DMA buffers in RAM1 by reflex: drivers expect RAM2 (DMAMEM) — otherwise hidden copies or weird behaviors occur.
- Porting a Teensy 3.x sketch with floating-point constants: the T4 has a hardware 64-bit double FPU and no longer forces literals to single precision — “this might cause some subtle errors on T4” (output thread); write 1.0f explicitly.
- Storing large files in EEPROM: 1080 bytes, period — for volume, use LittleFS on flash or a 4-bit SD card.
- Forgetting the 16 bytes of RTC RAM (LPGPR0-3 registers) saved by the VBAT battery: this is the ideal place for a small, ultra-persistent critical state.
Other tutorials for this board
- Premiers pas sur le Teensy 4.0 : Teensyduino, Loader et premier Blink
- GPIO et PWM sous 3,3 V : les règles d'or du Teensy 4.0
- Entrées analogiques et capteur de température interne : le ADC et ses limites
- Piloter un ruban WS2812 sans bloquer le CPU : WS2812Serial et OctoWS2811
- Contrôleur MIDI USB : un potard qui joue du piano (MIDIx4/MIDIx16)
- Deux ports USB simultanés : périphérique 480 Mbit/s ET hôte USB sur les pastilles
Code examples for this board
clignotante.inoArduinotouche-capacitive.inoArduinoanalogique-12-bits.inoArduinomidi-piano.inoArduinopwm-respiration.inoArduinoservo-angle.inoArduino