Public cible
Débutants, étudiants et professionnels qui souhaitent acquérir une pratique structurée dans ce domaine.
Écrire du logiciel qui tient dans quelques kilo-octets : contraintes simultanées, temps réel souple et dur, registres et dialogue matériel, protocole radio, inversion de priorité, et mises à jour sûres d'appareils déjà déployés.
Débutants, étudiants et professionnels qui souhaitent acquérir une pratique structurée dans ce domaine.
Comprendre les notions essentielles et les appliquer dans un projet vérifiable.
Aucune connaissance préalable n’est strictement obligatoire ; les prérequis détaillés sont précisés dans les ateliers.
Tous niveaux
La validation repose sur les évaluations actives et les livrables pratiques du cours.
Un ordinateur, un navigateur et les outils indiqués dans le premier atelier sont suffisants pour commencer.
Piloter un capteur, gérer les erreurs de protocole et mesurer la consommation.
Obligatoire ConsulterAnalyser un système temps réel et identifier la cause d'un gel.
Obligatoire ConsulterUn logiciel embarqué s'exécute sur une machine dont les ressources ne sont pas négociables. Ce n'est pas une version réduite du logiciel classique : c'est une autre discipline.
Ces quatre contraintes sont simultanées et antagonistes : réduire la mémoire allonge le temps d'exécution, donc la consommation ; augmenter la fréquence consomme plus. Chaque décision est un compromis, et c'est ce qui distingue l'ingénierie embarquée.
La différence la plus concrète avec du logiciel classique est l'absence d'espace pour une pile d'appels qui grandit à l'exécution. Sur un poste de travail, la pile est un problème de performance ; sur une cible contrainte, c'est une source de débordement qui corrompt la mémoire voisine sans aucun message : le système continue de fonctionner, avec des données aberrantes.
La parade : mesures systématique de la consommation mémoire, et une discipline d'exploration des appels qui ne dépend pas de l'implémentation de la bibliothèque standard — parce que cette bibliothèque est précisément ce qui est volumineux.
« Puis-je utiliser une bibliothèque ? » est une question d'ingénierie, pas de convenance. Les bibliothèques d'usage général contiennent presque toujours des fonctions jamais appelées, qui embarquent leur texte, leurs structures et leur logique d'erreur. Sur une cible de 64 kilo-octets, la taille de la bibliothèque importe plus que la complexité du code écrit.
Le temps réel ne signifie pas « rapide » mais « prévisible ». Un système peut être lent et rester temps réel ; un système rapide et imprévisible ne l'est pas.
Choisir du temps réel dur sans justification est un coût disproportionné : il interdit les bibliothèques utiles, impose des contraintes de conception, et réduit l'équipe disponible. La question à se poser est « que se passe-t-il si je rate ? ». Si la réponse est « rien de grave », le temps réel souple suffit et coûte beaucoup moins cher.
La plupart des systèmes temps réel utilisent un ordonnanceur à priorité préemptive : une tâche de priorité élevée reprend la main dès qu'elle est prête, et la tâche de faible priorité peut être interrompue indéfiniment. La conséquence est un risque classique et réel : une tâche de priorité moyenne ne s'exécute jamais si la charge des tâches haute et moyenne dépasse la capacité totale.
La parade est structurelle : garantir que les tâches haute priorité laissent de la place aux autres — par des budgets d'exécution, par une conception en à-coups plutôt qu'en occupation permanente. Ce défaut ne se voit pas en développement : l'environnement de test est presque toujours inchargé.
Une interruption s'exécute en plein milieu de n'importe quelle instruction, y compris au milieu d'une écriture d'état. Partager une variable entre le code principal et une routine d'interruption sans section critique produit une lecture à moitié mise à jour : la valeur est incohérente, et non simplement ancienne. Sur un octet, c'est invisible ; sur une structure de plusieurs champs, c'est un comportement imprévisible.
Et l'erreur inverse, plus coûteuse au développement : une interruption qui dure trop longtemps. Une interruption de traitement d'image bloque l'ordonnanceur pendant l'opération, et le système devient inutilisable alors que tout semble fonctionner sur un banc de test peu chargé.
Un microcontrôleur réunit sur une puce le processeur, la mémoire et les périphériques. Il n'y a pas de système d'exploitation en dessous : le programme est aux prises avec le matériel.
Un microcontroleur n'a pas de variables : il a des registres, des cases mémoire de taille fixe, chacune avec un rôle défini par le constructeur. Écrire dans le mauvais registre ne provoque pas une erreur, il produit un comportement arbitraire. C'est la différence structurelle avec un programme classique : la logique des causes et des effets disparaît.
Communiquer avec un capteur ou un actionneur est presque toujours un échange séquencé : une commande, un délai, une attente d'un signal prêt, une lecture de la donnée, une confirmation. Deux erreurs classiques :
La parade est identique dans les deux cas : lire un état et le tester, au lieu de supposer que l'opération a réussi.
Sur une carte cible, des cavaliers ou des straps selects à la compilation sélectionnent des variantes du même programme — le kristal d'horloge, la tension de fonctionnement, la source de démarrage. Deux engineers qui compilent le meme code pour deux cartes different obtient deux comportements, sans qu'aucune ligne de code diffère.
C'est la raison pour laquelle toute configuration matérielle doit être décrite dans le dépôt, dans un fichier versionné. Un projet embarqué dont la configuration de la carte vit dans la mémoire de l'ingénieur n'est pas reproductible — et il devient impossible à maintenir dès que l'équipe change.
Un objet embarque communique dans des conditions hostiles : peu de signal, batterie faible, interférences, et un utilisateur qui s'éloigne.
La consommation d'une radio est liée à la puissance d'émission : la transmettre plus loin coûte nettement plus que la recevoir. Un appareil sur batterie ne peut donc pas émettre en permanence, et chaque émission est une décision à() — ce n'est pas pas un simple choix technique, c'est un arbitrage énergie contre réactivité.
La conséquence pratique : la portée et la durée de vie de la batterie ne sont pas deux paramètres indépendants. On ne peut pas avoir les deux au maximum, et le produit doit choisir. Un capteur de température n'a aucun besoin d'émettre en continu, un traceur localisé en a.
Un protocole de communication se définit complètement, y compris ses cas d'erreur : Délai maximal d'attente, nombre de reprises, et ce qui se passe quand la cible ne répond pas. Un protocole qui ne définit pas la fin de l'attente n'est pas un protocole, c'est un script qui fonctionne quand rien ne va mal — et c'est exactement le cas qu'on forget de tester.
Un système d'exploitation temps réel fournit ce qu'un programme classique ne trouve pas sur une cible : l'ordonnancement, la synchronisation et la gestion du temps.
Confondre les deux est l'erreur qui produit un blocage généralisé : une tâche qui attend ce qu'elle garde, et qui empêche toutes les autres d'avancer. Le système reste figé, et rien n'indique la cause.
Deux mots à connaître parce qu'ils expliquent un défaut qui peut ruiner un système sans le faire planter :
La leçon générale : sur un système contraint, les propriétés qui se voient sont les moindres utiles. Un plantage est presque toujours plus facile à diagnostiquer qu'un gel.
Zephyr et FreeRTOS couvrent l'essentiel des besoins. Ce sont des choix d'écosystème autant que de technique : ils imposent des conventions, proposent une chaîne d'outils complète et sont organises autour d'eux, et cela pèse autant que les caractéristiques du noyau lui-même. Le choix se justifie par l'équipe et l'outil disponible, autant que par l'excellence technique — la même leçon que le cours sur les frameworks front.
Un défaut qui redémarre l'appareil est un défaut d'inconfort. Un défaut qui produit un mauvais calcul sans aucun signe est un défaut de sûreté, et il se traite avec une exigence complètement différente.
La phrase qui résume le métier : une conception sûre est une conception dont l'échec est détectable et sans conséquence grave. Un système qui plante trois fois par jour dans un environnement contrôlé est plus sûr qu'un système qui continue à produire un résultat faux sans jamais s'arrêter.
Mettre à jour un appareil déployé, c'est remplacer un composant dont on ne maîtrise plus l'état. Les deux pertes d'alimentation au milieu d'une écriture produisent un appareil inutilisable, et il est parfois à des centaines de kilomètres, sans possibilité d'intervention physique.
La solution est structurelle et connue : écrire dans la mémoire inactive, vérifier l'image par un contrôle d'intégrité, puis basculer un simple indicateur de démarrage. Le risque résiduel — une coupure pendant le basculement — se traite par un indicateur de démarrage enregistré, qui ramène toujours à une image valide. Un mécanisme de ce type se conçoit au moment du premier programme, pas au moment du premier incident terrain.
Piloter un capteur, et mesurer la consommation au lieu de l’estimer.
Publié le 29/09/2026