Académique Documents
Professionnel Documents
Culture Documents
DESCRIPTIF DU COURS
Les systèmes embarqués et/ou intégrés rappellent par certains côtés les ordinateurs
d'antan, par les ressources limitées dont ils disposent. Ceci conduit à des besoins de
compacité de code et à une exploitation optimisée du matériel qui n'est plus de mise
dans les systèmes informatiques actuels où l'abondance de ressources de calcul et de
mémorisation est la règle. Que l'on ne s'y trompe pas cependant : comparaison n'est
pas raison, et les systèmes informatiques embarqués d'aujourd'hui sont souvent bien
plus performants que leurs prédécesseurs non embarqués, mais ils sont aussi
extrêmement contraints, et les quelques kilo-octets, microsecondes ou milliwatts qui
sont épargnés par un système d'exploitation ad hoc seront toujours utiles à
l'application, pour permettre de faire fonctionner mieux, de manière plus sûre et plus
longtemps un appareillage. Globalement, le but d'un système d'exploitation consiste à
abstraire et partager les ressources matérielles pour simplifier l'écriture des
applications. Les systèmes d'exploitation des ordinateurs modernes visent à optimiser
les temps de réponses moyens pour l'utilisateur face à un clavier et une souris, quitte
à requérir de nombreuses ressources à un instant donné pour garantir cet objectif.
Dans le monde de l'embarqué, un tel objectif n'a souvent pas de sens, car il n'y a pas
d'utilisateur à proprement parler et la notion assez subjective et mal formalisée de
temps de réponse acceptable est clairement inadaptée. Les systèmes d'exploitation
pour les systèmes embarqués ont en général besoin de contraintes clairement
précisées pour réaliser les services qu'ils sont sensés fournir. Ces critères peuvent être
liés à la performance temporelle, par exemple sur la latence minimale et maximale du
traitement des interruptions, en espace mémoire maximal requis, en capacité de
contrôle du matériel en vue par exemple de la basse consommation, etc. Les systèmes
pour lesquels la réalisation d'une action doit être faite dans un laps de temps prédéfini,
potentiellement de manière répétée, sont dits temps réel. Ils ont une importance
particulière dans le monde de l'embarqué, car le contrôle du déclenchement d'un air
Page 2 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
bag ou le décodage d'une vidéo n'ont d'intérêt que si l'action est réalisée dans le temps
imparti.
Par ailleurs, les méthodes de construction des systèmes d'exploitation ont évolué au
cours du temps et permettent aujourd'hui de n'inclure que les parties qui sont utiles à
la fois à l'application, si celle-ci est connue d'avance, ce qui est le cas bien souvent, et
au matériel. Elles permettent ainsi de construire un système « sur mesure » qui
maximise l'efficacité de l'appareil. L'intégration posant des questions cruciales de
rendement et de flexibilité, les systèmes intégrés actuellement en cours de conception
tendent à inclure plusieurs (voire de nombreux) processeurs. La gestion de ces
nombreux processeurs, qui peuvent être de type identiques ou différents, par exemple
un processeur à usage général et un processeur de traitement de signal, a clairement
un impact sur les systèmes d'exploitation destinés à être embarqués.
La plupart des applications intégrées actuelles font appel à des algorithmes qui sont
très gourmands en termes de ressources mémoire et de capacité de calcul. Ainsi, les
systèmes électroniques embarqués, du moins ceux qui visent les appareillages grand
public, doivent non seulement être d'un coût très faible mais ils doivent de plus fournir
une performance très élevée. Ce faible coût implique une faible consommation, car
cela seul permet l'utilisation de boîtiers plastique à faible coût (par opposition aux
boîtiers en céramique) et l'absence de radiateur et de ventilateur. La solution utilisée
dans le passé pour satisfaire ces contraintes a été de développer du matériel ad hoc :
il est généralement admis que le nombre de MIPS (millions d'instructions par seconde)
par watt (unité de mesure de la performance vis-à-vis de la consommation) est de deux
à trois ordres de grandeur plus élevé dans le matériel spécialisé que dans le logiciel.
Cependant, les applications récentes sont peu pérennes à cause de l'évolution
continue et en profondeur des différents standards sur lesquels elles se basent. Ainsi,
les solutions purement matérielles ne sont plus acceptables car elles ne permettent
pas une flexibilité suffisante pour s'adapter au besoin, et les solutions au moins
partiellement programmables sont maintenant la règle. En conséquence, il est à
présent reconnu que des systèmes d'exploitation dédiés sont nécessaires.
Il suffit de regarder autour de soi au quotidien pour voir et avoir d’autres SE sous ses
yeux. Vous êtes réveillé le matin par votre radio-réveil ; c'est un système
embarqué...Vous programmez votre machine à café pour avoir un bon petit serré ;
c'est un système embarqué...Vous allumez la télévision et utilisez votre télécommande
; ce sont des systèmes embarqués...Vous prenez votre voiture et la voix suave du
calculateur vous dit que vous n'avez pas mis votre ceinture (pas bien) ; c'est un système
embarqué...Vous appelez votre patron avec votre téléphone portable pour signaler
que vous serez en retard (pas bien) ; c'est un système embarqué ! On peut continuer à
énumérer tous les systèmes embarqués croisés sans le savoir au cours d'une journée.
Bref, les systèmes embarqués nous entourent et nous sommes littéralement envahis
par eux, fidèles au poste et prêts à nous rendre service. On en croise des dizaines par
jour sans le savoir avant de retrouver son seul et unique PC.
Ils sont donc partout, discrets, efficaces et dédiés à ce à quoi ils sont destinés.
Omniprésents, ils le sont déjà et le seront de plus en plus. On parle en fait
d'informatique (et d'électronique) diffuse ou ubiquitous computing/ubiquitous
hardware dans la langue de Shakespeare... Ils sont bourrés d'électronique plus ou
moins complexe et d'informatique plus ou moins évoluée.
Un SE ne possède généralement pas des entrées/sorties standards et classiques
comme un clavier ou un écran d'ordinateur. Le système matériel et l’application sont
intimement liés, le logiciel embarqué étant enfoui, noyé dans le matériel. Le matériel
et le logiciel ne sont pas aussi facilement discernables comme dans un environnement
de travail classique de type ordinateur PC.
1.1.1 Historique
L'omniprésence des systèmes embarqués dans notre vie est liée à la révolution
numérique opérée dans les années 1970 avec l'avènement des processeurs. Les
processeurs, de plus en plus rapides, puissants et bon marché ont permis cette
révolution et aussi le boom du marché de l'embarqué. Ceci se confirme au travers de
la loi empirique de Gordon Moore, cofondateur d'Intel, qui stipule que pour une
surface de silicium donnée, on double le nombre de transistors intégrés tous les 18
mois ! La figure ci-dessous montre cette évolution inexorable.
Enfin pour terminer cette partie, les systèmes embarqués sont aujourd'hui fortement
communicants. Cela est possible grâce aux puissances de calcul offertes par les
processeurs pour l'embarqué (32 bits en particulier) et grâce aussi à l'explosion de
l'usage la connectivité Internet ou connectivité IP. La connectivité IP permet
fondamentalement de contrôler à distance un système embarqué par Internet. Ce
n'est en fait que l'aboutissement du contrôle à distance d'un système électronique par
des liaisons de tout type : liaisons RS.232, RS.485, bus de terrain...
Cela permet l'emplio des technologies modernes du web pour ce contrôle à distance
par l'utilisateur : il suffit d'embarquer un serveur web dans son équipement
électronique pour pouvoir le contrôler ensuite à distance, de n'importe où, à l'aide d'un
simple navigateur. Il n'y a plus d'IHM spécifique à concevoir pour cela, ce rôle étant
rempli par le navigateur web.
Cela est une réalité : les chauffagistes proposent maintenant des chaudières pouvant
être pilotées par le web !
Il faut aussi noter la montée en puissance des communications sans fil dans l'embarqué
au détriment des communications filaires pour limiter le câblage et faciliter la mise en
place du système embarqué. Le Wifi et toutes les normes de réseaux sans fil IEEE
802.15 comme Zigbee ont le vent en poupe dans l'embarqué et surtout en domotique
(réseaux de capteurs sans fil par exemple).
Devant toutes ces contraintes, le concepteur adopte des règles de bon sens :
Faire simple.
Utiliser ce que l'on a déjà fait ou fait par d'autres. On appellera cela
pudiquement du design reuse.
Ne pas se jeter sur les technologies dernier cri. Quelle est leur pérennité dans le
temps ?
Ne pas se jeter sur le dernier composant sorti surtout s'il est grand public. Quelle
est sa pérennité dans le temps surtout s'il l'on travaille pour la défense où l'on
demande une maintenance sur 30 ans !
Utiliser des technologies éprouvées qui ont fait leur preuve. Ces technologies
peuvent d'ailleurs avoir plusieurs générations de retard par rapport à leurs
homologues grand public.
Pour le grand public, le concepteur de systèmes embarqués peut sembler faire de
l'inertie face aux nouvelles technologies mais il faut le comprendre : c'est pour le bien
du système qu'il conçoit surtout si la sécurité des personnes est en jeu…
Un système critique est un système dont une panne peut avoir des conséquences
dramatiques, tels des morts ou des blessés graves, des dommages matériels
importants, ou des conséquences graves pour l'environnement. Par opposé, un
système non critique va correspondre aux applications dédiées aux loisirs (les jeux
vidéo par exemple). Ainsi, sont par exemple critiques les logiciels intervenant dans :
les systèmes de transport : pilotage des avions, des trains, logiciels embarqués
automobiles ;
la production d'énergie : contrôle des centrales nucléaires ;
Les systèmes les plus critiques sont généralement soumis à des autorités de
certification, qui vérifient que les impératifs prévus par la norme ont été remplis.
L'usage de méthodes formelles pourra, à l'avenir, être encouragé, voire imposé.
Le modèle en V de la figure ci-dessous est une autre façon de présenter une démarche
qui reste linéaire, mais qui fait mieux apparaître les produits intermédiaires à des
niveaux d’abstraction et de formalité différents et les procédures d’acceptation
(validation et vérification) de ces produits intermédiaires. Le V est parcouru de gauche
1.1 Introduction
1.1.1 Définitions
La plupart des systèmes embarqués temps réel sont avant tout des systèmes de
contrôle-commande. Un système de contrôle-commande est un système informatique
de contrôle de procédé. Le terme procédé est un terme générique désignant un
système physique contrôlé.
Afin de contrôler le procédé, le système informatique est en relation avec
l’environnement physique externe par l’intermédiaire de capteurs et/ou
d’actionneurs. Les grandeurs physiques acquises grâce aux capteurs permettent au
système de contrôle-commande de s’informer de l’état du procédé ou de son
environnement. Le système de contrôle-commande, à partir de consignes décrivant
l’état voulu du procédé, calcule des commandes qui sont alors appliquées sur le
procédé par l’intermédiaire d’actionneurs. Donnons ainsi une définition générale d’un
système de contrôle-commande comme illustré à la figure ci-dessous :
Un système embarqué est un système informatique dont les moyens de calcul sont
embarqués sur le procédé contrôlé. Le fait d’embarquer les moyens de calcul implique,
en plus des contraintes d’encombrement (taille, poids, forme), des contraintes de
consommation d’énergie puisque l’alimentation électrique des éléments de calcul est
soit embarquée (batteries, carburant, etc.), soit ambiante (panneaux solaires, etc.). À
technologie équivalente, l’énergie consommée par un calculateur est fonction du carré
de la vitesse de celui-ci ; en d’autres termes, plus le calculateur est performant, plus
l’énergie consommée est importante, avec une relation quadratique. Un système
embarqué se caractérise donc souvent par des ressources de calcul dimensionnées (ou
à dimensionner) au plus juste en fonction des besoins en calcul.
Un système critique est un système informatique pour lequel une défaillance, totale
ou partielle, du système, peut entraîner des conséquences graves, par exemple
économiques, humaines, écologiques, etc. La défaillance d’un drone d’observation
entraîne des conséquences économiques (perte de l’engin) mais surtout peut entraîner
des conséquences humaines en cas de collision, moteur allumé, avec une personne.
Un drone est donc considéré comme un système critique lorsqu’il évolue dans une
zone habitée. Un système est temps réel critique si une défaillance temporelle (le
système ne réagit pas suffisamment vite par rapport à la dynamique du procédé) peut
aussi entraîner des conséquences graves. Le drone peut être considéré comme temps
réel critique, puisque le fait de ne pas être capable d’appliquer les commandes de vol
à temps peut aboutir à une perte de contrôle. La plupart des systèmes de transport
sont des systèmes embarqués de contrôle-commande, temps réel critique.
Nous terminons cette section par des définitions qualifiant des systèmes temps réel
ayant des spécifications particulières. Ces contraintes temporelles peuvent être de
plusieurs types :
Contraintes temporelles relatives ou lâches (temps réel mou : soft real-time) :
les fautes temporelles sont tolérables (Ex. : jeux vidéo, applications
multimédias, téléphonie mobile...).
Ce retard peut affecter la prise en compte de n’importe quel événement, quelle qu’en
soit la gravité pour l’application. Il faut donc vérifier que l’architecture opérationnelle
choisie permettra de prendre en compte les contraintes temporelles : hypothèse de la
fenêtre de visibilité des événements ou d’instantanéité des actions. La capacité du
système à appréhender un événement externe est caractérisée par la durée de la tâche
la plus longue puisque les tâches sont non interruptibles ou non préemtibles.
Dans le cas du modèle synchrone d’exécution, nous avons un système
d’ordonnancement complètement prévisible et, en conséquence, il est possible en
faisant une analyse exhaustive de l’exécution de produire une séquence d’exécution
qui est jouée de façon répétitive. Cette étude de la séquence est appelée analyse de
l’ordonnancement hors-ligne. L’ordonnancement peut se réduire à un séquencement.
Nous avons alors un environnement informatique très simple de l’application
développée puisqu’il se réduit à une liste de tâches à exécuter. L’environnement
informatique pour piloter cette liste de tâches se réduit à un système très simple : un
séquenceur.
Dans ce contexte, nous avons des tâches qui sont interruptibles ou préemtibles. En
conséquence, l’ordonnancement n’est pas totalement prévisible et l’analyse de
l’exécution des tâches doit se faire en ligne par simulation ou par test. Cela nécessite
l’utilisation d’un gestionnaire centralisé des événements et de la décision d’exécution:
exécutif ou noyau temps réel.
Pour terminer cette section nous allons rappeler trois définitions importantes que nous
avons utilisées et fixer le contexte de ce cours. Nous avons ainsi défini :
Tâche non préemptible ou préemptible :
-Une tâche non préemptible ne peut être interrompue qu’à des endroits
spécifiques et à la demande de la tâche elle-même : fin_de_tâche,
attente_signal… Dans ce cas, la programmation est plus simple et aucun
mécanisme de partage de ressources critiques n’est à prévoir. En revanche,
des temps de réponse longs peuvent se produire.
-Une tâche préemptible peut être interrompue à n’importe quel instant et
le processeur être affecté à une autre tâche. Dans ce cas, les temps de
réponse à un événement externe peuvent être très courts ; mais nous avons
alors une programmation plus complexe avec un besoin de mécanisme de
partage de ressources critiques.
Analyse de l’ordonnancement hors-ligne ou en ligne :
Il est important de noter que les tâches sont les unités actives du système ; le
noyau temps réel n’est actif que lors de son appel. Une tâche activée peut
appeler le noyau temps réel par une requête. Les différentes requêtes sont
servies par des modules du noyau temps réel appelées primitives. Ensuite le
noyau temps réel réactive une tâche de l’application selon l’algorithme
d’ordonnancement utilisé (voir figure ci-dessous).
Ainsi le noyau temps réel centralise toutes les demandes d’activation des tâches et
gère des tables lui permettant de comparer les priorités (ou les urgences) et l’état de
ces diverses tâches, ainsi que l’état d’occupation des ressources. La décision
d’activation d’une tâche étant prise, le noyau temps réel lance les modules de
programmes correspondant à cette tâche et lui alloue les ressources disponibles. La
tâche activée occupe un processeur jusqu’à la fin de son exécution sous le respect des
conditions suivantes :
Elle ne réalise pas d’opérations d’entrées-sorties ;
Les ressources utilisées sont disponibles ;
Aucun événement extérieur ne revendique le déroulement d’une tâche plus
prioritaire.
Langages utilisés pour développer les applications avec un noyau temps réel (1:
gestion des interruptions, 2 : ordonnancement, 3 : relations entre les tâches)
Langages standards (langage C...) : le noyau temps réel qui supporte ce type de
langage doit être complet puisque le langage n’intègre aucune spécificité multi-
tâche.
Langages multitâches (langage C, Ada, Java...) : ces langages permettent de
décrire l’application en termes de tâches ; ainsi le noyau peut être plus réduit
et ne comporter que les deux premières fonctions.
Langages réactifs (langages Lustre, Esterel, Signal...) : ces langages donnent non
seulement la possibilité de décrire les fonctionnalités du programme, mais
aussi l’enchaînement des différentes parties. Le noyau est donc limité à une
couche proche du matériel lié notamment à la gestion des interruptions. En
revanche, étant donnée la possibilité très limitée d’expression de l’aspect
fonctionnel, ils sont souvent associés à un langage standard pour pallier ce
manque.
Au fil des années, il nous est apparu comme une évidence que le moyen le plus naturel
de concevoir un système pour un ingénieur est une approche descendante, partant de
fonctions de haut niveau, qui seront décomposées de façon arborescente jusqu’à des
fonctions élémentaires. Différents formalismes sont utilisés, comme SART
(Structured Analysis for Real-time), ou SysML (Systems Modeling Language) : ceux-ci
permettaient déjà d’opérer une analyse fonctionnelle descendante. Le point commun
de ces trois formalismes (SART, SysML, Capella) est que l’on utilise des diagrammes
flots de données pour la décomposition fonctionnelle. En effet, si l’on pouvait faire
l’hypothèse que tout traitement s’exécute en continu et de façon instantanée,
hypothèse qui est généralement faite pendant la phase de décomposition
fonctionnelle, alors tout système embarqué pourrait être totalement conçu à base de
flots de données.
L’exécution de celui-ci contrôlerait le système tel que le concepteur le souhaitait. La
manière dont les systèmes sont conçus a aussi évolué au cours de ces dernières
décennies. De façon à diminuer les coûts, on a pu voir des sociétés se spécialiser dans
différentes phases, et il est de plus en plus fréquent qu’un système soit spécifié par un
donneur d’ordres, décomposé en sous-systèmes, eux-mêmes spécifiés de façon
détaillée par un équipementier, qui sera à son tour donneur d’ordre pour externaliser
le développement de certaines fonctions élémentaires, développement ayant lieu
souvent en off-shore de façon à en diminuer les coûts. Ce sont donc souvent des
équipes pluriculturelles, ne communiquant pas directement, qui sont amenées à
joindre leurs efforts pour développer un système de grande envergure.
Il est donc primordial qu’une spécification soit bien comprise, et que toute fonction
non triviale puisse être exprimée de façon non ambigüe. L’expression formelle du
comportement attendu dans la conception de systèmes est un très bon moyen de lever
toute ambiguïté. Elle a bien entendu un coût en temps non négligeable, puisqu’il est
plus rapide de spécifier une fonction, en exprimant le comportement attendu en
langage naturel, plutôt que d’exprimer son comportement par un modèle formel.
Cependant, le modèle formel pourra être utilisé lors de la phase de validation formelle,
si elle existe pour le système, mais aussi simplement comme outil de test des fonctions
développées, voire même pour générer automatiquement le code de celles-ci.
L’expression formelle des comportements a pris plusieurs formes dans
les méthodes de spécification et conception durant les dernières décennies : de
l’utilisation de réseaux de Pétri, aux Grafcets, en passant par l’utilisation de différents
formalismes de machines à états. L’un de ces formalismes nous semble
particulièrement intéressant pour sa relative simplicité d’utilisation : le statechart, issu
des travaux de David Harel, et normalisé par l’OMG comme machine à états d’UML. Le
Page 35 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
choix de ce formalisme n’est pas un hasard : en effet, il intègre en particulier le concept
de régions orthogonales, permettant d’exprimer de façon parallèle le comportement
d’un système. Il est ainsi possible de spécifier formellement le comportement d’un
système de façon ascendante : le concepteur peut ajouter des détails au fur et à
mesure qu’il avance dans l’expression du comportement. Marier ce formalisme
ascendant à une méthode de spécification fonctionnelle descendante ouvre de
nombreuses possibilités, puisque la méthode de spécification mêlant flots de données
et automates de Harel peut être, au besoin, ascendante ou descendante.
L’approche « flots de données » pourrait donner directement l’implémentation d’un
système, si l’on pouvait considérer que toutes les fonctions s’exécutent
instantanément et en continu. Cependant, cette hypothèse est généralement éloignée
de la réalité sur un système embarqué. En effet, plus les ressources de calcul sont
importantes, plus l’énergie consommée par celles-ci est importante. Dans la
conception de systèmes embarqués, la dernière phase précédant l’implémentation est
donc la phase de co-conception logiciel/matériel, pendant laquelle le concepteur est
amené à choisir un rythme discret d’exécution de ses fonctions, et qui l’amène à casser
la confortable sémantique flots de données utilisée jusqu’alors, dans le but de
minimiser les ressources de calcul, et donc d’énergie, à embarquer sur le système.
Lorsqu’on parle de co-conception logiciel/matériel, on pense aussi à la conception de
matériel. Or, il existe aujourd’hui de très nombreuses cartes électroniques sur étagère.
Il nous semble donc que la diversité et le coût réduit de ces plateformes sur lesquelles
les systèmes embarqués sont déployés rend relativement rare le besoin de développer
sa propre architecture matérielle. Par conséquent, le parti pris du cours est de montrer
comment déployer le système logiciel sur des ressources matérielles existantes. Les
métriques non fonctionnelles, en particulier la réactivité du système de contrôle par
rapport au procédé contrôlé, sont très fortement impactées par le rythme choisi pour
l’exécution des fonctions. Cependant, le problème général du choix du rythme
d’exécution des fonctions pour respecter des contraintes temporelles de bout en bout
est en général un problème complexe. D’autant qu’à ce niveau de la phase de
conception, de nombreuses informations manquent. Par exemple, on n’a
généralement qu’une idée approximative de la durée d’exécution des fonctions, même
prises individuellement, puisque celles-ci n’ont souvent pas encore été déployées sur
la plateforme cible.
La méthodologie de co-design présentée ici est basée sur la méthodologie MCSE et est
caractérisée par une approche système, une modélisation selon 3 vues (fonctionnelle,
comportementale et architecturale), une architecture cible hétérogène et non figée,
une méthode de partitionnement interactif basée sur une évaluation des performances
dynamiques, une technique de co-simulation macroscopique et non-interprétée basée
sur un modèle d’attributs et une technique de co-synthèse incluant la génération des
interfaces matériel/logiciel qui repose sur un modèle de bus (protocole) générique et
l’utilisation d’une librairie de fonctions d’adaptation vers un bus spécifique.
L’utilisation de la méthodologie MCSE est recommandée pour faire tout d’abord
l’approche système nécessaire afin de rechercher une solution si possible globalement
optimale vis-à-vis de l’ensemble des contraintes. La solution fonctionnelle développée
servira alors comme base pour identifier les parties qui relèvent du co-design. La
description fonctionnelle de chaque partie sert ainsi de spécification. L’architecture de
la solution complète se déduit par MCSE. Les parties de l’architecture plus spécifiques
du co-design seront décidées selon les contraintes à satisfaire.
MCSE est une solution possible comme schéma d'organisation pour tout
développement de systèmes électroniques et informatiques à caractère temps-réel.
Cette méthodologie conduit à la conception et la réalisation de composants, de cartes,
de systèmes à la fois pour les aspects matériel et logiciel, ainsi qu’au développement
de logiciels en divers langages de manière à particulariser le matériel pour que celui-ci
réponde aux fonctionnalités exigées de l'application.
Un développement, selon MCSE, est décomposé en 4 étapes :
- l'étape de Spécification qui a pour objectif d'élaborer une description externe la
plus complète possible du système à concevoir, et ceci à partir du cahier des
charges.
- l'étape de Conception fonctionnelle. Elle conduit à rechercher une solution pour
le système sous la forme d'un ensemble de fonctions et de relations entre celles-
ci. Cette solution est une vue orientée vers l'application et se doit d'être
indépendante de la technologie.
- l'étape de Définition de la réalisation. Il s'agit d'introduire la répartition
géographique et les interfaces physiques pour satisfaire les contraintes
technologiques, puis après avoir défini le partitionnement matériel/logiciel
compte-tenu des contraintes de temps et autres contraintes de réalisation, de
déterminer les spécifications des parties matérielles et logicielles.
- l'étape de Réalisation qui consiste à développer le matériel et le logiciel à partir
des spécifications de l'étape précédente.
La figure suivante montre l’organisation de la démarche pour cette étape. Une partie
des spécifications technologiques est considérée ici. Il s’agit des contraintes de
distance entre constituants ou/et entre entrées/sorties, des contraintes d’interfaces
physiques et d’interfaces homme/machine, des contraintes de performances, de
sûreté, de coût.
Durant l’activité de répartition géographique, un premier partitionnement est déjà
effectué. Il se base exclusivement sur les distances imposées entre certains
constituants du système. Il s’agit d’un partitionnement fonctionnel c’est-à-dire vis-à-
vis de l’objectif à satisfaire. La phase 1 amène ainsi à déformer la solution fonctionnelle
Page 40 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
de l’étape précédente au sens de son enrichissement par des détails en vue de
satisfaire des contraintes d’ordre technologique.
La phase 2 concerne cette fois le partitionnement du système complet et donc sa
solution fonctionnelle vis-à-vis de la technologie de réalisation, c’est-à-dire matériel ou
logiciel. Les contraintes influentes que sont les performances, la sûreté de
fonctionnement au sens large du terme, le coût, servent de base pour déterminer la
ou les parties qui conduisent à une réalisation purement logicielle, à une réalisation
purement matérielle, à une réalisation où une variation est possible entre le matériel
et le logiciel (partie qualifiée de co-design). Ce partitionnement est de niveau système
et se comprend bien lorsque l’on considère un système possédant le qualificatif de
complexe. La séparation radicale matériel ou logiciel est généralement assez simple
pour une grande partie du système. La partie restante (frontière à délimiter) qui se
veut plus délicate est celle relevant du co-design.
1.1.4 Bilan
La présentation faite dans ce paragraphe montre clairement que la démarche de co-
design n’est pas une activité isolée de la conception de l’ensemble du système. Faisant
partie intégrante de l’étape de définition de la réalisation, le travail de co-design est
appliqué sur une ou des parties qui ont été pleinement identifiées comme justifiant
d’une telle approche. En amont, en plus d’un partitionnement géographique réalisé
durant la conception préliminaire, un travail de partitionnement au niveau système
conduit à décider d’une première grande répartition matérielle ou logiciel si possible
optimale globalement. Il en résulte une identification de zones intermédiaires qui
nécessitent un travail plus approfondi qui est alors typiquement du ressort du co-
design. Pour ces parties, un optimum local est alors recherché. Une telle approche
système en 2 temps évite les écueils du “défaut de myopie” qui amènerait à trouver
un optimum local pour une spécification donnée sans s’être assuré que la spécification
résulte elle aussi d’un optimum pour le niveau système.
Bien entendu, lorsqu’un problème posé est seulement du ressort du co-design, seule
la démarche décrite par la figure 2.3 est suffisante à condition de disposer des
spécifications correctes et complètes de l’objet à concevoir. Pour décider de la bonne
démarche à suivre, une question importante à se poser est de savoir si le problème est
ou non “immergé” dans un problème plus vaste. On constate aujourd’hui que la
plupart des problèmes sont présentés isolés alors qu’en réalité ils ne le sont pas. MCSE
impose une démarche plus globale ne serait-ce qu’en imposant d’abord une analyse et
une modélisation de l’environnement de l’objet à concevoir, modélisation bien utile
en final pour la vérification et la qualification du système placé dans son
environnement.
1.3.1 La co-simulation
Une co-simulation est une simulation simultanée de la partie logicielle et de la partie
matérielle d’un système et de leurs interactions. Elle est utilisée pour observer le
comportement du système complet qui se compose de quatre classes d’objets: les
processeurs matériels ou co-processeur dédiés, les processeurs logiciels, le logiciel
s’exécutant sur les processeurs logiciels et la logique d’interface (communication inter-
processeurs).
Un système complet peut être simulé à différents niveaux de détail. Par exemple, un
processeur logiciel peut être décrit comme un ordonnanceur de tâches et le logiciel
comme un ensemble de tâches. Mais le processeur logiciel peut aussi être représenté
par une description architecturale détaillée (pipeline, cache, registre, ALU...) et le
logiciel par une séquence d’instructions du jeu d’instructions du processeur.
Généralement, plus le développement est avancé, plus la co-simulation est détaillée.
Au cours du cycle de développement, la co-simulation repose donc sur différents
modèles et vise plusieurs objectifs: elle sert à faire une vérification fonctionnelle ou
comportementale détaillée (modèle interprété), une évaluation des performances
(modèle non interprété) ou les deux simultanément (modèle hybride).
Nous considérons qu’une méthodologie de co-design repose sur l’utilisation de
plusieurs techniques de co-simulation: une co-simulation non-interprétée pour
l’analyse des performances lors de la phase de recherche de l’architecture et du
partitionnement matériel/ logiciel, une co-simulation fonctionnelle détaillée après
synthèse (ou co-vérification) pour valider l’implantation. On parle alors de vérification
d’un prototype virtuel.
Les techniques de co-simulation se distinguent par l’utilisation d’un modèle ou langage
unique ou non et par le niveau d’abstraction du modèle de description matérielle
(VHDL comportemental, RTL, netlist) et logicielle (C, jeu d’instruction, microcode).
Pour les techniques basées sur différents modèles de représentation des parties
matérielles et logicielles, il faut faire communiquer différents simulateurs
Les techniques mono modèles se distinguent par le degré d’abstraction du modèle des
processeurs logiciels (modèle d’attributs, modèle flot de ressource, modèle ISA du jeu
d’instructions).
Le modèle de performance de MCSE décrit sous une forme textuelle ou résultant d’une
saisie graphique sert de point d’entrée à un générateur de code (MCSE-GEN) qui le
transforme en un code VHDL simulable. La simulation du code généré produit un fichier
de trace représentant l'évolution des fonctions et des relations inter-fonctions
(mécanismes de communication et de synchronisation). Ce fichier est alors
directement exploitable par un outil d’analyse de performances (MCSE-PERF) pour la
présentation des résultats.
Le modèle de performance capable de modéliser la partie logicielle et la partie
matérielle est un modèle :
macroscopique: le système n’a pas besoin d’être entièrement détaillé ce qui
autorise à faire une évaluation des performances très tôt dans le cycle de
développement.
non-interprété: seuls les temps des opérations et des dépendances temporelles
sont pris en compte ce qui permet un parcours rapide du domaine des solutions
possibles d’un partitionnement tout en évitant l’écriture des parties
algorithmiques des opérations.
évolutif: la notion d’attributs permet d’enrichir le modèle. L’élément délicat qui
est le processeur logiciel pour la co-simulation, est représenté par sa puissance
Tout était donc pour le mieux dans le meilleur des mondes possibles, ou presque. A
cette époque le concepteur manipulait des objets élémentaires qui étaient des
surfaces rectangulaires de couleur. Un transistor était constitué de l’assemblage d’une
dizaine de ces rectangles (25 rectangles pour l’inverseur CMOS ci-dessous).
Les langages de description de matériel (HDL) ont ainsi fait leur apparition. Ils avaient
pour but de modéliser, donc de simuler, mais aussi de concevoir. Des outils
informatiques (placeurs-routeurs) permettant de traduire automatiquement une
description textuelle en dessins de transistors (dessins au micron) ont fait leur
apparition.
Les deux exemples ci-dessus montrent l’équivalence entre les deux types de
représentation. On imagine aisément comment passer de la forme schématique à la
forme textuelle. On comprend aisément aussi pourquoi les informations
supplémentaires contenues dans la première (symboles des portes, position relative
et orientation des portes, taille et couleur des objets, polices de caractère utilisées,
etc.) ne sont utiles qu’au seul concepteur humain. Les outils informatiques n’en ont
pas l’usage.
Une description textuelle est plus facilement transportable d’un outil de CAO à
l’autre, d’un concepteur à l’autre, d’une entreprise à l’autre. La portabilité est
accrue.
Il est beaucoup plus facile de modifier une description textuelle qu’un schéma.
La maintenabilité est plus grande.
On peut aisément archiver un module sous la forme de sa description textuelle
afin de le réutiliser dans un autre projet (éventuellement après modification).
C’est plus difficile avec d’autres représentations pour lesquelles le coût de mise
à jour est plus élevé.
Il s’agit de décharger les concepteurs d’une tâche de plus, afin de leur permettre de
travailler à un niveau d’abstraction encore plus élevé, de manipuler des objets
élémentaires encore plus grands. Pour ce faire, la description structurelle ne suffit plus.
En effet, le nombre de primitives utilisables ne doit pas dépasser quelques centaines ;
au-delà, le concepteur ne peut plus mémoriser le contenu des bibliothèques et donc
ne parvient pas à en tirer le meilleur parti.
Pour aller encore plus loin, il faut permettre au concepteur de décrire le “quoi” au lieu
du “comment”. Il doit pouvoir s’affranchir de la connaissance des primitives
disponibles. Le dispositif à modéliser ou à concevoir sera désormais représenté par sa
fonction et non plus par sa structure. C’est le synthétiseur logique qui déterminera la
structure automatiquement à partir de la fonction. Bien sûr, les possibilités de
description structurelle existent toujours mais on leur associe d’autres possibilités afin
d’augmenter l’efficacité de l’ensemble.
Il est important de comprendre la nature des différentes utilisations que l’on peut faire
des langages fonctionnels de description de matériel.
2.2.1 Simulation
En tout premier lieu vient la modélisation. Elle n’a pas pour fonction de décrire la
structure de l’objet mais son comportement. Celui qui écrit le modèle peut recourir à
la description structurelle pour se simplifier la tâche en découpant le problème en
sous-problèmes plus simples à modéliser, mais le découpage ainsi obtenu n’a aucune
raison à priori de correspondre au partitionnement qui sera effectivement utilisé lors
de la conception de l’objet. Le but de la modélisation, c’est la simulation. Ce qui compte
avant tout, c’est la fidélité - un modèle se doit d’être aussi précis que possible dans son
champ d’application - et l’efficacité - le modèle doit pouvoir être simulé le plus
rapidement possible et doit être portable, réutilisable et facile à maintenir.
Pour simuler un modèle, il faut disposer du modèle, bien sûr, mais aussi de stimuli,
c’est à dire de la description des signaux d’entrée du modèle au cours du temps. Jadis,
avec les langages structurels, il n’était pas possible de décrire les modèles et les stimuli
d’entrée à partir du même langage. Il fallait donc utiliser plusieurs langages, plusieurs
outils et c’était autant de risques d’erreurs et de coups portés à la portabilité.
2.2.2 Synthèse
Les langages fonctionnels de description de matériel servent aussi - et c’est sans doute
là l’une de leurs fonctions premières - à concevoir. Il ne s’agit plus de modéliser en vue
de la simulation, mais de décrire les objets qui seront véritablement fabriqués.
modèle physique
Chacun de ces modèles peut être plus ou moins raffiné, selon la finesse des détails
qu'on y présente.
On représente souvent ces trois types de modèles et leur degrés de finesse selon un
diagramme dit "en Y" :
Diagramme en Y
De plus, la frontière entre les différentes descriptions est souvent floue (sans compter
les abus de langages). Par exemple, une représentation comportementale sous forme
d'équation booléenne (S = A XOR B XOR C) suggère une implémentation directe sous
forme de portes logiques (ici deux portes XOR). Cette équation peut donc être vue
soit comme une description comportementale (ce qui compte alors est juste la
fonction réalisée, et peu importe si on a vraiment des portes XOR ou bien plein
de AND, de OU et de NOT...)
Les abus de langage font aussi qu'on présente souvent le plus haut niveau d'abstraction
d'un système comme comportemental même s'il est structurel. Et bien souvent on
parle de RTL à la place de comportemental et vice-versa, alors que le RTL n'est qu'un
de ses niveaux de finesse...
Bref, les frontières entre niveaux sont floues, celles entre les modèles aussi.
Verilog est particulèrement à l'aise dans les descriptions de bqs niveaux, mais
manque un peu de souplesse dans le comportemental de très haut niveau (il ne
sait par exemple pas modéliser les entités abstraites telles que des OS, des
mutex, des canaux de communications, ...).
VHDL est semblable à Verilog, permet un tout petit peu plus de haut niveau dans
le comportemental (il dispose de la notion de pointeurs), mais est moins adapté
au bas niveau.
SystemC est très peu adapté au bas niveau. Il a été conçu pour modéliser les
système à des niveaux intermédiaires jusqu'à très haut. Il sait modéliser des
entités propres aux OS telles que des mutex, des sémaphores, ... et dispose d'un
moyen simple de modéliser des canaux de communication abstraits (ethernet,
UMTS par exemple). Il laisse les très bas niveaux (transistors) à Verilog, VHDL et
aux langages dédiés (SPICE, ...).
De plus, les habitudes de travail font que chaque niveau n'est pas conçu par les mêmes
personnes, et chaque population a ses propres habitudes. Par exemple, la description
de plus haut niveau d'une chaîne de traitement UMTS sera faite par des gens du
traitement du signal, qui représentent généralement leurs algorithmes en C ou en
Matlab. C'est le niveau du dessous qui sera traité par les électroniciens, qui
travailleront alors en Verilog, VHDL ou SystemC.
Le matériel est, par essence, parallèle. Dans un circuit intégré, tous les composants
sont actifs simultanément.
De ces deux considérations on déduit que la forme la plus probable des langages
fonctionnels de description de matériel comportera des aspects séquentiels et des
aspects parallèles. En d’autres termes, un modèle de composant électronique sera
composé de l’assemblage de plusieurs programmes séquentiels, s’exécutant en
parallèle. Le concepteur partitionnera son problème en modules assez simples pour
être décrits sous la forme de programmes séquentiels classiques, puis il assemblera ces
modules que le simulateur exécutera en parallèle.
Pour parvenir à ce résultat, il faut que les variables partagées entre processus
conservent leur valeur jusqu’à ce que tous les processus aient fini leur exécution. En
quelque sorte, on simule pas à pas et, à chaque pas :
Les variables partagées ou globales doivent donc être traitées d’une façon particulière.
On appelle ces variables des signaux, pour les distinguer des variables classiques.
les concepteurs aimeraient typiquement bien exprimer les stimuli de test ainsi
: "a vaut 0 initialement, puis 1 au bout de 10ns, puis 0 au bout de 35 ns, puis..."
un système doit pouvoir générer des horloges de fréquences différentes, donc
avoir une notion (au moins relative) du temps physique
il faut pouvoir éventuellement modéliser des temps de propagation
Pour pouvoir modéliser des portes idéales et des conducteurs parfaits (temps de
propagation nuls), il faut décorréler les pas de simulation du temps physique : prenons
l'exemple d'un inverseur parfait, dont le temps de propagation est nul. Si son entrée
change au temps t, sa sortie changera aussi au temps t. Pourtant les deux événements
(simultanés) n'auront pas lieu lors du même pas de simulation.
Autrement dit, un pas de simulation n'a pas de valeur temporelle physique intrinsèque.
C'est un intervalle de temps virtuel, appelé delta, dont la durée est nulle, qui ne sert
qu'à ordonner les événements "simultanés", c'est-à-dire à déterminer lequel a
provoqué lequel. Pendant un delta, le temps physique ne s'écoule pas.
Se pose alors le problème suivant : quand faire avancer le temps courant, quelle est la
relation entre ce compteur (temps physique courant) et les pas de simulation ?
2.6 La simulation
La solution à ce problème est simple et élégante, et possède pour une fois la bonne
propriété d’accélérer considérablement les simulations.
1. Chaque événement possède une date complète, comprenant une date physique
(1h, 17minutes, 43secondes, ...) et une date symbolique (... 4 deltas).
Lorsqu’une affectation de signal ne comporte pas de précision sur la date
Page 68 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
physique à laquelle l’événement doit avoir lieu, il est sous-entendu que la date
sera la date à laquelle l’affectation a été exécutée augmentée d’un delta.
Lorsque la date physique est précisée, la date de l’événement est exactement
cette date physique.
Notons que les synthétiseurs logiques n’utilisent pas le temps physique. Seul
l’ordre des opérations que subissent les données sont pertinentes pour la
synthèse. Le temps symbolique est donc le seul que les synthétiseurs
comprennent.
2. Le simulateur maintient un échéancier des requêtes pour chaque signal. Une
requête est le résultat d'une affectation; elle est composée de la valeur que doit
prendre le signal et de la date complète (date physique + date symbolique) du
futur événement. Lorsque tous les processus ont été exécutés et que toutes les
requêtes ont été enregistrées, le simulateur peut ainsi déterminer quel signal
doit changer de valeur lors du prochain pas de simulation. Il modifie donc les
signaux en question et avance le temps d’un pas (1 delta), puis il recommence
l’exécution des processus.
3. Afin de réduire les temps de simulation on optimise la stratégie du simulateur.
Les exécutions inutiles sont supprimées. Avant de commencer un nouveau pas,
le simulateur consulte l'échéancier, détermine la date du prochain événement,
ainsi que la liste des signaux devant changer de valeur à cette date, et saute
directement à cette date-là :
o soit en restant au même temps physique, mais en augmentant le delta
courant
o soit en sautant directement au temps physique correct; le delta courant
est alors remis à 0.
En fait, cette optimisation est même indispensable puisque la durée physique d’un
delta est nulle. Les durées symboliques ont pour seule fonction d’ordonner les
événements les uns par rapport aux autres. Si le simulateur ne faisait avancer le temps
que d’un delta à la fois, le temps physique n’avancerait pas.
L’aspect séquentiel est conservé à l’intérieur des processus. Ils obéissent aux règles très
classiques de la programmation séquentielle. On trouve les mêmes instructions et les
mêmes structures de contrôle qu’en langage C, en Pascal ou en Ada.
La seule exception à l’exécution séquentielle des processus concerne l’affectation des
signaux (voir ci-dessous).
De plus, chaque processus est une boucle infinie. Il doit donc comporter au moins un
point de synchronisation (appelé aussi point d'arrêt). Faute de quoi, le simulateur est
dans l’obligation de l’exécuter indéfiniment (temps physique et temps symbolique
n’évoluent pas, il s’agit d’un processus cyclique sans point d’arrêt).
Ce point d'arrêt est soit :
On peut considérer les processus comme des threads d'un OS multitâche, sachant que
l'OS en question est non-préemptif : chaque thread doit rendre la main au scheduler.
C'est le rôle des points d'arrêt.
On a déjà vu que leur affectation doit être traitée de façon spéciale (déférée à la fin
du delta courant). Lors de l'affectation des signaux, une instruction d’affectation
spéciale est créée. Lorsqu’une telle instruction est exécutée, elle ne prend pas effet
immédiatement. Elle est “enregistrée” par le simulateur, qui la traitera effectivement
lorsque tous les processus auront été exécutés.
Les variables locales aux processus sont traitées comme dans tout langage de
programmation classique. A la différence des signaux, elles sont modifiées dès
l’exécution d’une instruction d’affectation qui les concerne. Ces variables locales ne
sont, en général, pas visibles de l’extérieur du processus où elles sont déclarées. Un
autre processus ne peut ni les lire, ni les modifier. Elles ne sont pas réinitialisées d’une
exécution à l’autre du processus ; elles conservent leur valeur, comme si le processus
était en fait une boucle infinie dans un langage de programmation classique.
En VHDL :
En SystemC :
la différence entre signal et variable locale est aussi déterminée par le type
(sc_signal ou type C normal : int, bool, ...)
En Verilog :
une difficulté habituelle vient du fait que les deux ont le même type
(généralement reg). C'est la façon dont est écrite l'affectation qui détermine si
elle doit avoir lieu instantanément (la variable devrait alors être locale), ou être
déférée à la fin du delta courant (la variable est alors un signal de
communication entre processus). Nous verrons plus tard que
Page 71 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
- une affectation immédiate (dite bloquante) s'écrit ainsi : a = b;
- une affectation déférée à la fin du delta courant (dite non-bloquante) s'écrit
ainsi : a <= b;
Plutôt que de contraindre les utilisateurs à utiliser un type ou l'autre, Verilog fait
confiance à l'intelligence des concepteurs pour utiliser la bonne affectation.
Cela permet une souplesse accrue, au prix d'un risque de se tromper si on n'y a
pas pris garde.
3. Spécification SA-RT
La méthode SA-RT a été mise au point à la fin des années 80 pour exprimer les
spécifications des applications temps réel. La méthode SA-RT intègre trois aspects
fondamentaux d’une méthode de spécification :
L’aspect fonctionnel (ou transformation de données) : représentation de la
transformation que le système opère sur les données et spécification des processus
qui transforment les données ;
L’aspect évènementiel (piloté par les évènements) : représentation des
évènements qui conditionnent l’évolution d’un système et spécification de la
logique de contrôle qui produit des actions et des évènements en fonction
d’événement en entrée et fait changer le système d’état ;
L’aspect informationnel (données) : spécification des données sur les flots ou dans
les stockages. Ce dernier aspect, qui est en général assez négligé dans ce type
d’application, doit faire l’objet d’une description spécifique.
Le flot de données peut représenter aussi bien une donnée de type continu qu’une
donnée discrète codée par un booléen. Une donnée peut décrire une donnée
élémentaire ou bien une donnée structurée intégrant plusieurs données élémentaires.
La spécification détaillée est faite dans le dictionnaire des données.
Stockage de données : modélise le besoin de mémorisation d’une donnée de telle
façon que sa valeur puisse être relue plusieurs fois. Il est représenté par deux traits
horizontaux encadrant l’étiquette de la donnée. Les arcs arrivants et sortants ne
sont pas étiquetés, comme sur la figure ci-dessous (Exemple de stockage de
données).
L’étape de conception a pour but de décrire les éléments qui seront manipulés lors de
l’implémentation pour répondre aux exigences de la spécification.
3.3 Conception
Une méthode de conception doit permettre d’exprimer les différents éléments
constituants une application. Pour un système temps réel, on doit trouver :
Les tâches avec leur type d’activation et les paramètres ou données en entrée
et en sortie ;
Les relations entre les tâches : synchronisation de type asynchrone ou
synchrone (rendez-vous) et les communications avec les données qui transitent
entre les tâches ;
Le partage des ressources critiques.
La figure ci-dessous présente un exemple de BAL de taille 10 avec une gestion FIFO des
données et qui est bloquante pour le récepteur.
Plusieurs tâches peuvent demander l’accès à une ressource critique qui sera gérée en
exclusion mutuelle. Sa mise en œuvre au niveau de l’implémentation n’est pas
spécifiée dans la conception.
Phase 3 : Mise en place des transferts de données. Le transfert des données est traduit
par des communications ou par des ressources critiques. Il peut être nécessaire de
revoir le dessin de l’étape 2. Les relations de communication sont traduites par des
boîtes aux lettres ou par des modules de données. Leur établissement peut se faire en
se basant sur les deux règles suivantes :
Règle 3.1 : les communications directes entre les processus fonctionnels (flot de
données d’un processus fonctionnel à un autre) sont traduites
préférentiellement par des boîtes aux lettres.
Règles 3.2 : Les communications par une zone de stockage entre les processus
fonctionnels sont traduites préférentiellement par des modules de données, en
particulier si cette zone de stockage se trouve partagée par plus d’une tâche.
3.3.3 Un exemple de conception pour lire, afficher et de stocker l’état d’un bouton
L’application modélisée dans la figure ci-dessous a pour but de lire, d’afficher et de
stocker l’état d’un bouton. La fonction d’affichage et de mesure ne doivent pas être
regroupée pour des raisons de modularité. Les solutions proposées sont viables, mais
présentent chacune des inconvénients et surtout ne sont pas complètes…
Le processus de contrôle est lié aux différents processus fonctionnels par des événements qui
sont mis en place en même temps que la réalisation du diagramme état/transition de la figure
ci-dessous. Ce diagramme état/transition, description du fonctionnement du processus de
contrôle 5 (Contrôler mine), comprend quatre états :
– fonctionnement nominal de la mine (niveau d’eau inférieur à HLS et taux de méthane
inférieur à MS_L1) ;
– pompe en marche (niveau d’eau supérieur à LLS) ;
– état alerte (consigne MS_L1 dépassée et niveau d’eau inférieur à HLS, ou consigne MS_L2
dépassée et niveau d’eau quelconque) ;
– état alerte (consigne MS_L1 dépassée) et pompe en marche.
Nous pouvons remarquer que, dans ce diagramme état/transition complexe, nous avons
utilisé dans certains cas des combinaisons logiques de deux événements pour passer d’un état
Page 84 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
à l’autre, par exemple « MS_L2_dépassée OU Niveau_LLS » pour passer de l’état « État alerte
et pompe en marche » à l’état « État alerte ».
D’autre part, ce diagramme état/transition fait l’hypothèse pour la surveillance du taux de
méthane que les événements « MS_L1_dépassée » et « MS_L2_dépassée » se produisent
toujours dans l’ordre cité et, lors du retour à la situation normale, l’événement « Consigne
respectée » est émis.
1. Introduction
La conception et l’évolution des systèmes sont souvent ralenties par leur taille et leur
complexité. D’un côté, ces systèmes embarquent des applications logicielles utilisant
de plus en plus de nœuds de calcul devant collaborer et communiquer les uns avec les
autres. Et d’un autre côté, la capacité d’adaptation des plateformes matérielles est de
plus en plus importante notamment grâce aux cartes FPGA.
L’ingénierie basée sur les modèles consiste à fournir à l’utilisateur des interfaces de
représentation pour ce genre de systèmes. Les nombreux aspects de la plateforme
matérielle et de l’application logicielle sont abstraits sous la forme de composants. La
réutilisation et la hiérarchisation de ces composants permettent de modéliser un
système entier de façon claire et précise.
Afin d’augmenter la précision des modèles, il est possible d’associer différents types
de propriétés aux composants pouvant, ou non, être utilisés par des outils d’analyse.
Les objectifs ciblés par les méthodologies de conception basée sur les modèles sont
multiples :
Les modèles réalisés doivent permettre d’avoir une vision globale du système
pour permettre aux différents acteurs de sa conception de s’entendre sur
l’architecture et les caractéristiques de celui-ci.
Ces méthodologies doivent valider une cohérence du système assurant
robustesse, fiabilité et sécurité lors de son exécution.
Les modèles mis en place doivent permettre de réaliser des analyses
préliminaires sur le système et ainsi détecter des problèmes de conception très
tôt dans un flot permettant ainsi d’économiser beaucoup de temps.
Plusieurs méthodologies ont ainsi été mises au point pour répondre à ces objectifs,
comme des extensions du langage UML très portées sur une modélisation des
systèmes à travers différents diagrammes ou le langage AADL développé à la base pour
les domaines de l’avionique et de l’automobile qui nécessitent beaucoup de
vérification et de validation.
Nous avons retenu pour ce cours le formalisme AADL pour exprimer la co-conception
logiciel/matériel, car il permet de représenter tous les concepts qui nous semblent
importants dans cette étape. De plus, il est bien instrumenté, et de nombreux outils
ont été développés pour effectuer de l’analyse ou de la génération de code
automatique à partir de ce langage.
Le développement d’un système cyber-physique concerne de nombreux domaines : la
mécanique, la thermique, l’énergétique, l’informatique, l’automatique, la physique,
Page 86 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
voire la chimie, etc. Or aujourd’hui, ces domaines sont tellement développés qu’il est
rare de trouver un expert de plus d’un domaine à la fois. Chacun utilise ses propres
modèles, qui, par définition même du modèle, simplifient une grande partie de la
réalité pour se focaliser sur les concepts importants du domaine, en négligeant le reste.
Chaque domaine a pu se développer, et sait apporter de bonnes solutions sur son cas
particulier, sur ses propres modèles de la réalité. Le développement d’un système
cyber-physique aujourd’hui correspond donc souvent à la combinaison de plusieurs
briques, chacune traitant du système dans sa globalité, mais uniquement du point de
vue de son domaine. À partir de son propre modèle, chaque brique tente donc
d’optimiser un certain nombre de métriques, mais en prenant en considération les
autres briques de façon extrêmement simplifiée, via des contraintes de haut niveau,
(typiquement, un automaticien pourra dire à l’architecte système que le correcteur
fourni devra s’exécuter à 50 Hz). Les experts de chaque domaine ne sont souvent pas
à même de communiquer finement sur les leviers qui pourraient être employés pour
leur permettre d’améliorer leur solution (si la contrainte de 50 Hz a un
impact important sur l’architecture logicielle, est-ce que 51 Hz est acceptable ? De plus,
comment exprimer le fait que les données provenant des capteurs aient un certain
délai ? Est-ce que cela pourrait rendre le correcteur instable ?). L’ingénierie
collaborative tente de faire tomber les frontières entre les domaines, en permettant
aux modèles d’être facilement traduits d’un domaine à un autre. L’un des principaux
candidats pour faciliter la « traduction » inter-domaines est l’ingénierie dirigée par les
modèles. Dans le domaine des systèmes cyber-physiques, il nous semble que cette
technologie est prometteuse pour permettre, à terme, de concevoir un système non
pas comme un assemblage d’optimum locaux mais comme un optimum global.
Le langage AADL (Architecture Analysis & Design Language) a été développé par SAE
international et approuvé en 2004 comme le standard AS 5506. Ce langage a été conçu
dans l’optique de fournir un standard et une syntaxe précise pour des systèmes
critiques et de permettre une représentation simple et complète d’une architecture
pouvant être analysée très tôt dans le flot de conception. AADL est de plus en plus
utilisé dans des domaines porteurs et à la pointe de la technologie comme l’avionique,
l’automobile, l’aérospatial, la robotique et plus généralement dans le domaine des
systèmes temps réels.
Des composants logiciels et matériels sont déclarés et instanciés pour composer
l’architecture d’un système. Ils sont dans un premier temps modélisés comme « boites
noires » en renseignant leurs interfaces. Dans un second temps, la composition interne
et les détails de l’implémentation d’un composant sont déclarés. C’est ainsi que la
hiérarchie de l’architecture est mise en place puisqu’un composant peut être conçu à
partir de plusieurs autres composants.
Les systèmes temps réel peuvent être modélisés efficacement grâce à ce langage qui
permet d’appliquer des propriétés aux différents composants d’une architecture.
Certaines de ces propriétés sont notamment utilisées pour indiquer des spécifications
temporelles comme la période d’exécution d’un thread, son pire temps d’exécution,
ces échéances, etc.
En résumé, le langage AADL permet de modéliser l’architecture d’un système de façon
simple avec un haut niveau d’abstraction. Plusieurs outils peuvent ensuite se servir de
cette modélisation dans le but d’analyser et de vérifier l’implémentation et
l’intégration, mais surtout la certification du système.
La modélisation d’un système en langage AADL peut être réalisée de façon textuelle
dans un éditeur de texte, mais également par l’intermédiaire d’une interface
graphique. De nombreux éditeurs existent, mais on retrouve très souvent l’outil OSATE
qui est greffé sur l’IDE Eclipse. OSATE intègre les différents outils d’analyse d’un
modèle AADL qui sont directement accessibles à partir de l’interface de l’outil.
2.1.1 Composants
L'AADL est un langage déclaratif qui permet de définir des composants suivant deux
étapes : la première étape consiste à déclarer le composant comme une boite noire.
On lui associe alors des ports d'entrée et de sortie. La seconde étape permet de
déclarer une implémentation du composant en agissant sur la composition interne de
celui-ci comme les sous-composants et leurs branchements. Ces deux étapes de
Data
Certains ports de communications de composant sont référencés comme « data » ou
« event data ». Il faut alors renseigner le type de donnée associé à ces ports. Ces
données sont implémentées comme les autres composants AADL. Tel qu’illustré à la
figure ci-dessous (Déclaration d'un type de donnée) où « Data_type » fait référence au
type « long », elles peuvent faire référence à des types de données d’un langage.
Processor
Le processeur est le composant matériel qui va exécuter le code logiciel. Plusieurs
processeurs peuvent être déclarés dans un système. L’utilisateur doit alors renseigner
sur quel processeur s’exécute chaque thread.
Memory
Les mémoires permettent de définir des zones mémoires accessibles par tous les
threads du système.
2.1.2 Propriétés
L’un des grands intérêts du langage AADL est de pouvoir associer des propriétés aux
différents composants d’un modèle. Ces propriétés peuvent se présenter sous
différents types : les propriétés de type énuméré, de type entier, de type entier avec
unité (e.g. 50 ms), etc. Le langage offre une grande panoplie de propriétés pour chaque
type de composant utilisé, mais bien que la banque de propriétés disponibles soit
importante, il est possible qu’un utilisateur ait besoin de propriétés plus spécifiques.
Dans ce cas, il lui est possible de définir ses propres propriétés.
2.1.2.1 Déclarations
La déclaration des propriétés pour un composant peut se faire dans la déclaration de
celui-ci, dans son implémentation ou dans les deux. Elle est précédée du mot clé «
properties » comme on peut le voir sur la figure ci-dessous (Déclaration de propriétés
2.1.3 OSATE2
OSATE 2.0 (Open-Source AADL Tool Environment) est un outil libre basé sur IDE Eclipse
et peut être ajouté comme module d’extension à celui-ci.
2.1.3.1 Développement
Cet outil nous permet d’éditer du code AADL et de réaliser une analyse de celui-ci en
direct, permettant de faciliter la génération de code et la recherche de bugs. OSATE
permet, entre autres, d’analyser la consistance d’un flot de donné qui doit posséder le
même type de donnée.
Cet outil permet de générer un graphe pour faciliter la visualisation du système
développé. Il est également possible de créer et d’éditer un modèle directement à
partir de l’interface graphique pour des utilisateurs plus à l’aise avec ce type de
développement.
2.1.3.2 Tests
Le langage AADL permet de réaliser facilement des tests à haut niveau. Ces tests sont
très importants, car ils permettent de détecter très tôt des problèmes de conception
faisant ainsi économiser beaucoup de temps aux équipes de programmation. L’outil
OSATE 2 permet de réaliser bon nombre de ces tests préliminaires.
Page 93 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
2.2 SpaceStudio
SpaceStudio est un outil développé par la compagnie SpaceCodesign qui permet un
codéveloppement de la partie comportemental d’un système (i.e. le logiciel) et de sa
plateforme matérielle. Dans cette section, nous allons davantage mettre l’accent sur
l’utilisation de SpaceStudio qui va nous permettre de valider les spécifications à la fois
fonctionnelles et non fonctionnelles du système en créant un modèle exécutable
systemC et de réaliser l’implémentation du système au niveau RTL.
Le système que nous voulons réaliser est un système de ventilation : nous mesurons la
température, et lorsque celle-ci dépasse une température de consigne, un ventilateur
est commandé proportionnellement à la différence de température entre la mesure et
la consigne. Nous souhaitons afficher sur une console différente informations
Page 95 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
mesurées, comme la température, la vitesse du ventilateur, et la valeur de commande
envoyée à celui-ci.
La température de fonctionnement devrait se situer entre 0 et 100 °C.
Génération d’un signal sinusoïdal à 1 kHz à l’aide d’un PWM à 8 kHz et d’un filtre
passe-bas d’ordre 2
Il nous faut donc un système de contrôle permettant de lire une entrée analogique
(capteur de température), une entrée PWM (rotation du ventilateur), et d’écrire du
PWM en sortie à une fréquence de 25 kHz (commande du ventilateur). Une connexion
de type série ou USB permettrait de réaliser l’affichage initialement sur un PC.
Nous choisissons une carte microcontrôleur Arduino Uno, munie d’entrées-sorties,
parmi lesquelles nous pouvons trouver notamment six entrées analogiques, et une
douzaine d’entrées-sorties numériques. Ces dernières nous permettront de lire et de
générer des signaux PWM.
Arduino Uno : carte matérielle embarquant un microcontrôleur huit bits
ATmega328P à 16 MHz équipé de 32 ko de mémoire flash. La carte intègre
notamment 14 entrées/sorties numériques (dont six sont compatibles PWM),
six entrées analogiques multiplexées, et une liaison série. Le montage
expérimental 1 est donné sur la figure ci-dessous. La sortie analogique (fil
orange) de la sonde TMP36 est reliée à l’entrée analogique A0 du
microcontrôleur. Pour son alimentation, elle doit également être connectée à la
masse et à la sortie 5 V du microcontrôleur. La commande PWM (fil bleu) du
ventilateur est liée à la broche 3 INT1 du microcontrôleur, alors que la sortie
tachymètre (fil vert), lié à la broche 2 INT0, est montée avec une résistance de
tirage de 10 kΩ, de façon classique pour un circuit en drain ouvert (voir
encadré). Contrairement à la sonde, l’alimentation du ventilateur se fait en 12
V (fils jaune et noir). Le microcontrôleur est quant à lui directement alimenté
Les programmes et tout support numérique utiles sont disponibles sur le site internet
http://www.dunod.com. Il est conseillé à ce niveau de télécharger le matériel
numérique afin de pouvoir compiler, tester, et potentiellement modifier les
programmes.
Représentation de l’information
Toute information numérique est représentée en binaire, c’est-à-dire en base 2. En
base décimale, que nous utilisons tous les jours, la base est 10, ce qui nous laisse les
dix chiffres 0 à 9 pour représenter chaque multiplicateur de puissance de 10. Ainsi, le
nombre 123 se lit 1 × 10 2 + 2 × 10 1 + 3 × 10 0 , et est donc représenté par 123 en base
décimale. En binaire, il n’y a que deux chiffres, 0 et 1. Un chiffre binaire s’appelle un
bit, pour BInary digiT. Les bits permettent de représenter le nombre 123 comme 1 × 2
6
+ 1 × 2 5 + 1 × 2 4 + 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 1 × 2 0 , ce qui se lit 1111011 en base
binaire. Afin de distinguer les bases, nous utiliserons en préfixe la lettre « b » pour les
nombres donnés en binaire. Le nombre 123 se représente donc b1111011 en binaire.
La sonde de température est assez sensible aux variations de tension, en effet, nous
avons vu qu’une variation de 10 mV correspond à 1 °C. Une faible variation de tension
liée à une erreur aura donc un impact important sur la température mesurée. Nous
introduirons donc un filtre très simple de température : le filtre exponentiel de Poisson.
Ainsi, si la première mesure de température est notée T0, nous considérerons que la
température considérée à la mesure courante est donnée par T i = (1 − λ) Ti − 1 + λT où
Ti − 1 est la température considérée à la mesure précédente, et T est la mesure
effectuée. Le paramètre λ est un facteur d’oubli : lorsqu’il vaut 1, le filtre considère la
mesure instantanée comme étant la température courante, alors que lorsqu’il a une
valeur faible, les variations de température sont absorbées. Ce type de filtre lisse les
mesures et réduit le bruit lié aux erreurs, mais en contrepartie diminue la réactivité du
système. Afin de programmer ce filtre très simple, nous avons besoin de conserver la
dernière température lue, ce qui va être fait dans la variable temperature.
float temperature ;
Enfin, un tableau dans lequel nous placerons la durée des traitements est déclaré
globalement afin de ne pas avoir à le passer en paramètre à chaque sous-programme.
Ce type de programmation n’est pas très sûr, mais n’est ici utilisé que pour la phase de
mise au point et ne sera pas présent dans le programme final.
// Tableau utilisé pour stocker les durées des parties du
// programme
// 0: lecture analogique de température et calculs
// 1: lecture TPM
// 2: envoi sur le port série
unsigned long durees[3];
Points fixes
La valeur renvoyée par analogRead() est typique de ce qu’on appelle un nombre à
virgule fixe, ou point fixe. Ce nombre s’interprète comme un entier avec une unité qui
n’est pas unitaire, ici, l’unité est le 5/1 024 e de volts (avec la référence 5 V). Certains
langages de programmation, comme Ada, proposent des éléments syntaxiques
permettant au compilateur de vérifier que le développeur utilise ses points fixes de
manière consistante. En C, le langage ne permet pas la définition de points fixes, et il
est de la responsabilité du programmeur d’en assurer la consistance.
Remarque :char signifie caractère, car historiquement, le code ASCII encodant les
caractères américains était exprimé sur sept bits, auquel on adjoignait un bit tel que
chaque octet ait une parité paire, ce qui permettait de détecter des erreurs de
transmission entre le clavier et l’unité centrale des premiers ordinateurs. Ce code a
ensuite été étendu à huit bits, ajoutant ainsi 128 caractères et symboles possibles.
L’encodage des caractères est un défi, et la famille de normes Unicode s’y intéresse,
avec des caractères pouvant être codés sur un à quatre octets (en UTF-8, par exemple).
1. Introduction
Au cœur de la très grande majorité des produits électroniques actuels se trouvent
enfouis un (souris, montre, carte monétique, etc) voire plusieurs processeurs (voiture,
avion, etc). Un système embarqué, peut d'ailleurs interagir avec plusieurs sous
systèmes embarqués (un ordinateur et une souris par exemple). Différentes familles
de processeurs cohabitent sur le marché (MCU, GPP/MPU, AP/MPU, DSP, MPPA, FPGA,
GPU, etc), chacune répondant à des besoins et exigences (application/supervision ou
calcul/algorithmique, consommation, coût, encombrement, performance, etc). MCU
(Micro Controller Unit ou microcontrôleur) est l'architecture processeur la plus
répandue en volume sur le marché.
2. Architecture matérielle
Un système embarqué comprend un processeur, sa mémoire, ses interfaces d'entrée-
sortie interconnectés par des bus (figure ci-dessous). Cette partie correspond à
l'architecture matérielle classique d'un ordinateur et est plus ou moins sophistiquée
Page 109 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
en fonction des besoins de performance du système. Dans les versions les plus simples,
on retrouve des architectures matérielles proches de celles des systèmes à
microprocesseur des années 1980, avec néanmoins souvent la présence
d'accélérateurs matériels spécialisés pour une fonction donnée.
3. Architecture logicielle
L’architecture logicielle est le système de commande de l’ensemble du dispositif.
Sans le système d’exploitation (SE, Operating System, OS), le système informatisé n’est
qu’une boîte inutilisable. Le système d’exploitation fait l’interface entre le matériel et
le logiciel (figure ci-dessous) : il présente aux programmes une machine virtuelle,
relativement indépendante du matériel sous-jacent
Le logiciel de ces OS est réparti sur plusieurs unités de traitement (l’unité principale et
des unités annexes). Ces OS sont trop complexes pour être gérés par un seul
programme sur l’unité de traitement centrale. Une gestion multitâche est donc
nécessaire sur cette dernière et par conséquent un système d’exploitation est souvent
utilisé avec ces OS. Le logiciel de l’unité de traitement centrale est écrit avec un langage
de haut niveau tel que le C/C++. Les logiciels des unités de traitement annexes sont
souvent trop spécifiques et donc écrits avec à la fois un langage de haut niveau C/C++
et le langage d’assemblage.
Le terme bus de terrain est utilisé par opposition au bus informatique. En effet, le bus
de terrain est en général beaucoup plus simple, du fait des faibles ressources
numériques embarquées dans les capteurs et actionneurs. Il est également plus
robuste face aux perturbations externes.
5. Systèmes d’exploitation
5.1 Les contraintes de temps et les systèmes embarqués
La gestion du temps est l'un des problèmes majeurs des systèmes d'exploitation. La
raison est simple : les systèmes d'exploitation modernes sont tous multitâches or ils
utilisent du matériel basé sur des processeurs qui ne le sont pas, ce qui oblige le
système à partager le temps du processeur entre les différentes tâches. Cette notion
de partage implique une gestion du passage d'une tâche à l'autre qui est effectuée par
un ensemble d'algorithmes appelé ordonnanceur.
Tout d'abord, la notion de priorité entre les tâches est peu prise en compte, car
l'ordonnanceur a pour but premier le partage équitable du temps entre les différentes
tâches du système (on parle de quantum de temps ou tick). Notez que sur les
différentes versions d'UNIX dont LINUX, la commande nice permet de modifier la
priorité de la tâche au lancement.
Ensuite, les différentes tâches doivent accéder à des ressources dites partagés ce qui
entraîne des incertitudes temporelles. Si une des tâches effectue une écriture sur le
disque dur, celui-ci n'est plus disponible aux autres tâches à un instant donné et le délai
de disponibilité du périphérique n'est donc pas prévisible.
En outre, la gestion des entrées/sorties peut générer des temps morts car une tâche
peut être bloquée en attente d'accès à un élément d'entrée/sortie. La gestion des
Page 113 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
interruptions reçues par une tâche n'est pas optimisée. Le temps de latence - soit le
temps écoulé entre la réception de l'interruption et son traitement - n'est pas garanti
par le système.
Dans les systèmes classiques, le temps est partagé entre les tâches de manière
équitable. Alors que dans les systèmes temps-réel, les tâches doivent être exécutées
dans les délais impartis. On entend souvent parler de Temps Réel dès que l'on parle de
système embarqué. En fait, un système embarqué doit généralement respecter des
contraintes temporelles fortes (Hard Real Time) et l'on y trouve enfoui un système
d'exploitation ou un noyau Temps Réel (Real Time Operating System, RTLinux, QNX,
VxWorks, etc).
Le Temps Réel est un concept un peu vague et chacun a sa propre idée sur la question.
On pourrait le définir comme : Un système est dit Temps Réel lorsque l'information
après acquisition et traitement reste encore pertinente.
Plus précisément, cela veut dire que dans le cas d'une information arrivant de façon
périodique (sous forme d’une interruption périodique du système), les temps
d'acquisition et de traitement doivent rester inférieurs à la période de rafraîchissement
de cette information. Un temps maximum d'exécution est garanti (pire cas) et non un
temps moyen. Pour cela, il faut que le noyau ou le système Temps Réel :
• Soit déterministe : les mêmes causes produisent les mêmes effets avec les mêmes
temps d'exécution.
• Soit préemptif : la tâche de plus forte priorité prête à être exécutée doit toujours
avoir accès au processeur.
On est donc lié à la contrainte durée entre deux interruptions. C'est donc bien le
process extérieur à contrôler qui impose ses contraintes temporelles au système
embarqué et non le contraire. On est donc lié à la contrainte de délai entre deux
interruptions générées par le processus extérieur à contrôler.
Si cette durée est de l'ordre de la seconde (pour le contrôle d'une réaction chimique
par exemple), il ne sert à rien d’avoir un système à base de Pentium IV ! Un simple
processeur 8 bits du type microcontrôleur Motorola 68HC11, Microchip PIC, Scenix,
AVR... ou même un processeur 4 bits fera amplement l'affaire, ce qui permettra de
minimiser les coûts sur des forts volumes de production.
Si ce temps est maintenant de quelques dizaines de microsecondes (pour le traitement
des données issues de l'observation d'une réaction nucléaire par exemple), il convient
de choisir un processeur nettement plus performant comme un processeur 32 bits Intel
x86, StrongARM ou Motorola ColdFire.
L'exemple donné est malheureusement idyllique (quoique fréquent dans le domaine
des télécommunications et réseaux) puisque notre monde interagit plutôt avec un
système électronique de façon apériodique.
Si ce temps est maintenant de quelques dizaines de microsecondes (pour le traitement
des données issues de l’observation d’une réaction nucléaire par exemple), il est alors
nécessaire de choisir un processeur nettement plus performant comme un processeur
32 bits (processeurs ARM, ColdFire..). Dans le pire des cas, le traitement en Temps Réel
sera réalisé en logique câblé tout simplement.
Il est évident que la structure des systèmes temps réel dépendra de ces fameuses
contraintes. On pourra diviser les systèmes en deux catégories :
Les systèmes dits à contraintes souples ou molles (soft real time). Ces systèmes
acceptent des variations dans le traitement des données de l'ordre de la demi-
seconde (ou 500 ms) ou la seconde. On peut citer l'exemple des systèmes
multimédia : si quelques images ne sont pas affichées, cela ne met pas en péril
le fonctionnement correct de l'ensemble du système. Ces systèmes se
rapprochent fortement des systèmes d'exploitation classiques à temps partagé.
Ils garantissent un temps moyen d'exécution pour chaque tâche. On a ici une
répartition égalitaire du temps CPU entre processus.
Les systèmes dits à contraintes dures (hard real time) pour lesquels une gestion
stricte du temps est nécessaire pour conserver l'intégrité du service rendu. On
citera comme exemples les contrôles de processus industriels sensibles comme
la régulation des centrales nucléaires ou les systèmes embarqués utilisés dans
l'aéronautique. Ces systèmes garantissent un temps maximum d'exécution pour
chaque tâche. On a ici une répartition totalitaire du temps CPU entre tâches.
Un système temps réel n'est pas forcément plus rapide qu'un système à temps partagé.
Il devra par contre satisfaire à des contraintes temporelles strictes, prévues à l'avance
et imposées par le processus extérieur à contrôler. Une confusion classique est de
5.4.2 QNX
Développé par la société canadienne QNX Software (http ://www.qnx.com), QNX est
un système temps réel de type UNIX. Il est conforme à POSIX, permet de développer
5.4.4 Windows CE
Annoncé avec fracas par Microsoft comme le système d'exploitation embarqué qui tue,
Windows CE et ses cousins comme Embedded Windows NT n'ont pour l'instant pas
détrôné les systèmes embarqués traditionnels. Victime d'une réputation de fiabilité
approximative, Windows CE est pour l'instant cantonné à l'équipement de nombreux
assistants personnels ou PDA.
5.4.4 LynxOS
LynxOS est développé par la société LynuxWorks http://www.lynuxworks.com qui a
récemment modifié son nom de par son virage vers LINUX avec le développement de
Blue Cat. Ce système temps réel est conforme à la norme POSIX.
5.4.5 Nucleus
Nucleus est développé par la société Accelerated Technology Inc.
(http://www.acceleratedtechnology.com). Il est livré avec les sources et il n'y pas de
royalties à payer pour la redistribution.
5.4.6 eCOS
Acronyme pour Embeddable Configurable Operating System, eCOS fut initialement
développé par la société Cygnus, figure emblématique et précurseur de l'open source
professionnelle, aujourd'hui rattachée à la société Red Hat Software. Ce système est
adapté aux solutions à très faible empreinte mémoire et profondément enfouies. Son
environnement de développement est basé sur LINUX et la chaîne de compilation GNU
avec conformité au standard POSIX.
5.4.8 RTAI
RTAI (de l'anglais « Real Time Application Interface ») est une extension libre du noyau
Linux lui apportant des fonctionnalités temps réel dures. Le projet est toujours
maintenu et distribué depuis l'origine selon les termes de la licence GNU LGPL, et sous
la GPL pour la portion de code concernée par l'implémentation RTLinux. RTAI supporte
les architectures x86, PowerPC, ARM, MIPS. RTAI utilise logiciel Adeos.
Page 120 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
Il faut noter que l'étude s'applique uniquement au noyau 2.x (dernière version stable
disponible à ce jour). Des versions similaires du patch Prempt Kernel sont intégrées au
noyau de développement 2.x. Une fusion des deux patchs est peut être envisageable
dans le futur noyau 2.x (information sans garantie mais évoquée dans certains
interviews de Robert M. Love). De même, l'éditeur MontaVista Software diffuse une
Il est également nécessaire de valider le support RTC (Real Time Clock) car certains
outils de mesure de latence utilisent le device /dev/rtc.
Enfin il est nécessaire de valider l'utilisation du DMA (Direct Memory Access) sur le bus
PCI coté noyau ce qui normalement fait par défaut. L'utilisation du DMA permet
d'améliorer fortement les performances puisque le processeur n'est plus sollicité.
Ce script crée puis efface de manière répétitive des fichiers de 50 Mo. Une fois le
script lancé depuis une console, on pourra exécuter le test en tapant dans une autre
console :
Le système utilisé est basé sur un AMD Duron 900 MHz, équipé de 128 Mo de RAM,
d'un disque IDE récent (mais bas de gamme !) et de la distribution Red Hat 7.3. Bien
entendu, le résultat absolu de la mesure est très dépendant de l'architecture matérielle
du système. Le but est ici d'observer une tendance dans les résultats.
Avant d'effectuer les tests, il convient de vérifier grâce à la commande hdparm si les
accès disque utilisent le DMA que nous avons validé coté noyau.
# hdparm /dev/had
/dev/hda:
multcount = 16 (on)
I/O support = 0 (default 16-bit)
Page 125 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
unmaskirq = 0 (off)
using_dma = 0 (off)
keepsettings = 0 (off)
nowerr = 0 (off)
readonly = 0 (off)
readahead = 8 (on)
geometry = 3648/255/63, sectors = 58615258, start = 0
busstate = 1 (on)
Nous pouvons positionner le DMA ainsi que deux autres paramètres d'optimisation
(cependant moins importants) avec la ligne de commande suivante:
# hdparm -d 1 -c 1 -u 1 /dev/hda
/dev/hda:
setting 32-bit I/O support flag to 1
setting unmaskirq to 1 (on)
setting using_dma to 1 (on)
I/O support = 1 (32-bit)
unmaskirq = 1 (on)
using_dma = 1 (on)
Les options utilisées sont décrites ci-dessous dans un extrait du man hdparm:
“-u “ Get/set interrupt-unmask flag for the drive. A setting of 1 permits the
driver to unmask other interrupts during processing of a disk interrupt, which
greatly improves Linux' s responsiveness and eliminates "serial port overrun"
errors.
“ -c “ Query/enable (E) IDE 32-bit I/O support. A numeric parameter can be used
to enable/disable 32-bit I/O support.
Par contre lorsque le système est stressé par le script stress.sh on observe des
irrégularités sur les courbes (36 et 66 ms).
0.0 99828
0.1 118
0.2 5
0.3 2
0.5 3
0.6 2
0.7 1
1.1 1
2.4 1
2.5 5
2.6 5
2.7 2
2.8 4
2.9 2
3.4 1
4.0 1
6.3 1
9.5 1
11.4 1
11.9 1
12.0 1
12.1 1
12.2 1
12.3 1
12.5 1
12.7 1
12.9 1
13.3 1
13.4 2
13.6 1
13.7 1
14.3 1
15.1 1
Page 129 sur 144
Université de Dschang
Faculté des Sciences
Master Pro
15.2 1
Soit une latence maximale de 15 ms mais avec très peu de points supérieurs à 1 ms.
Le résultat est parfait. Si nous utilisons le programme realfeel2 sur le même système,
nous obtenons le fichier d'historique suivant sur 100000 itérations :
0.0 99858
0.1 134
0.2 5
0.3 3
Le patch Low latency semble être plus efficace que Preempt kernel. Ceci étant dit, des
études plus approfondies sur des cas réels permettront également de valider la
stabilité des noyaux modifiés s’ils sont soumis à de fortes sollicitations pendant un
grand intervalle de temps.
L’image d’un processus comporte du code machine exécutable, une zone mémoire
pour les données allouées par le processus, une pile ou stack (pour les variables locales
des fonctions et la gestion des appels et retour des fonctions) et un tas ou heap pour
les allocations dynamiques (new, malloc).
Ce processus est une entité qui, de sa création à sa mort, est identifié par une valeur
numérique : le PID (Process IDentifier).
Chaque processus a un utilisateur propriétaire, qui est utilisé par le système pour
déterminer ses permissions d’accès aux ressources (fichiers, ports réseaux, ...).
7.15.1. Le langage C
Le langage C a vu le jour à la fin des années 60. Son rôle initial était de permettre la
portabilité de la majeure partie du code d’un système d’exploitation d’une architecture
matérielle à une autre. En 1973, il est utilisé avec succès pour écrire un système
d’exploitation. Depuis, son utilisation n’a cessé de croître et il est le langage utilisé dans
l’implémentation de la majeure partie des systèmes d’exploitation. C’est aujourd’hui
encore l’un des langages de programmation les plus utilisés.
Le langage C est un langage de type impératif (en opposition aux langages déclaratifs,
fonctionnels, flots de données ou orientés objets) compilé. Il est faiblement typé, à
compilation séparée. Le langage C est sensible à la casse (majuscules/minuscules).
Le langage C dispose d’une bibliothèque exceptionnelle de composants logiciels, et la
quasi-totalité des langages de programmation peuvent s’interfacer avec le langage C.
Le langage C est fait pour le multiprocessus, mais pas pour le multitâche, ce qui
explique l’émergence de différentes normes temps réel dont POSIX est le représentant
le plus répandu.
Le langage C est assez proche de la machine, comparé aux langages modernes. Cet
inconvénient est cependant un atout indéniable lorsque l’on doit faire de la
programmation bas niveau, comme dans la programmation des entrées/sorties
spécifiques aux applications de contrôle-commande.
Le langage C est un langage de programmation normalisé. Aujourd’hui, des centaines
de compilateurs C et environnements de développement associés existent, aussi bien
en logiciel libre (le plus connu étant GNU C Compiler, GCC) qu’en logiciel commercial.
Références bibliographiques
6. Pierre Ficheux, Linux embarqué, Ed. Eyrolles, 2005.
7. Ch. Bonnet, I. Demeure. Introduction aux systèmes temps réel. Edition HERMES