Une analyse statique du code réalisée avec CppDepend offre une vision architecturale approfondie des dépendances structurelles de la base de code FreeRTOS. Grâce à une Dependency Structure Matrix (DSM), les développeurs peuvent visualiser comment les composants centraux du noyau interagissent entre eux.

Principales conclusions architecturales
- Cycles de dépendances identifiés : l’analyse met explicitement en évidence une dépendance circulaire entre des modules centraux :
Source/timers.cforme un cycle de dépendance avecSource/tasks.c. - Cartographie DSM : la Dependency Structure Matrix visualise les couplages inter-fichiers entre les composants centraux, notamment
Source/event_groups.c,Source/list.c,Source/queue.c,Source/tasks.cetSource/timers.c. - Découpage de la structure des répertoires : le projet regroupe ses composants sous l’espace de noms principal
freertos, comprenantSource/*,Source/include/*et les implémentations spécifiquesSource/portable/, aux côtés des dépendances externes.
Analyse approfondie : le cycle de dépendance entre timers.c et tasks.c
En zoomant dans la Dependency Structure Matrix (DSM), le code couleur révèle la nature exacte de ce couplage :
- La cellule rouge : un double-clic sur la cellule rouge met en évidence le cycle de dépendance bidirectionnel global entre
Source/timers.cetSource/tasks.c. - Les cellules vertes : représentent les dépendances directes qui partent des fonctions et structures de
tasks.cverstimers.c. - Les cellules bleues : représentent les dépendances inverses, de
timers.cverstasks.c— références aux contrôles de tâches, aux états du scheduler et aux structures partagées.

Peut-on améliorer l’architecture ?
D’un point de vue purement logiciel, un découplage complet (par exemple faire des timers un module plug-in totalement indépendant) est techniquement possible, mais il s’accompagne de compromis importants pour les systèmes embarqués :
- Performance et surcoût : FreeRTOS est conçu pour des microcontrôleurs soumis à des contraintes strictes de RAM et de cycles CPU. Découpler les modules exige généralement des couches d’abstraction, des tables de pointeurs de fonctions ou des hooks d’enregistrement dynamique. Cela ajoute de la RAM, du footprint ROM et de la latence d’appel.
- Conception temps réel monolithique : dans un RTOS critique ou à ressources limitées, on préfère des interactions étroitement contrôlées et prévisibles entre le scheduler et les services auxiliaires (comme les timers) à des architectures plug-in lâches, afin de garantir un comportement déterministe et de faciliter l’analyse statique (comme la conformité MISRA).
Si vous cherchez à minimiser la taille du code ou à personnaliser ce qui est compilé, FreeRTOS permet d’exclure complètement timers.c de votre CMakeLists.txt si votre application n’utilise pas les timers logiciels — il ne reste alors que tasks.c, queue.c et list.c, pour un empreinte aussi légère que possible.
Un couplage faible entre les fonctions FreeRTOS
L’analyse du couplage des méthodes avec Code Quest (CQLinq) révèle que la quasi-totalité des fonctions FreeRTOS présente un couplage exceptionnellement faible.

En interrogeant les méthodes dont le nombre de méthodes appelées (NbMethodsCalled) est supérieur à 10, le résultat est remarquablement restreint :
from m in Methods
where m.NbMethodsCalled > 10
select new { m, m.NbMethodsCalled }- Très peu de valeurs extrêmes : sur l’ensemble de la solution
freertos, seules 4 méthodes atteignent ou dépassent ce seuil. - Opérations centrales des files : les seules fonctions au-delà de cette limite se trouvent dans
Source/queue.csous__Globals— des primitives de routage et de synchronisation commexQueueGenericSend,xQueueReceive,xQueueSemaphoreTakeetxQueuePeek(13 à 14 méthodes appelées). - Leçon architecturale : cela confirme que la grande majorité des fonctions FreeRTOS sont granulaires, autonomes et interagissent avec un nombre étroitement contrôlé de collaborateurs.
Modularité granulaire : l’architecture au niveau fonction dans Code City
Visualiser la base de code FreeRTOS sous forme de Code City 3D offre une perspective intuitive de la structuration des fonctions. Plutôt que des blocs monolithiques tentaculaires, la disposition révèle une ville dense de bâtiments compacts et hautement spécialisés représentant chacun une fonction.

- Fonctions compactes : les métriques Code City confirment que les routines centrales conservent une empreinte réduite et maîtrisable. Des routines critiques de gestion mémoire comme
pvPortMalloc(size_t)ne font que 71 lignes de code tout en obtenant une note A de maintenabilité. - Principe de responsabilité unique : l’uniformité des tailles de bâtiments dans la ville illustre la philosophie de conception de FreeRTOS — chaque fonction est isolée sur un objectif précis.
- Faible complexité et forte maintenabilité : en gardant des routines courtes, la logique conditionnelle complexe et la dette technique sont minimisées — vital pour les systèmes temps réel.
Une maintenabilité élevée sur les fichiers sources FreeRTOS
L’analyse du graphe de dépendances et de métriques révèle que FreeRTOS maintient une maintenabilité exceptionnelle sur l’ensemble de ses fichiers et modules centraux.

- Des notes « A » uniformes : chaque composant majeur —
Source/queue.c,Source/tasks.c,Source/timers.cetSource/portable/MemMang/heap_4.c— obtient la note maximale A en maintenabilité. - Zéro dette technique : malgré des opérations RTOS critiques, des fichiers comme
Source/queue.c(624 LOC) etSource/tasks.c(1036 LOC) affichent 0 min 0 s de dette technique — preuve d’un respect rigoureux des standards de codage. - Indice de maintenabilité (MI) élevé : l’indice reste constamment élevé d’un fichier à l’autre, de scores confortables dans
heap_4.c(MI : 66) jusqu’à d’excellentes notes dansSource/timers.c(MI : 76) et les en-têtes portables (MI : 78).
Code Map : un regard dans timers.c
En examinant un fichier comme timers.c via la visualisation Code Map (blocs dimensionnés selon les lignes de code et colorés selon la maintenabilité), on obtient une vue granulaire de la contribution de chaque routine à la propreté du fichier :

- Un vert constant : la grande majorité des fonctions de
timers.csont colorées d’un vert franc, signe d’un indice de maintenabilité élevé et d’une faible complexité structurelle. - Des tailles de méthodes équilibrées : les blocs utilitaires plus volumineux comme
prvProcessReceivedCommandsoccupent une part visible du plan, mais restent proprement partitionnés aux côtés de petites fonctions auxiliaires. - Une distribution architecturale propre : cette décomposition visuelle confirme que, même dans des fichiers contenant une logique de synchronisation temps réel complexe, les fonctions restent compactes, bien définies et hautement maintenables.
Voici quelques autres patrons de conception et d’architecture de haut niveau de FreeRTOS :
1. La couche de portabilité (séparation claire des responsabilités)
- Abstraction matérielle : FreeRTOS isole proprement la logique d’ordonnancement générique des détails propres au processeur.
- La frontière portable/ : tout le code dépendant du matériel — changement de contexte, gestion des interruptions, configuration SysTick — est confiné dans le répertoire
Source/portable/. - Bénéfice architectural : cette conception modulaire permet au cœur du noyau (
tasks.c,queue.c) de rester 100 % portable sur des dizaines d’architectures (ARM Cortex-M, RISC-V, etc.).
2. Pointeurs opaques et encapsulation des données
- Masquage d’information : FreeRTOS utilise massivement des pointeurs opaques et des types de handles (comme
TaskHandle_touQueueHandle_t) plutôt que d’exposer les structures de contrôle brutes. - Bénéfice architectural : le code applicatif interagit avec le noyau strictement via des API bien définies. Cela empêche un couplage fort entre les tâches utilisateur et les états internes du noyau.
3. Stratégies de gestion mémoire plug-and-play
- Plusieurs options de heap : FreeRTOS fournit cinq implémentations distinctes de gestion mémoire (
heap_1.càheap_5.c), du simple allocateur sans libération aux algorithmes avancés de coalescence. - Bénéfice architectural : les développeurs embarqués gardent un contrôle architectural sur le comportement mémoire. Pour les systèmes critiques (automobile, aérospatial), on peut choisir des allocateurs déterministes et sans fragmentation.
4. Faible complexité cyclomatique pour le déterminisme temps réel
- Chemins d’exécution bornés : les fonctions étant courtes et peu ramifiées (moins de if-else imbriqués et de boucles), le temps d’exécution des routines du noyau reste hautement prévisible.
- Bénéfice architectural : dans un système d’exploitation temps réel dur (RTOS), la prévisibilité temporelle (déterminisme) est aussi importante que l’exactitude. Une faible complexité garantit que le scheduler respecte des échéances strictes.
Conclusion : les leçons de l’analyse de FreeRTOS
L’analyse architecturale avec CppDepend montre clairement comment FreeRTOS concilie exigences temps réel et pratiques de code propre :
- Un couplage pragmatique plutôt qu’un découplage absolu : si un cycle de dépendance existe entre
Source/timers.cetSource/tasks.cen raison d’états partagés commexTimerTaskHandle, ce choix de conception minimise le surcoût d’abstraction, l’indirection par pointeurs de fonctions et l’empreinte mémoire — des priorités critiques pour des microcontrôleurs à ressources limitées. - Modularité exceptionnelle et faible couplage : au-delà de cette unique interaction étroite, la base de code présente un couplage remarquablement faible. Seules quatre fonctions de tout le dépôt appellent plus de dix autres méthodes, réservant la complexité aux primitives de files et de synchronisation de
Source/queue.c. - Haute maintenabilité et zéro dette technique : grâce à des fonctions granulaires à responsabilité unique, FreeRTOS atteint des notes A de maintenabilité et 0 s de dette technique sur des fichiers clés comme
tasks.c,timers.cetheap_4.c.
Envie de voir l’architecture de votre propre firmware ? Téléchargez CppDepend et lancez l’analyse de votre base de code en quelques minutes. Vous pouvez aussi lire comment nous avons visualisé un autre projet : Du code IA à une Code City vivante.
