Temps réel embarqué

Nœud multi-capteurs FreeRTOS

Une boucle d'acquisition STM32 sans gigue : tâches à priorités fixes, étages découplés par files et mesure DWT en microsecondes.

STM32FreeRTOSCMSIS-RTOS2I2CC
View on GitHub
Problème

Une boucle unique qui lit l'I2C, calcule des statistiques et imprime sur l'UART couple un capteur rapide à une console lente. Une seule impression bloquante arrête l'acquisition et détruit la période d'échantillonnage, sans moyen de savoir quel retard a été pris.

Approche

Séparer la chaîne en trois tâches à priorités fixes reliées par des files : acquisition (haute), traitement (au-dessus de la normale) et console (normale). Un cœur en C pur gère les fenêtres glissantes et est testé sur l'hôte. Les horodatages DWT donnent la latence d'acquisition, la latence bout-en-bout et la gigue en microsecondes ; le tickless idle endort le cœur quand il n'y a rien à faire.

Architecture
BME280 / capteur simulé→
acq_task (haute)→
sample_q→
process_task (au-dessus de la normale)→
stat_q→
console_task (normale)→
UART + heartbeat

Tech Stack

MCUNUCLEO-L476RG (Cortex-M4F @ 80 MHz)Carte cible
RTOSCMSIS-RTOS2 / FreeRTOSTâches à priorités fixes et files
CapteurBME280 sur I2C1Température, humidité et pression
TempsCompteur de cycles DWTLatence et gigue en microsecondes
CœurRing buffer en C purStatistiques à fenêtre glissante testées sur l'hôte

Décisions clés

  • →Les priorités sont acq > process > console : la boucle d'acquisition ne doit jamais attendre la console.
  • →Quand la file d'échantillons est pleine, le plus récent est jeté et compté au lieu de bloquer le producteur.
  • →Le cœur de statistiques n'a aucune dépendance HAL ou RTOS, ce qui permet de le tester avec gcc sur l'hôte.
  • →Le tickless idle (avec STOP2 en option) endort le cœur quand il n'y a pas de travail.
Deep Dive

Découplage par files

La tâche d'acquisition possède la lecture I2C et pousse un échantillon horodaté dans une file de longueur 16. Le traitement le consomme et pousse un résumé dans une file de longueur 8 pour la console. Une console lente peut prendre du retard sans changer la période d'acquisition ; le seul effet visible est le compteur d'échantillons jetés.

text
acq_task --sample_q(16)--> process_task --stat_q(8)--> console_task

Mesurer la gigue avec le DWT

Chaque acquisition est horodatée avec le compteur de cycles DWT. Le nœud affiche la latence d'acquisition, la latence bout-en-bout (acquisition -> traitement) et le retard maximal en microsecondes : le comportement temps réel est observé, pas supposé.

text
acq=412 us  e2e=1180 us  behind by 0 us  drops=0

Basse consommation et détection de blocage

Le tickless idle de FreeRTOS (et STOP2 en option) endort le cœur entre deux périodes. Un compteur heartbeat est vérifié par la tâche console, afin de signaler une tâche d'acquisition bloquée au lieu de laisser la chaîne se figer silencieusement.

text
configUSE_TICKLESS_IDLE=1
PWR_STOP2 si la prochaine échéance est assez lointaine
Résultats
6 / 6
Tests hôte
3
Tâches à priorité fixe
1 us (DWT)
Résolution temporelle
en attente du matériel
Latence / consommation carte

Fonctionnalités démo

  • →Le capteur simulé est le mode par défaut : le nœud tourne sans BME280
  • →Les tests hôte couvrent le ring buffer, les sommes après rebouclage et la sécurité à capacité nulle
  • →Le nœud affiche latence d'acquisition, latence bout-en-bout et gigue en microsecondes
  • →La configuration CubeMX et l'architecture des tâches sont documentées dans docs/
Leçons apprises
  • →Découpler le producteur rapide du consommateur lent : une file rend le budget temporel explicite.
  • →Instrumenter l'ordonnancement. Sans horodatage DWT, la gigue reste une opinion.
  • →Garder le cœur de statistiques sans HAL ni RTOS est ce qui rend les tests hôte possibles.