Cela faisait un moment que je réfléchissais à parler des systèmes embarqués,
en particulier autour de Linux. Cela fait quelques temps que je suis dedans, et
les ressources francophones étant plutôt rares dans le secteur, j'aimerais
partager mon expérience, mes pensées, mes trucs et astuces potentiels.
Bien sûr cela ne remet nullement en cause la communication de l'actualité
autour de Fedora.
Pour commencer cette catégorie, je pense qu'il est bon de définir ce que
j'entends ici par systèmes embarqués afin que ce soit clair et raconter un peu
ma vie sur pourquoi je travaille dedans.
Mon parcours
Mon intérêt pour les systèmes embarqués vient de loin, mais reste flou.
Globalement j'ai toujours apprécié manipuler un produit, un objet. Cela s'est
confirmé durant mon cursus dans le supérieur, je n'éprouve pas une grande
satisfaction à faire tourner mon bout de programme sur un serveur dont j'ignore
même sa localisation. Ce besoin de concret est très important pour moi. J'ai
toujours été très excité de lancer le résultat de mon travail préliminaire sur
une nouvelle carte électronique qui vient de débarquer. Et constater que cela
ne fonctionne pas du premier coup bien entendu.
Ensuite, il y a également l'intérêt d'apprendre le fonctionnement de nos
ordinateurs. J'ai toujours été fasciné par le fonctionnement des processeurs,
de la RAM ou des systèmes d'exploitation. Sans doute l'émerveillement devant
leur complexité et l'ingéniosité de leur conception (si on met sous le tapis
les horreurs également présentes). Dans ce domaine, il faut connaître les
caractéristiques du circuit, du processeur, lire la documentation associée,
comprendre l'état de la mémoire, comment l'OS va gérer les entrées/sorties et
les processus pour donner accès à la fonction voulue. Impossible de se reposer
sur une machine virtuelle ou un interpréteur qui nous cache ces détails (ce
qu'ils font à raison, mais cela ne m'intéresse pas).
Enfin, je trouve que c'est un domaine omniprésent. Cela permet de côtoyer de
nombreux secteurs d'activités différents comme: télécommunication, aéronautique
ou spatial, automobile, agriculture, sécurité bancaire, multimédia,
l'électronique, etc. Et comme le produit doit répondre aux contraintes de
chaque secteur, il faut étudier, comprendre et analyser les caractéristiques du
secteur considéré. Cela permet de varier l'environnement d'étude et donc les
choses à en apprendre. Or j'adore apprendre.
Qu'est-ce qu'un système embarqué ?
Cela peut paraître absurde, mais il y a probablement autant de définitions
que d'acteurs dans le domaine. D'autant plus qu'avec le temps et l'évolution
technique, la définition de ce qui entre ou pas dans ce cadre peut varier.
Typiquement, un téléphone aujourd'hui est radicalement différent par rapport
aux débuts des années 2000. Pour certains un smartphone n'en est plus un, pour
d'autres, cela continue.
Du coup on va dégager les tendances ou les points communs pour le définir.
Globalement nous pouvons résumer cela en tout système programmé qui n'est pas
d'architecture x86 ou qui présente une contrainte spécifique.
La puissance disponible
La première chose qui vient à l'esprit, ce sont les performances
matérielles. Un processeur pas très puissant, voire ancien, peu de RAM ou de
stockage et une connectique souvent un peu spéciale pour en tirer parti. Grâce
aux progrès de la miniaturisation et de l'économie d'énergie, c'est de moins en
moins vrai. Des processeurs tels que les nVidia Tegra TK1/TX1 ne consomment pas
grand chose. Pour moins d'une dizaine de watts, et une surface raisonnable,
nous avons un couple GPU/CPU pouvant atteindre le TFLOPS en puissance de calcul
brut. Qu'on peut facilement épauler de quelques Gio de RAM et de mémoire de
stockage.
À titre de comparaison, 1 TFLOPS (en admettant cette unité de mesure comme
pertinente, ce qui est discutable) c'est l'ordinateur le plus puissant du
monde déclaré (donc pas militaire ou top secret) en 1997. 20 ans après un
téléphone ou une voiture en ont un voire plusieurs sur quelques millimètres
carré. Nous sommes très loin d'un simple microcontrôleur ou d'un processeur
peinant à gérer plusieurs processus à la fois. Cela est également proche de ce
qu'on peut retrouver dans un ordinateur personnel normal.
Donc si la puissance disponible est un critère souvent retenu, programmer un
microcontrôleur est de fait un système embarqué, il est possible aujourd'hui de
faire des systèmes embarqués avec une puissance de calcul très élevée.
Les contraintes d'un système peu puissant c'est qu'il demandera sans doute
une économie des ressources, la renonciation à certaines technologies et à
certaines fonctionnalités. Ce n'est pas pour rien que le C et le C++ règnent
encore en maître dans le domaine, même si Python ou Java prennent de plus en
plus de place, grâce justement à l'amélioration des performances.
L'énergie
Pour enchaîner avec le point précédent, nous pouvons relever la consommation
énergétique. Tous les systèmes embarqués n'ont pas cette contrainte, mais cela
reste assez commun. En effet, un système sur batterie devra faire attention à
la consommation énergétique pour limiter l'apport d'énergie (en fréquence comme
en puissance) par exemple pour augmenter son autonomie.
Le lien avec la puissance est évidente, malgré les progrès, plus de
puissance de calcul demandera plus de ressources électriques. C'est ce qui a
limité pendant longtemps la possibilité de faire des systèmes embarqués avec
des performances élevées. La mise à disposition de processeurs modernes avec
une consommation faible permet le contournement de ce problème mais pas
complètement. Cela se vérifie avec l'Internet des Objets qui remet au centre du
secteur des processeurs très minimalistes et très peu gourmands pour exécuter
uniquement la fonction demandée.
L'énergie va avoir plusieurs contraintes sur le système. Il peut en effet
limiter la puissance disponible. Il peut aussi être une contrainte car
l'énergie fournie est non fiable. Nous pouvons penser à des systèmes en
aéronautique ou aérospatiale dont certains composants ont une puissance
électrique allouée maximale et que dans certains cas l'engin peut couper
l'alimentation de composants secondaire (par exemple le multimédia à
bord des avions).
Il faut donc tenir compte de cela, par exemple certaines communications
peuvent être coupées brutalement, le système aussi. Cela a un impact fort sur
le design électronique et logiciel. Il faut réfléchir à comment gérer le cas
d'une coupure de courant lors d'une mise à jour du système (dans quel état le
système va être retrouvé ?). Les fonctions qui doivent être maintenues en vie
et d'autres pas. Si ces questions existent pour l'ordinateur personnel, cela
reste moins problématique et beaucoup plus rare que dans le cas des systèmes
embarqués. On peut en effet présumer que dans les pays développés le réseau
électrique est plutôt fiable (ce qui n'est pas sans poser de soucis pour ceux
ne vivant pas dans de tels pays mais passons).
L'autonomie
Ici je ne parlerai pas d'autonomie électrique, bien que ce soit liée, mais
plutôt d'autonomie en terme d'isolement du système. Un système où l'accès au
réseau n'existe pas forcément, où il n'y a pas un technicien disponible pour le
réparer en cas de besoin rapidement.
Cela a un impact bien entendu très fort sur le système. Cela signifie que le
système doit être robuste aux pannes ou bogues divers. Certains processus
devront être très fiables, comme la mise à jour. Si on envoie un nouveau
logiciel à un satellite dans l'espace et que cela échoue, le satellite doit
rester opérationnel dans tous les cas. On ne va pas envoyer une fusée pour
réparer ce genre de choses.
En terme d'architecture du système, il va falloir penser à beaucoup de
choses pour minimiser l'intervention humaine. Il faut forcément automatiser le
lancement pour que l'application métier soit lancée toute seule. Mais aussi
programmer des tâches récurrentes, prévoir des solutions en cas de coupure du
réseau ou de l'électricité.
Par exemple, pour que le système soit auto-entretenu dans un tel contexte,
il est courant de recourir à un système sans état. Ce type de système fait
qu'en cas de redémarrage, la fonction recommence comme si de rien n'était, le
système pouvant être en lecture seule. On couple cela avec un watchdog
pour que le système redémarre matériellement tout seul si jamais l'application
ou le noyau ont planté.
Les entrées/sorties limitées ou spéciales
De part les contraintes énoncées plus haut, il en ressort qu'on n'interagit
pas avec un système embarqué comme avec son ordinateur personnel. Il n'y a pas
forcément d'écran, encore moins souvent de clavier complet ou de souris. Si
écran il y a, c'est souvent du mono applicatif donc sans bureau. Le système
doit être minimal, pour économiser en coût de composants, en risque de
problèmes matériels ou logiciels et simple d'utilisation pour un utilisateur
non formé. En effet il serait malvenue que le distributeur de billet de votre
quartier soit complexe à prendre en main ou qu'il tombe en panne
régulièrement.
Cela va induire par effet de bords des choix en terme d'interface
utilisateur pour présenter le moins de choix possibles d'un coup, en restant
clair et complet. Et que tout ceci soit sélectionnable sans difficulté ou
ambiguïté pour tous les utilisateurs (comme les personnes âgées ou les
handicapées). Ceci explique souvent les interfaces un peu vieillottes avec de
gros boutons que ce soit bien visible et clair. Les interfaces riches peuvent
être sources de confusion dans ce genre de situations en plus de demander plus
de ressources matérielles et de temps de développement.
En terme d'entrées/sorties spécifiques, nous avons ceux du développement et
en environnement de production. Pour le développement, comme nous utilisons
notre ordinateur, nous devons communiquer avec la bête. Très souvent cela se
fait par le réseau (par SSH et NFS), par port série voire USB pour l'accès à la
console (quand le SSH n'est pas possible) et JTAG pour déboguer en
stoppant le processeur par exemple pour analyser la situation à n'importe quel
moment. Parfois pour flasher la JTAG sert encore mais cela est de moins en
moins le cas. Il faut souvent jongler avec tout ceci ce qui encombre pas mal le
poste de travail.
Les normes et l'environnement
Encore un sujet assez vaste et pourtant au combien important. Les systèmes
embarqués sont très souvent employés dans des secteurs industriels où les
normes sont omniprésentes pour des raisons de sécurité, de compatibilité, de
respect de l'environnement, etc. Et cela n'est pas sans incidence sur le
développement.
Des secteurs sont par exemple très très réglementés comme l'aéronautique, le
médical, le spatial, l'automobile ou le ferroviaire. Ce sont des secteurs où
des défauts peuvent engendrés la perte de vies humaines ou avoir des coûts
matériels très important en cas de défaut. Il est impératif de respecter des
normes afin de limiter au maximum les risques.
Je vais parler de l'aéronautique, secteur que j'ai pu côtoyer durant deux
ans. Tout logiciel (et matériel) embarquant dans un avion doit être certifié
conformément aux directives des agences continentales et internationales. Pour
être certifié, l'écriture du logiciel doit suivre une procédure précise qui
dépend bien sûr de la criticité du système.
En effet, tout système se voit attribué un DAL qui est un niveau
d'exigence noté de A à F, plus la note est élevée, plus l'exigence et les
limitations seront fortes. Dans tous les cas il faudra documenter le design,
rédiger des cahiers de tests et communiquer les résultats. Il faut également
facilement faire le lien entre le code / commit et un test ou une exigence du
design.
Et là où cela se corse, c'est par exemple des logiciels pour les DAL A ou B,
il faut impérativement que tout soit contrôlé. Tout le chemin d'exécution du
code, de même que le déterminisme du processeur en dessous. C'est pourquoi il
est fréquent d'utiliser des code très léger sur microcontrôleur dans ce cas, on
ne peut se fier à la complexité d'un noyau Linux complet sur un processeur x86.
La communication avec les autres composants doit être réduite au strict
nécessaire, la consommation électrique est plafonnée. Il y a aussi des
interdictions plus concrètes comme le respect d'un code couleur pour les
interfaces (le rouge est par exemple réservé aux erreurs sévères et strictement
définies).
Concernant les normes, il y a aussi les standards comme le bus CAN pour
l'automobile ou l'A429 pour l’aéronautique qui sont incontournables pour
interagir avec le reste de l'appareil sans réinventer la roue systématiquement.
D'ailleurs l'analyse de ces normes mettent en évidence les contraintes de
l'environnement pour expliquer ces choix de design et le maintient de ces
normes anciennes sur des systèmes modernes. Cela fera l'objet d'un autre
article.
En somme, il faut respecter les contraintes du secteur d'activités qui
peuvent être importantes car il y a de fortes responsabilités derrière. Et cela
influe forcément le design de l'application et du matériel et de fait du
produit qui sera réalisé.
Conclusion
C'est un article un peu long qui se veut être une introduction générale. Par
la suite je compte présenter quelques petites choses :
- Étude d'une norme comme le bus CAN ou A429, qui sont assez simples, et
comprendre leur intérêt dans les systèmes actuels et les raisons d'une telle
conception ;
- Présenter des projets liés aux systèmes embarqués comme Yocto, buildroot,
U-boot ou le noyau Linux et expliquer le boulot d'un développeur sur ces
projets ;
- Expliquer certaines pratiques industrielles ou technologies dans le
secteur, pour comprendre certaines décisions qui peuvent paraître aberrantes
mais qui finalement le sont moins. Typiquement pourquoi il est rare qu'Android
soit mis à jour décemment sur la plupart des modèles vendus ? Pourquoi il est
difficile de faire un OS compatible avec tous les systèmes ARM ?
- Présenter certains bogues ou designs que j'ai rencontré dans le cadre de
mon travail.
Cela s'étendra dans le temps, je ne compte pas tout rédiger maintenant. Les
humeurs, les envies, les idées, tout ça.
N'hésitez pas si vous avez des suggestions, des corrections, des questions
ou de signifier si cela vous plaît / déplaît. Merci.
Original post of Renault.Votez pour ce billet sur Planet Libre.