Débordement Timer : Mécanisme, Conséquences et Gestion en Systèmes Embarqués
Débordement Timer : Mécanisme, Conséquences et Gestion en Systèmes Embarqués
Un **débordement timer** survient quand un registre compteur/timer matériel atteint sa valeur maximale ($2^N - 1$ pour N bits) et revient à zéro au coup d'horloge suivant. C'est un événement fondamental, périodique, dans virtuellement tous microcontrôleurs (MCU), SoC, et noyaux RTOS.
Le Mécanisme
- Compteur : Registre libre incrémenté par source horloge ($f_{clk}$ ou $f_{clk}$/Prescaler).
- Largeur : 8-bit (256), 16-bit (65 536), 32-bit (4,29G), 64-bit.
- Période ($T_{ovf}$) : $T_{ovf} = \frac{2^N}{f_{count}}$.
- Exemple : 16-bit, 1 MHz horloge $\rightarrow$ $T_{ovf} = 65,536 \text{ ms}$.
- Exemple : 32-bit, 100 MHz $\rightarrow$ $T_{ovf} = 42,9 \text{ s}$.
- Drapeau/Interruption : Matériel positionne **Drapeau Débordement (TOV / UIF)**. Génère **Demande Interruption (IRQ)** si activé (TOIE).
Conséquences Débordement Non Géré
| Domaine | Mode Défaillance |
|---|---|
| Horodatage (RTC / SysTick) | Temps saute arrière / reboucle. `millis()` reboucle (Arduino : 49,7 jours). `gettimeofday()` corruption si ISR manquée. |
| PWM / Comparaison Sortie | Glitch si valeur TOP pas mise à jour atomiquement avec tampon. Erreur rapport cyclique une période. |
| Capture Entrée / Largeur Impulsion | Période mesurée $>$ $T_{ovf}$ $\rightarrow$ Ambiguïté (comptage débordement manqué). Nécessite extension logicielle compteur débordement. |
| Ordonnanceur RTOS (SysTick) | Perte tick $\rightarrow$ Dérive timing tâches, échéances manquées, inversion priorité. |
| Sécurité / Crypto | Échec source entropie. Fuites canaux auxiliaires timing si débordement prévisible. |
| Y2K38 / `time_t` 32-bit | Débordement époque Unix 19 jan 2038. Pas timer HW, mais même math. |
Stratégies Gestion (Firmware)
1. Extension Largeur Logicielle (Pratique Standard)
// Timer HW 16-bit $\rightarrow$ Temps Système 32/64-bit
volatile uint32_t overflow_count = 0;
ISR(TIMER_OVF_vect) {
overflow_count++;
}
uint64_t get_time_us() {
uint8_t sreg = SREG; cli();
uint16_t hw = TCNT1;
uint32_t ovf = overflow_count;
SREG = sreg;
// Gestion course : if (TIFR & TOV) ovf++; hw = TCNT1;
return ((uint64_t)ovf << 16) | hw;
}
volatile uint32_t overflow_count = 0;
ISR(TIMER_OVF_vect) {
overflow_count++;
}
uint64_t get_time_us() {
uint8_t sreg = SREG; cli();
uint16_t hw = TCNT1;
uint32_t ovf = overflow_count;
SREG = sreg;
// Gestion course : if (TIFR & TOV) ovf++; hw = TCNT1;
return ((uint64_t)ovf << 16) | hw;
}
2. Réinitialisation / Rechargement Périodique (Mode Rechargement Auto / Périodique)
- Définir **Registre Rechargement Auto (ARR / TOP / PRD)** = Période Désirée - 1.
- Compteur compte 0 $\rightarrow$ ARR $\rightarrow$ 0. **Pas drapeau débordement** (ou drapeau = Correspondance Période).
- Utilisé pour : **SysTick (1ms), Période PWM, Déclenchement ADC, Tick RTOS.**
- Élimine ambiguïté débordement ; définit période exacte.
3. Capture Entrée avec Comptage Débordement
- Sur Événement Capture : Lire Timer ($T_{cap}$) + Lire/Incrémenter Compteur Débordement ($N_{ovf}$).
- Temps Total = $(N_{ovf} \times 2^N + T_{cap}) / f_{count}$.
- Lecture atomique (Compteur + Débordement) critique (Support HW : Registre capture 32-bit incluant bits débordement, ou double lecture avec vérification drapeau).
4. Compteurs Libres Haute Résolution / 64-bit
- ARM Cortex-M **DWT CYCCNT** (32-bit @ Fréquence CPU).
- RISC-V **`mtime` / `mtimeh`** (64-bit mémoire-mappée).
- x86 **TSC (Time Stamp Counter)** (64-bit, invariant).
- Période débordement = Siècles. Effectivement « pas débordement » pour durée vie système.
5. Compensation Dérive Horloge (Étalonnage)
- Tolérance oscillateur ($\pm 50$ ppm quartz, $\pm 1-2\%$ RC).
- Sync périodique référence externe (GPS PPS, NTP, IEEE 1588 PTP, Passage Zéro Secteur).
- Ajuster `ARR` ou facteur échelle logiciel dynamiquement.
Bonnes Pratiques
- Utiliser Mode Rechargement Auto pour tâches périodiques (SysTick, PWM, Boucles Contrôle). Éviter débordement libre sauf mesure longs intervalles.
- Lectures Atomiques : Désactiver interruptions / Utiliser LDREX/STREX / Double lecture avec vérification drapeau pour valeurs multi-registres.
- Volatile + Barrières Mémoire : Variables partagées ISR/Principal.
- Tester Rebouclage : Simuler débordement (mettre compteur près MAX) en CI/HIL. Vérifier gestion rebouclage `millis()` (historique bug rebouclage Arduino `millis()`).
- Watchdog : Watchdog indépendant fenêtré (IWDT/WWDT) — domaine horloge séparé — attrape défaillance timer principal.
Conclusion
Le débordement timer n'est pas une erreur — c'est une **contrainte de conception**. Compteurs libres 32/64-bit modernes le rendent négligeable pour horodatage. Pour timers 8/16-bit, **extension logicielle (compteur débordement) + accès atomique** est le pattern standard. Pour tâches périodiques, **Mode Rechargement Auto élimine le concept entièrement.**
