🛠 Comprendre la mémoire : 2 Mo de flash, 1 Mo de RAM TCM/DMA, EEPROM émulée et LittleFS
Objectifs
L'architecture mémoire du Teensy 4.0 est sa plus grande force — et son principal piège de portage. La puce NXP n'a pas de flash embarqué : le programme vit dans une flash SPI externe Winbond W25Q16JV de 2 Mo (1984 Ko utilisables — les 64 Ko du haut stockent l'EEPROM émulée et le programme de secours LED-blink), exécutée via un cache de 65536 octets à 66 Mo/s. Côté RAM : 1024 Ko au total, moitiés RAM1 (TCM, accès un cycle via bus 64 bits ITCM/DTCM) et RAM2 (optimisée pour le DMA). Vous apprendrez les mots-clés de placement et l'EEPROM émulée.
Les mots-clés de placement
- FASTRUN : placement explicite du code dans RAM1 (le compilateur y place déjà le code critique par défaut — accès un cycle, le plus rapide).
- FLASHMEM : forcer une fonction dans la flash (économise la RAM, accès via cache).
- PROGMEM / F : données constantes en flash, hors de la RAM.
- DMAMEM : données dans RAM2, là où les périphériques DMA (USB, SDIO, audio) travaillent le mieux.
Code complet
// 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); }
Pour les fichiers (logs, samples audio), la flash restante s'utilise via LittleFS : SD.begin(BUILTIN_SDCARD) vise le connecteur SDIO des pastilles inférieures, tandis que LittleFS forme la zone flash libre — même API File.
Vérification attendue
Le compteur de sessions survit à la coupure d'alimentation (1080 octets persistants). La mesure micros autour d'EEPROM.update montre la micro-coupure d'exécution documentée par PJRC : l'écriture depuis la flash interrompt le code — à bannir d'une boucle audio temps réel. Comparez la durée d'une boucle de cheminCritique avec et sans FASTRUN pour sentir la différence TCM vs flash cachée.
Erreurs fréquentes
- Écrire dans l'EEPROM à chaque tour de loop : non seulement ça stalle l'exécution, mais ça use la flash — n'écrire que sur changement de valeur (EEPROM.update le fait, pas EEPROM.put).
- Croire disposer de 2048 Ko de programme : 1984 Ko, les 64 Ko supérieurs sont réservés (EEPROM + restore).
- Mettre les buffers DMA en RAM1 par réflexe : les pilotes attendent la RAM2 (DMAMEM) — sinon copies cachées ou comportements bizar.
- Porter un sketch Teensy 3.x avec des constantes flottantes : le T4 a un FPU double 64 bits matériel et ne force plus les littéraux en simple précision — « this might cause some subtle errors on T4 » (fil de sortie) ; écrivez 1.0f explicitement.
- Stocker de gros fichiers en EEPROM : 1080 octets, point final — pour du volume, LittleFS sur flash ou carte SD 4 bits.
- Oublier les 16 octets de RTC RAM (registres LPGPR0-3) sauvegardés par la pile VBAT : c'est l'endroit idéal pour un petit état critique ultra-persistant.
Autres tutoriels pour cette carte
- 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
Exemples de code pour cette carte
clignotante.inoArduinotouche-capacitive.inoArduinoanalogique-12-bits.inoArduinomidi-piano.inoArduinopwm-respiration.inoArduinoservo-angle.inoArduino