Cours : Systèmes de Télécommunications Embarqués Classe : ING_TEL_3 Cours Systèmes Embarqués : Introduction 1- Introduction Un système embarqué est un système complexe qui intègre du logiciel et du matériel conçus ensemble afin de fournir des fonctionnalités données. Il contient généralement un ou plusieurs microprocesseurs destinés à exécuter un ensemble de programmes définis lors de la conception et stockés dans des mémoires. Le système matériel et l'application (logiciel) sont intimement liés et immergés dans le matériel et ne sont pas aussi facilement discernables comme dans un environnement de travail classique de type ordinateur de bureau PC ( Personal Computer) . Un système embarqué est autonome et ne possède pas des entrées/sorties standards tels qu'un clavier ou un écran d'ordinateur. Contrairement à un PC, l'interface IHM (Interface Homme machine) d’un système embarqué peut être aussi simple qu'une diode électroluminescente LED( Light Emitter Diode) qui clignote ou aussi complexe qu'un système de vision de nuit en temps réel ; les afficheurs à cristaux liquides LCD (Liquid Crystal Display) de structure généralement simple sont couramment utilisés. Afin d'optimiser les performances et la fiabilité de ces systèmes, des circuits numériques programmables FPGA (Fild Programmable Gate Array), des circuits dédiés à des applications spécifiques ASIC (Application Specific Integrated Circuits) ou des modules analogiques sont en plus utilisés. Le logiciel a une fonctionnalité fixe à exécuter qui est spécifique à une application. L'utilisateur n'a pas la possibilité de modifier les programmes. Bien souvent, il n'a pas conscience d'utiliser un système à base des microprocesseurs. Les systèmes embarqués sont désormais utilisés dans des applications diverses tels que le transport (avionique, espace, automobile, ferroviaire), dans les appareils électriques et électroniques (appareils photo, jouets, postes de télévision, électroménager, systèmes audio, téléphones portables), dans la distribution d'énergie, dans l'automatisation, …, etc. 2- Caractéristiques spécifiques Les systèmes embarqués fonctionnent généralement en Temps Réel (TR) : les opérations de calcul sont alors faites en réponse à un événement extérieur (interruption matérielle). La validité et la pertinence d'un résultat dépendent du moment où il est délivré. Une échéance manquée induit une erreur de fonctionnement qui peut entraîner soit une panne du système (plantage), soit une dégradation non dramatique de ses performances. Lorsque les systèmes embarqués sont utilisés dans les produits de grande consommation, ils sont fabriqués en grande série. Les exigences de coût se traduisent alors en contraintes sur les différentes composantes du système : utilisation de faibles capacités mémoires et de petits processeurs (4 bits ou 8 bits), mais en grand nombre. Ainsi, les systèmes embarqués sont particulièrement sensibles au coût de production. Il existe des applications dans lesquelles les contraintes de coût de production et de maintenance ont une importance de même niveau que les performances envisagées. Dans les systèmes embarqués autonomes, la consommation d'énergie est un point critique pour le coût. En effet, une consommation excessive augmente le prix de revient du système embarqué, car il faut alors des batteries de forte capacité. 3- Complexité Les système embarqués requièrent souvent un faible encombrement (faible poids) PDA(Personal Digital Assistant) , Internet et téléphone mobiles, …). Leur technologie fait alors appel à une électronique et à des applications portables où l'on doit minimiser aussi bien l'encombrement que la consommation électrique. Par conséquent, la réalisation du packaging afin de faire cohabiter sur une faible surface de l'électronique analogique, de l'électronique numérique, des composantes RF (Radiofréquence) sans interférences est une tâche difficile. En effet, les performances des systèmes sur carte deviennent obsolètes dans le contexte des besoins actuels. Dans les stratégies de conception actuelles, un système embarqué est généralement intégré sur un support silicium unique constituant ainsi un système complet intégré sur une puce SoC(System on a Chip). Les systèmes sur puce contiennent généralement une grande variété de dispositifs programmables tels que des microcontrôleurs, des processeurs de traitement de signaux DSP (Digital-Signal Processor) et des ASIC qui sont développés pour des applications complexes nécessitant une production en grande série. Les mémoires (ROM et RAM) y sont intégrés pour le stockage des données et des programmes. Ces composants digitaux cohabitent généralement sur le même support de silicium avec des composants analogiques et mixtes divers tels que des composantes radiofréquence (RF) comme moyen de communication, des composantes optiques pour le transfert de données à haut débit, des MEMS (Micro Electro Mechanical System) pour l'interfaçage avec le monde externe, des convertisseurs analogiques/numérique et numérique/analogique requis pour le dialogue interne. L'objectif est d'obtenir une coopération harmonieuse entre composants embarqués afin de garantir des services globaux. Des contraintes d'implémentation physique sont liées à la consommation de ressources et au contexte de déploiements tels que le poids, la taille physique, la résistance aux vibrations, ou aux irradiations, …, etc. 4- Criticité, fiabilité Du fait de leur portabilité et de la mobilité des produits dans lesquels ils sont incorporés, les systèmes embarqués évoluent généralement dans de conditions environnementales non déterministes et souvent non maîtrisées. Ils sont exposés à des variations et autres contraintes environnementales susceptibles d'induire des défaillances : vibrations, chocs, variation de température, variations d'alimentation, interférences RF, corrosion, humidité, radiations, … D'où la nécessité de prendre en compte des évolutions des caractéristiques des composants en fonction des conditions environnementales. En même temps que s'accroît leur sophistication, les systèmes embarqués sont utilisés dans des applications de plus en plus critiques dans lesquels leur dysfonctionnement peut générer des nuisances, des pertes économiques ou des conséquences inacceptables pouvant aller jusqu'à la perte de vies humaines. C'est le cas, par exemple, des applications médicales ou celles de transports pour lesquelles une défaillance peut avoir un impact direct sur la vie d'êtres humains. C'est aussi le cas des applications spatiales, souterraines ou sous-marines où la défaillance peut entraîner des conséquences redoutables aussi bien en termes de sécurité qu'au niveau économique. Ce type de systèmes doit garantir une très haute fiabilité et doit pouvoir réagir en cas de panne de l'un de ses composants. 5- Définition Quelle que soit la nature et la complexité du système, on décompose un système embarqués en : le système contrôlé le système de contrôle Le système contrôlé = environnement (procédé) équipé d'une instrumentation qui réalise l'interface avec le système de contrôle Le système de contrôle = éléments matériels (microprocesseurs) et logiciels dont la mission est d'agir sur le procédé via les actionneurs en fonction de l'état de ce procédé indiqué par les capteurs de manière maintenir ou conduire le procédé dans un état donné Un système électronique embarqué ou enfoui est un élément constitutif d'un système plus complexe pour lequel il rend des services bien précis (contrôle, surveillance, communication). Il est constitué de parties matérielles et logicielles qui sont conçues spécifiquement pour réaliser une fonction dédiée. Système embarqué = Système electronique/informatique conçu pour réaliser une ou plusieurs tâches précises. 6- Caractéristiques Les caractéristiques principales d'un système électronique embarqué sont : Autonomes. Une fois enfouis dans l'application ils ne sont (le plus souvent) plus accessibles Temps réel. Les temps de réponses de ces systèmes sont aussi importants que l'exactitude des résultats Réactifs. Il doit réagir à l'arrivée d'informations extérieures non prévues 7) Comparaison aux systèmes informatiques standards : Informatique : Processeur standard o Multiples unités fonctionnelles (flottant) o Vitesse élevée (> GHz) o Consommation électrique élevée o Chaleur o Taille MMU (mémoire virtuelle) OS Cache Grand nombre de périphériques Embarqué : Processeur dédié (contrôleur) o Architecture adaptée o Vitesse faible (~200 MHz) o 8-32bits : mémoire limitée o Basse consommation o Petite taille, grand volume => faible coût Processeur DSP (traitements) o Très puissants Quelques Mo de mémoire RTOS 8- Classification des systèmes embarqués 8.1) Système Transformationnel : Activité de calcul, qui lit ses données et ses entrées lors de son démarrage, qui fournit ses sorties, puis meurt. 8.2) Système Interactif : Système en interaction quasi permanente avec son environnement, y compris après l'initialisation du système ; la réaction du système est déterminée par les événements reçus et par l'état courant (fonction des événements et des réactions passés); le rythme de l'interaction est déterminé par le système et non par l'environnement. 8.3) Système Réactif ou Temps Réel Système en interaction permanente avec son environnement, y compris après l'initialisation du système ; la réaction du système est déterminée par les événements reçus et par l'état courant (fonction des événements et des réactions passées); mais le rythme de l'interaction est déterminé par l'environnement et non par le système. 9- Systèmes embarqués temps réel 9.1) Définition : (CNRS 1988) : Peut être qualifiée de "temps-réel" (ou "temps contraint", ou encore "réactif") toute application mettant en œuvre un système informatique dont le fonctionnement est assujetti à l'évolution dynamique de l'environnement qui lui est connecté et dont il doit contrôler le comportement. Ce sont des systèmes liés au contrôle de procédés l'exécution de programmes dans ces systèmes doit terminer avant une date appelée échéance au-delà de laquelle les résultats ne sont plus valides. On distingue deux types de systèmes embarqués temps-réel : Exemple critique : le contrôleur de frein d'une voiture • Système temps-réel dur/stricte (hard real-time) Le non-respect des échéances peut avoir des conséquences graves sur le fonctionnement du système ou sur son environnement (auto-pilotage, freinage, assistance médicalisée). Les échéances ne doivent jamais être dépassées. • Système temps-réel mou (soft real-time) Le non-respect des échéances ralentit le système sans conséquences graves (billetterie automatique). Le système doit répondre au mieux, le plus rapidement possible. La plupart des systèmes embarqués sont dit mutlirate ou multi-période Les données sont capturées à un certain rythme Les traitements sur ces données ne sont pas forcément à la même granularité Différents traitements peuvent intervenir de manière indépendante Les actionneurs fonctionnent à une fréquence différente 10- Architecture générale et modes de fonctionnement 10.1) Fonctionnement général : boucle infinie Tant que TOUJOURS faire Acquisition des entrées (données capteurs, mesures…) Calcul des ordres à envoyer au procédé Émission des ordres Fin tant que Mais, deux modes de fonctionnement : fonctionnement cyclique (time driven ou système "synchrone") fonctionnement événementiel (event driven) fonctionnement mixte : à base de traitements périodiques et et apériodiques (déclenchés sur événements) 10.2) Fonctionnement Cyclique : scrutation d'une mémoire d'entrée périodiquement (polling) échantillonnage des entrées sur l'horloge du système activation du système à chaque top d'horloge A chaque top d'horloge faire Lecture de la mémoire des entrées Calcul des ordres à envoyer au procédé Émission des ordres Fin Mais ce type de système est peu "réactif" si l'environnement produit des informations à des fréquences différentes ce qui oblige à prévoir toutes les réactions du système dans la même boucle donc il y a un problème de performance et en est obligé à imbriquer des boucles de fréquences multiples ce qui implique des difficultés de réalisation, de lisibilité du code et d'évolution 10.3) Fonctionnement Evénementiel : Le fonctionnement est basé sur le principe d'activation du système à chaque événement (notion d'interruption) A chaque interruption faire Lecture de l'information arrivée activation du traitement correspondant Émission des ordres issus de ce traitement Fin Mais dans ce cas le problème réside dans le cas où une interruption survient alors que le système est en train de traiter une interruption précédente, ce qui implique des contraintes de programmation : notion de priorité des interruptions notion de "tâche" associée à une ou plusieurs interruptions mécanisme de préemption et de reprise de tâche gestion de l'exécution concurrente des tâches (ordonnancement) => Un système temps réel est souvent un système multitâche incluant un gestionnaire de tâches (Ordonnanceur) 11- Exemple Le système de contrôle des gouvernes de l'Airbus A320 est un système embarqué dont les exigences sont : le système doit traduire en ordres de déflection des gouvernes les ordres de pilotage venant du pilote ou de pilote automatique (facteur de charge) Le système doit maintenir l'avion dans son domaine de vol quelles que soient les commandes du pilote ou du pilote automatique Compte tenu de la dynamique de l'avion, les ailerons et la gouverne de direction doivent être asservis à une période minimale de 10ms Compte tenu de la dynamique de l'avion, la gouverne de profondeur doit être asservie à une période minimale de 30ms La perte de contrôle à la fois des ailerons et des spoilers est catastrophique (taux de panne de 10-9) La perte de contrôle de la profondeur est catastrophique (taux de panne de 10-9) La perte de contrôle des spoilers, des ailerons, de la direction et de la profondeur ne doit pas être causée par une panne unique Chapitre 2. Systèmes embarqués et temps réel 1- Notions de systèmes temps réel 1.1-Système temps réel Système temps réel : système matériel ou logiciel sujet à des contraintes temps réel Par exemple, de devoir répondre en deçà d’une certaine période de temps à certains événements Fonctions fondamentales d’un système temps réel Collecte d’information (capteurs, communications) Actions du système sur son environnement (actuateurs) Interactions humain-machine (assister les opérateurs) Exigences temporelles Exigences associées à interactions humain-machine faciles à respecter Exigences provenant d’une boucle de contrôle sont beaucoup plus contraignantes 1.2-Exemple boucle de contrôle Exemple d’un système avec boucle de contrôle Objet contrôlé : cuve contenant un liquide Capteurs : température de la cuve et flot de vapeur Actuateur : valve modifiant le débit de vapeur 1.3- Types de systèmes Temps-Réel Temps-réel mou : un résultat en retard diminue la qualité de service, mais même en retard le résultat est toujours utile. Exemple : un distributeur de billets devrait répondre à la pression d’une touche en moins de 250ms, un retard diminue l’ergonomie, mais n’est pas dramatique. Temps-réel dur : un résultat en retard est inutile Exemple : déclenchement de l’airbag dans une voiture Caractéristiques et comparaison 1.3- contraintes de systèmes Temps-Réel Précision : il faut effectuer une action à un moment précis dans le temps (horloge électronique). Temps de réponse : effectuer une action avant son échéance (freinage pour un système de contrôle de vitesse) ou avec un temps moyen fixé (d´décompresseur vidéo, 24 images par secondes environ). Rendement : nombre de requêtes traitées par unité de temps (robot de production dans une usine). 1.4- caractéristiques de système temps réel Réponse garantie vs meilleur effort Si hypothèses précises sur charge et fautes rencontrées peuvent être énoncées, on parle d’un système avec réponse garantie Probabilité de défaillance revient alors à probabilité que les hypothèses de charge et de fautes ne soient pas respectées Sinon une telle réponse analytique n’est pas possible, on parle d’un système avec le meilleur effort (best-effort) Types de contrôle Contrôle activé par le temps : activités produites l’interne, par l’horloge Contrôle activé par un évènement : activités initiées par des évènements externes *Requiert un ordonnancement dynamique des taches Exemple illustratif : lecture des boutons d’appel d’un ascenseur *Contrôle activé par le temps : lecture des boutons est p ́périodique (pooling) *Contrôle activé par un évènement : appuyer sur un bouton génère une interruption immédiate au système 1.4- Caractéristiques des applications temps réel Utilisation du temps concret Au sein d'une application ou d'un système temps réel, il faut pouvoir manipuler le temps concret (horloge) Le temps réel (ou temps concret) sera utilisé de plusieurs façons : - Soit en définissant la date à laquelle une action doit être commencée - Soit en définissant la date à laquelle une action doit être finie Il peut être nécessaire de pouvoir modifier ces paramètres en cours d'exécution et de pouvoir préciser les actions à prendre en cas de faute temporelle Découpage en tâches Dans le monde réel, l'environnement du système temps réel peut consister en plusieurs actions qui évoluent simultanément (en parallèle ou en concurrence). Pour réduire la complexité de conception et calquer fidèlement la réalité, il faut utiliser la programmation concurrente : - utiliser un modèle de tâches ou processus concurrents. utiliser des moyens de communication et de synchronisation intertâches ou inter-process (mémoire partagée, boîtes aux lettres, files de messages, moniteurs, etc.). Respect des contraintes temporelles La limitation des ressources (en particulier du processeur) conduit à bloquer des processus (ils ne peuvent progresser du fait du manque de ressource) Afin de respecter en permanence les échéances, il faut gérer efficacement la pénurie et tenter de favoriser les processus dont l'avancement est le plus « urgent » Un ordonnancement consiste à définir un ordre sur l'utilisation des ressources du système afin de respecter les échéances. Ordonnancement On appelle ordonnanceur (scheduler), le processus système qui gère l'ordonnancement des processus (tâches) Un algorithme d'ordonnancement est une méthode ou stratégie utilisée pour ordonnancer les processus (tâches) Un tel algorithme s'appuie sur la connaissance de certaines caractéristiques des processus (tâches) ou du système processus (tâches) périodiques ou apériodiques ; préemption possible ou non ; échéance et pire temps d'exécution des processus (tâches) système à priorité fixe ou à échéance etc. 1.5- La structure d'un STR Un système TR est constitué de deux couches essentielles, la couche « matériel » et la couche « logiciel » • Hardware (matériels) : peut avoir plusieurs configurations suivant l'importance de l'application et le cout à investir. Cependant, la structure de base est la même. • Software (logiciel) : doit permettre l'exécution des tâches attribuées au calculateur, et de répondre en temps optimal à toutes les actions/lectures. 2- Structure et fonctionnement des systèmes temps réel embarqués 2.1- Système d’exploitation Définitions : Ensemble de logiciels pour l’exploitation des ressources d’un système ordonné • Forme une interface entre applications et matériel – Pilotes des périphériques – Fonctions de service pour les applications • Les versions de bureautique incluent minimalement des fonctions de gestion du clavier, de l’écran et d’un système de fichiers sur disque Composants d’un SE Le noyau (kernel) - Fonctions de base pour gérer la mémoire, les tâches exécutées, les fichiers, les entrées‐sorties principales, et les fonctionnalités de communication. L'interpréteur de commande (shell) - Permet de communiquer avec le noyau via un langage de commande prédéfini Le système de fichiers (file system ou FS) -Permet d’enregistrement des fichiers dans une structure de répertoires arborescente. Topologie générale d’un SE Trois couches logicielles entre les applications et le matériel Types de SE • Monoprocesseur, monotâche - Le SE alloue le CPU à un seul programme à la fois. Tant que celui‐ ci est en exécution, aucun autre ne peut s’exécuter (MS‐DOS) • Monoprocesseur, multitâche - Le SE répartit le temps de CPU entre plusieurs tâches, en utilisant un mécanisme de préemption (priorité ; Windows, Unix, Mac OS) • Multiprocesseur, multitâche - Le SE répartit l’exécution de tâches multiples sur plusieurs CPUs et assure leur synchronisation pour le partage des ressources (SE parallèles et exécutifs à temps réel) 2.2- Système d’exploitation embarqué L’application et le SE sont fusionnés Caractéristiques : - Le code du SE et celui de l’application résident dans de la mémoire non volatile La gestion des ressources est spécifique à celles présentes Moins de surcharge de traitement (overhead) SE de bureau vs. SE embarqué SE de bureau : l’application est compilée/assemblée séparément du SE - Au démarrage du système, le SE est lancé en premier SE embarqué : l’application est compilée/assemblée et liée de concert avec le SE - Au démarrage du système, l’application est lancée en premier ; elle part le SE ensuite - Seuls les composants du SE (services, routines, ou fonctions) requis par l’application sont ajoutés au code exécutable par l’éditeur de lien 3- Ordonnancement Temps Réel 3.1. Définition d’une tache Une tache est un programme qui s’exécute comme s’il était le seul à utiliser le CPU. Il possède une priorité, du code à effectuer, une partie de la mémoire et une zone de pile. 3.2. États d’une tache Une tache peut être dans un état : Pret : La tâche est prête à être exécutée mais n’a pas le CPU, actif : La tâche est exécutée par le CPU, bloqué : La tâche est en attente d’un signal ou d’une ressource pour poursuivre, 3.3. Types de taches Suivant les contraintes temporelles, le partage de ressources et la relation de précédence, on distingue les types de taches suivants : - Tâches dépendantes (figure c et d) / indépendantes (figure a et b) - Tâches répétitives / périodiques : activations successives (figure a) - Tâches répétitives / apériodiques (figure b) La figure (a) montre une tache périodique se déclenchant à des intervalles de temps réguliers (périodes) La figure (c) affiche deux taches dépendantes A et B reliées par une relation de précédence causale ; Tache A précède Tache B La figure (d) affiche aussi deux taches dépendantes partageant une section critique. 3.4. Priorités des tâches En fonction de sa criticité, chaque tache se voit attribuer une priorité. Les taches importantes auront des priorités élevées. Il existe deux types de priorité de taches : - statiques c’est-à-dire les priorités sont fixes, Chaque tache reçoit une priorité fixe lors de sa création et ne change pendant son exécution, - dynamiques c’est-à-dire les priorités sont variables et peuvent être modifié pendant l’exécution. 3.5. Ordonnanceur L'Ordonnanceur est le composant du noyau responsable de la distribution du temps CPU entre les différentes taches. Il est basé sur le principe de la priorité : chaque tache possède une priorité dépendant de son importance (plus une tache est importante, plus sa priorité est élevée). Il attribue le processeur à la tache exécutable de plus haute priorité. 3.6. Critères de performance d’ordonnancement Le choix d’une politique d’ordonnancement doit tenir compte des points suivants : Utilisation de l’UC : utiliser la CPU le maximum possible. Débit (Throughput) : nombre de taches qui terminent leur exécution par unité de temps. Temps de rotation (Turnaround time) – le temps depuis le lancement de la tache jusqu’à la fin de son exécution (les attentes incluses). Temps de réponse (Response time) : temps qui s’écoule entre l'entrée de la tâche et le moment où elle commence à être traitée. Temps d’attente (Waiting time) – temps de la tache dans la file d’attente des taches prêtes. Il est conseillé de maximiser l’utilisation de l’UC (proche de 100% c’est-à-dire pas de repos de le CPU) et de minimiser le temps de rotation, le temps d’attente et le temps de réponse. 3.7-Caractéristiques des tâches r : date de réveil: dans certains cas, un traitement doit être déclenché à une date précise relative par rapport au début de l’exécution de la tache ou absolue (plus rarement). Cette date de réveil n’implique pas obligatoirement l’exécution ; il peut y avoir un délai dû à l’indisponibilité du processeur. C : durée d'exécution maximale (capacité) D : délai critique (échéance ou deadline) : délai maximum acceptable pour son exécution ; le traitement doit être terminé à un instant spécifié par rapport au début de l’exécution de la tâche. P : période (si tâche périodique) d = r+D : échéance (si tâche à contraintes strictes) tâche périodique : rk= r0+ k*P si D = P, tâche à échéance sur requête La figure présente une tache périodique. On voit qu’il y a un décalage entre la date de réveil de la tache (r0 ou r1) et sa Date de démarrage c’est-à-dire l’instant correspondant à son exécution effective. Aussi, le traitement de tache doit se terminer avant le dépassement de son échéance pour éviter tout problème. La Date de fin d’une tache Ti est l’instant correspondant à la fin de son exécution. elle doit être à inferieure à di(deadline) et Pi(periode) 3.8. Paramètres statiques * U = C/P : facteur d'utilisation du processeur * CH = C/D : facteur de charge du processeur 3.9- Algorithmes d’ordonnancement des tâches indépendantes Pour les tâches indépendantes, il n’y a ni de partage de ressources ni de contraintes de précédence. Leurs ordonnancement est simple. On distingue deux catégories de taches indépendantes : Taches indépendantes périodiques Taches indépendantes apériodiques a- Rate Monotonic Analysis (RMA) algorithme à priorité constante basé sur la période (tâches à échéance sur requête) : la tâche de plus petite période est la plus prioritaire. La priorité d’une tâche est inversement proportionnelle à sa période. Plus la période est petite, plus la priorité est grande test d'acceptabilité (condition suffisante de Liu et Layland) Exemple 1 : Soit un système temps réel avec 3 tâches ayant les paramètres suivants : - Priorité(T1) < Priorité(T3)< Priorite(T2) La tache T2 est la tâche la plus prioritaire car sa période est la plus petite. - Condition de Lui Layland 3/20 + 2/5 + 2/10 = 0,75 < 0 ,78 les taches sont ordonnancables Exemple 2 : Soit un système temps réel avec 3 tâches ayant les paramètres suivants : - Priorite(T1)< Priorite(T2)< Priorite(T3) La tacheT3 est la tache la plus prioitaire car sa periode est la plus petite. - Condition de Lui Layland 12/50 +10/40 + 10/30 = 0,82 < 0 ,78 == on ne peut rien dire sur l’ordonnancabilité des taches Sur le graphe que les trois taches sont non ordonnacables. La tache T1 lui manque 2 unités de temps qu’elle doit les exécuter à partir de l’instant 50. Or cet instant est sa période. Donc, il est impossible qu’elle termine son exécution. Architecture des processeurs embarqués Exemple : Processeurs ARM 1- Introduction Très schématiquement on peut donc représenter les différents éléments constitutifs d’un processeur comme suit : Les éléments constitutifs d'un processeur L’unité arithmétique et logique (ALU) C’est la partie opérative du système. La seule partie qui capable de faire des calculs. Cependant, surtout sur un processeur dédié à l’embarqué, les capacités de calcul d’une ALU restent très limitées en terme de variété, même si elles peuvent s’exécuter très rapidement. Les opérations ordinaires d’une ALU sont : - l’accès à la mémoire, - - les additions/soustractions, - - les multiplications/divisions et toute une flopée d’opérations logiques portant sur des bits (opération ET, opération OU, décalages, rotations, compléments, extractions,…). Classiquement toutes ces opérations ne se font que sur des entiers (8 bits, 16 bits ou 32 bits), ce qui limite d’autant plus les capacités de calcul. Une banque de registres Généralement l’ALU ne communique pas directement avec la mémoire pour faire ses calculs. Pour gagner en rapidité et en efficacité, elle est connectée à des registres dont l’accès peut se faire en un seul cycle d’horloge. Ces registres sont : soit à usage général, pour stocker toutes sortes d’informations alimentant les calculs, soit spécifiques, dédiés à une tâche très précise. Parmi ces registres spécifiques citons-en 3 types : un registre qui contient l’adresse courante du programme en cours. Au cours de l’exécution du code, il se modifie tout seul pour aller chercher la prochaine instruction que devra réaliser l’ALU. Il est très souvent dénommé PC (pour Program Counter), un registre “de statut” qui renseigne sur l’état du processeur à un instant donné et qui est mis à jour en fonction de ce qui s’y passe. Entre autres informations essentielles pour un programme, on y trouve les « flags » c’est-à-dire des bits qui informent l’ensemble de la machine si la dernière opération exécutée par l’ALU a retourné une valeur nulle, une valeur négative… Remarquez que les structures algorithmiques classiques comme if-then-else, while, for, etc., sont réalisées au niveau du processeur à l’aide de ces flags, un registre contenant une adresse accessible en mémoire vive pour stocker des informations temporaires mais vitales pour le bon déroulement de l’ensemble. Cet espace mémoire est la PILE système (nous y reviendrons plus tard) et ce registre est le plus souvent dénommé Stack Pointer (SP). Mémoire ROM (Read Only Memory) Constituée de composantes ROM (Read Only Memory) ou FLASH (comme les clés USB), ces mémoires ont surtout la capacité de conserver leurs contenus lorsque l’alimentation est coupée. Cette mémoire va donc naturellement contenir le code à exécuter . Remarque : Une case mémoire (typiquement un octet) détient donc une valeur et se différencie des autres cases par une adresse unique (codée en général sur 32 bits). Le registre PC présenté ci-dessus va donc contenir la valeur sur 32 bits de l’adresse où le processeur pourra lire la prochaine instruction à traiter. De la mémoire « vive » (Random Access Memory) Ce type de mémoire est accessible en lecture et en écriture par le processeur. Toutes les variables que vous créerez dans votre programme se retrouveront naturellement stockées dans ces éléments. Contrairement à la mémoire en lecture seule, lorsque ces boîtiers mémoires ne sont plus alimentés, ils perdent de facto leur contenu. Une pile système C’est une zone de la mémoire RAM prédéfinie au départ par le programme. Cette zone est repérée (pointée) par un registre spécial (SP). Ce pointeur évolue au gré des écritures/lectures sur le principe d’une structure LIFO (Last In First Out: “dernier arrivé, premier sorti”). Remarque : La présence d’une pile est essentielle à un processeur. Par exemple, lorsqu’une interruption arrive au processeur. Dans ce cas le processeur doit cesser ses calculs en cours et se brancher sur la partie de code qui va faire les choses urgentes demandées au processeur pour répondre à cette demande d’interruption. Pour ne pas perdre ses calculs en cours et savoir où les reprendre, il doit stocker toute une série d’informations qu'il pourra restaurer à la reprise. L’endroit où il les stocke est la pile système. Il écrit ses données essentielles dans un certain ordre sur la pile système et les récupère dans l’ordre inverse en utilisant le mécanisme de la structure LIFO. 2- Les grandes familles de processeurs Les microprocesseurs Les DSP (Digital Signal Processing) Les microcontrôleurs : Ce sont des processeurs moins puissants que les microprocesseurs, mais dont les capacités de calcul peuvent être relativement très élevées au regard des besoins. Les FPGA (Field-Programmable Gate Array) 3- Principe et chaîne de compilation Pour construire une application embarquée, il est plus agréable d’utiliser une suite logicielle appelée IDE (Integrated Development Environment). Keil µVision en est un exemple. Un bon IDE est constitué de 6 éléments : Un éditeur : permet de saisir du code. Il doit être syntaxique (il reconnait par exemple les mots clés du langage et les colorise) pour maximiser le confort et la productivité de celui qui se trouve de l’autre côté du clavier. Un compilateur : outil logiciel qui transforme un code en langage structuré en un code assembleur compatible avec le processeur sur lequel le code va être exécuté. Généralement le fichier en langage d’assemblage n’est pas directement produit. Un assembleur : outil logiciel qui permet de transformer un fichier assembleur en fichier « objet » c’est-à-dire en un fichier exécutable incomplet. Il manque notamment toutes les adresses où seront implantées les variables et les procédures dans l’exécutable final. Un linker ou éditeur de liens : outil logiciel qui réunit l’ensemble des différents fichiers « objets » constituant le projet et qui attribue les adresses physiques de toutes les entités. Au final, il fabrique une image complète de l’exécutable. Un loader ou chargeur : outil logiciel et matériel qui permet de transférer l’image du programme en mémoire du processeur cible. Un débugger : outil logiciel et matériel qui permet de « prendre la main » sur l’exécution du processeur cible afin d’observer et de contrôler le déroulement du code sans modification de celui-ci. Mis à part les fichiers sources (*.c, *.s ou *.asm) et les fichiers objets (*.o ou *.obj) les principaux fichiers crées par les différents étages sont : Le fichier listing (*.lst) : contiennent des informations sur les erreurs de compilation et/ou d’assemblage. Le fichier mapping (*.map) : contient l’ensemble des informations relatives à l’organisation mémoire de l’application. On peut y trouver entre autres les adresses physiques où seront implémentées les variables, les procédures, les sections, etc. Le fichier exécutable (*.axf ou *.elf ou *.hex) : contient l’image (en binaire ou en version éditable de l’application). Remarque : D’autres fichiers peuvent être utilisées : des librairies (*.lib) : ce sont des fichiers objets un peu particuliers contenant un ensemble de procédures. Ils sont fournis généralement par un tiers qui ne tient pas à divulguer ses sources. Lors de l’édition de liens, ne seront insérés dans le code final que les parties des procédures réellement utilisées et nécessaires à l’application. En agissant ainsi, l’application ne se trouve pas alourdie par l’ajout d’une librairie complète et souvent conséquente en volume de code, des scatter files (*.sct ou *.ld) : pour faire son travail l’éditeur de lien a besoin d’avoir des informations sur les quantités et les types de mémoire qui existent dans la cible. Une telle spécification est contenue dans les scatter files. À noter que lorsque l’on utilise une IDE, cette information peut aussi directement être éditée dans les options de la cible. 4- Architecture des processeurs embarqués Un système embarqué se traduit par un système autonome. Cela implique au niveau de l’architecture des mécanismes qui permettent de minimiser la consommation électrique. Citons, par exemple, la capacité de n’activer qu’en fonction des besoins certaines parties du microcontrôleur ou encore d’avoir la possibilité d’endormir le circuit complètement si celui-ci n’est pas utilisé. 4.1- Architecture de microcontrôleur La figure suivante représente les blocs constitutifs d’un microcontrôleur Les périphériques Ces éléments constituent la partie la plus typique des microcontrôleurs. Comme le processeur doit « dialoguer » avec le monde physique qui l’entoure il doit posséder des éléments qui sont capables de réaliser cet interfaçage. Cela passe par des capacités hors norme de gérer le temps via des timers (synchronisation d’échange numérique) à la gestion de grandeurs analogiques (convertisseur analogiques numériques). Toutes ces parties périphériques peuvent être considérées comme des micromachines extrêmement spécialisées, mais autonomes. Elles sont évidemment accessibles pour le cœur, mais leur dialogue débute généralement par une demande du périphérique via un mécanisme d’interruption. Les principaux périphériques : Une application embarquée et un microcontrôleur pourront « dialoguer » ensemble si les signaux qu’ils se transmettent sont compréhensibles et compatibles entre eux. Cette information est transmise par les broches du circuit et donc sera toujours supportée par un signal électrique que l’on peut séparer en trois grandes classes : les grandeurs binaires les grandeurs analogiques les grandeurs numériques (succession de valeurs binaires dont la suite forme des valeurs codées) Le sens de transmission est aussi essentiel : pour une broche donnée, on va soit du processus physique au microcontrôleur (on dit que la broche est en entrée) soit l’inverse (la broche est en sortie). Les GPIO Allumer une lampe, savoir qu’un bouton poussoir est appuyé, ouvrir une électrovanne tout ou rien, détecter la présence d’une pièce avec un capteur inductif… Tous ces exemples montrent que beaucoup d’informations que l’on envoie ou que l’on reçoit du process sont binaires. En étant capable de piloter l’état binaire d’une broche (en entrée ou en sortie), il devient facile d’un point de vue fonctionnel de réaliser ces services. Même si ce n’est pas le sujet ici, il faudra tout de même s’interroger sur l’aspect électronique des branchements. Inutile d’espérer allumer un halogène de 500W sans un étage de puissance intermédiaire. Le timer La gestion du temps est une problématique générique et essentielle pour les systèmes embarqués et on se doute bien que les périphériques de type timer vont répondre à ce besoin. Les Capture/Compare Ces unités sont en quelque sorte des sous-fonctions des timers. Elles sont parfois directement associées aux unités timer, parfois elles sont indépendantes, mais auquel cas, elles intègrent une capacité propre de type timer. La fonction Capture consiste à dater un évènement lorsqu’apparaît sur une broche du circuit un front montant ou un front descendant ou un des deux. L’unité capture est donc associée à un signal de type binaire sur une broche, à un timer qui mesure le temps qui passe et à un registre pour stocker la valeur capturée du timer lorsque l’événement apparait. Exemple d’application : je mesure le temps pendant lequel un bouton poussoir a été appuyé. La fonction Compare est un peu le symétrique. Il y a toujours un signal de type binaire, mais le timer est remplacé par un compteur qui compte les événements (toujours les fronts) qu’il détecte sur la broche. Il a également, stocké dans un registre interne, une valeur dite de comparaison. Lorsque le compteur égale cette valeur l’unité va déclencher une demande d’interruption. Exemple d’application : je compte le nombre de pièces qui sont passées sur mon tapis roulant et je déclenche une action quand 100 pièces ont été détectées. L’ADC Le monde que l’on cherche à piloter peut nous indiquer son état à travers de grandeurs physiques (température, pression, distance, accélération, …). L’électronicien de service aura équipé le process d’un capteur qui transforme cette grandeur en une grandeur proportionnelle en volts. Le processeur lui ne connait que le monde numérique, il faut donc une unité spécialisée qui réalise cette transformation : l’Analog Digital Converter. Très généralement cette unité est branchée sur un multiplexeur, c’est à dire que plusieurs broches sont capables de porter un signal analogique et qu’il revient au programmeur de sélectionner logiciellement sur quelle(s) voie(s) d’entrée du multiplexeur il doit connecter l’ADC. Une grandeur importante qui qualifie un ADC est sa résolution, c’est-à-dire la quantité de valeurs entières que peut prendre l'ADC après conversion. Elle peut être donnée par : le nombre de bits du registre de conversion (par exemple 12 bits), le nombre de valeurs différentes de conversion (par exemple 1024=2101024=210), le quantum en volts entre deux valeurs numériques de conversion (par exemple si la pleine échelle est de [0V - 5V] on obtient 4,88mV=510244,88mV=51024). La PWM Le symétrique d’un ADC est un DAC (Digital Aanlog Converter) qui permet de transformer une valeur numérique en une valeur analogique proportionnelle permettant de commander le process. Cependant ces unités sont peu courantes dans une gamme complète de microcontrôleur. La raison principale est que ce genre de circuit consomme beaucoup (on transfère directement de l’énergie électrique). On peut d’autant mieux s’en passer qu’une unité Pulse Width Modulation peut très correctement remplacer un DAC. Ces unités PWM fournissent un signal binaire carré périodique dont on peut agir sur le rapport entre le temps à l’état haut et le temps à l’état bas. Dans l’exemple ci-dessous le signal est d’une période fixe Tp . Au début de la séquence le ratio Th1/Tp est fixé à 75%. Au temps τ, ce ratio est changé à 37%, le période Tp ne change pas, c’est le temps Th2 qui est diminué par rapport à Th1. Exemple : Considérons que ce signal commande un petit moteur électrique. Lorsque l’on applique une tension constante à un tel moteur à courant continu il va se mettre à tourner à une vitesse constante mais il lui faut un petit temps d’établissement pour passer de sa vitesse initiale à sa vitesse finale. Imaginons que l’on s’amuse à maltraiter le moteur en lui envoyant un signal carré lent, voici ce que donnerait l’évolution de sa vitesse en fonction du temps en réponse à ce signal de commande : Envoi d'un signal carré lent au moteur Supposons que nous répétions cette même expérience en augmentant maintenant la fréquence du signal d’entrée mais tout en maintenant le même ratio. Le moteur est toujours le même et son temps de réaction (temps d’établissement) est identique. Il va donc être amené à faire varier sa vitesse plus rapidement. Ci-dessous est représentée cette évolution en superposant le signal de commande de la PWM et celui du signal de la vitesse de sortie : Le moteur n’a plus le temps de s’adapter au changement intempestif de l’entrée qui n’arrête pas de changer entre 5V et 0V. Il ne va voir au final qu’une moyenne du signal. Cette moyenne correspond au 5V multiplié par le ratio. En jouant ainsi sur le ratio entre 0% et 100% il nous est possible de créer un pseudo-signal analogique aux yeux du système commandé. Cela suppose que la période de base Tp de la PWM soit correctement choisie : trop grande le système commandé va « suivre » les oscillations du signal d’entrée, trop petit on risque d’exciter les circuits électroniques du système commandé de façon plus ou moins néfaste. Les bus Pour de multiples raisons un système informatique a besoin d’envoyer des données à un autre système informatique. L’information prise à son plus bas niveau est une information binaire. Elle peut donc être transportée du point à un autre à l’aide d’un simple fil en faisant transiter sur ce fil une suite de 1 et de 0 qui forme la donnée numérique à transmettre. Le principe est simple, mais la mise en œuvre peut être bien plus complexe car il faut que l’émetteur et le récepteur se retrouvent et se comprennent. Le protocole le plus simple est celui de la liaison série asynchrone (Universal Asynchronous Receiver Transmitter). Un fil pour émettre, un pour recevoir et une masse électrique commune. Les données transitent octet par octet à une vitesse fixée à l’avance. Ce premier protocole peut se complexifier en ajoutant un signal d’horloge commun qui permet de synchroniser les données. On obtient alors un Universal Synchronous/Asynchronous Receiver Transmitter (USART). Une transmission RS-232 : Il faut souvent augmenter les débits et sécuriser les données pour s’assurer que ce qui est envoyé est correctement reçu. Il est également souvent nécessaire de connecter plus de 2 systèmes ensemble, induisant par exemple l’idée de réseau, de système maître/esclave pour la communication et aussi d’adresse numérique d’un système à contacter. Pour répondre à ces besoins est donc apparu sur le marché plusieurs standards de protocole. Les plus célèbres, car liés au monde de l’informatique, sont sans aucun doute l’Ethernet et l’USB. D’autres répondent à des besoins plus industriels et portent généralement le terme générique de bus industriel ou bus de terrain : I²C, SPI, CAN. 4.2- Les registres et les masques Sur les microcontrôleurs les périphériques sont configurés et contrôlés à travers des registres ayant une adresse mémoire réservée. Cela signifie que l’accès et la configuration d’un périphérique se fait au niveau du code simplement en écrivant ou en lisant à des adresses mémoires spécifiques. Un registre est généralement de la taille d’un mot du processeur, par exemple de 32 bits, et chaque bit qui le compose peut avoir une fonctionnalité différente. Les opérateurs logiques en C Les opérateurs logiques bit-à-bit. Ils sont de quatre types : ET, OU, XOR (OU exclusif), NON. La syntaxe en langage C des opérateurs logiques bit-à-bit est : Par contre, les opérateurs bit-à-bit ET, OU, XOR et NON donnent les résultats suivants : Mettre un bit à 1 Pour mettre un seul bit à 1 dans un registre, nous utilisons l’opérateur bit-à-bit OU avec un masque dont tous les bits sont à 0, sauf celui que l’on veut initialiser. Ainsi, pour une valeur de l’octet init décrite en binaire par b7 b6 b5 b4 b3 b2 b1 b0, si vous voulez passer le bit b4 à 1, vous allez composer un masque, (mask) ayant la valeur binaire b0001 0000 et appliquer l’opérateur bit-à-bit OU. En C, cela s’écrit : Exemple : mask = 0x10; // valeur hexadécimale pour 0b0001 0000 init = init | mask; // application du masque à la valeur init La dernière ligne peut aussi s’écrire plus succinctement : init |= mask; La valeur init aura pour valeur finale b7 b6 b5 1 b3 b2 b1 b0. Ainsi le bit b4 est passé à 1 sans modifier la valeur des autres bits. Passage du bit b4 à 1 Mettre plusieurs bits à 1 Vous pouvez aussi utiliser cette méthode pour mettre à 1 plusieurs bits en même temps. Reprenons l’exemple précédent avec init une variable décrite par 8 bits b7 b6 b5 b4 b3 b2 b1 b0 pour laquelle nous voulons passer les bits b4, b1 et b0 à 1. Une première solution est de faire une opération pour chaque bit. Exemple : init = init | (1 << 4); init = init | (1 << 1); init = init | (1 << 0); Une seconde solution plus efficace, est de construire un masque où les bits 0, 1 et 4 sont à 1 (b0001 0011 en binaire, 0x13 en hexadécimal, 19 en décimal), puis d’utiliser ce masque avec l’opérateur bit-à-bit OU : init = init | 0x13; // masque avec la valeur b0001 0011 On obtient de cette manière l’affectation de la valeur b7 b6 b5 1 b3 b2 11 à init. Au lieu de faire vous-même le calcul du masque complet, vous pouvez aussi combiner les masques unitaires à l’aide de l’opérateur bit-à-bit OU, soit pour le cas précédent : Exemple : init = init | ((1<<0) | (1<<1) | (1<<4)) ; Mettre des bits à 0 Pour mettre des bits à 0, nous utilisons l’opérateur bit-à-bit ET avec un masque ayant des bits à 0 uniquement devant les bits que nous voulons initialiser. Ainsi, si vous souhaitez passer à 0 les bits b4, b1 et b0 d’un octet init dont la valeur en binaire est décrite par b7 b6 b5 b4 b3 b2 b1 b0, vous utiliserez un masque binaire b1110 1100 avec l’opérateur ET, ce qui s’écrit Exemple : init = init & 0xEC; // 0xEC est la valeur hexadécimale pour b1110 1100 ce qui fixe la valeur de init à b7 b6 b5 0 b3 b2 00 : 4.3- Configurez les ports d’entrée/sortie Le GPIO Un microcontrôleur interagit avec les éléments extérieurs par le biais de plusieurs fils que l’on appelle broche. Ces broches sont regroupées généralement par paquet de 8 (octet) ou 16 (mot) pour former ce que l’on nommera par la suite des ports d’entrée/sortie (I/O ports). Du point de vue logiciel, un port est un ensemble de registres. Une broche peut être pilotée soit directement par le biais de registres dédiés (on parle alors de General Purpose Input Output, GPIO) soit indirectement par le biais d’un périphérique (on parle alors d’Alternate Function). Dans tous les cas, il sera nécessaire de configurer l’étage électronique qui permet d’interfacer le matériel et le logiciel. Une broche d’un port peut être configurée en entrée ou en sortie (le sens étant celui vu du microcontrôleur), c’est ce que l’on appelle sa direction. Les timers Principe des timers : Un timer est avant tout un compteur électronique. Il a une résolution qui dépend de son architecture et contraint l’amplitude des valeurs sur lesquelles il peut compter. Ainsi un timer avec une résolution de 8 bits pourra compter entre 0 à 255, un timer de 16 bits entre 0 à 65 535 et une timer de 32 bits de 0 à 4 294 967 295 L’incrémentation d’un timer se fait sur des événements. Ces événements sont usuellement générés par une horloge avec une fréquence fixée. Dans ce cas, le timer “compte le temps” d’où son nom. Il est cependant possible de configurer le timer pour compter des événements qui ne sont pas périodiques, par exemple un signal venant d’une broche et présentant des fronts montants et descendants. Dans ce cas, on parle alors plutôt de compteur pour désigner le timer. L’entrée d’horloge d’un timer est très souvent précédée d’un diviseur (prescaler). Son rôle est d’opérer une première division de la fréquence de l’horloge pour “ralentir” la fréquence de comptage du timer. L’utilisation classique d’un timer va consister à réagir au débordement (overflow) de son compteur. En effet, la résolution du timer étant bornée, son incrémentation va inévitablement conduire à un débordement, c’est-à-dire que l’incrément suivant dépasse la capacité du compteur. Lorsque ce débordement survient, le compteur est remis à zéro et un événement interne est généré pour signaler cette rupture dans la séquence de comptage. Afin de mieux contrôler le débordement, le compteur est associé à un registre dit autoreload. Celui-ci contient la valeur à laquelle le compteur va déborder, même s’il n’a pas atteint sa capacité maximale. Ainsi, le compteur va avoir le comportement décrit par la figure ci-dessous : Les interruptions Une interruption est un événement interne ou externe qui va de manière chronologique : 1. Arrêter le fonctionnement en cours du programme. 2. Sauvegarder le contexte d’exécution : état du programme en cours d’instruction (registres et compteur ordinal) 3. Exécuter une suite d’instruction pour servir l’interruption : routine de service d’interruption– programme spécifique à l’interruption 4. Restaurer le contexte précédent d’exécution 5. Reprendre le fonctionnement du programme Une interruption est un événement interne ou externe : Interruptions internes : exceptions Les interruptions internes sont appelées exceptions. Elles surviennent lors d’une erreur d’exécution du programme (overflow, watchdog, instruction réservée, adressage, etc.) Interruptions externes : interruptions Les interruptions externes concernent essentiellement les demandes de service des périphériques. Elles arrivent de manière asynchrone avec les instructions en cours d’exécution. Architecture du Cortex M4 Rappel: Architectures des processeurs I. Noyau Cortex-M4 I.1. Modes de traitements Le programme est exécuté avec le processeur Cortex-M4 via deux modes de fonctionnement, qui sont le mode Thread ou le mode Handler. Thread mode: Utilisé pour exécuter les applications logicielles ordinaires Le processeur est automatiquement en mode Thread à la suite d’une RAZ (Reset) Le registre de controle regarde si l’exécution du programme est effectuée en mode privilègié ou non-préviligié Handler mode: Utilisé pour traiter les exceptions Le processeur retourne au mode Thread après avoir fini le traitement d’une exception (matérielle ou logicielle) I.2. Niveaux de traitement Niveau préviligié Un programme en niveau préviligié peut utiliser toutes les instructions et accéder à toutes les ressources. Il peut changer le niveau de prévilège dans le registre de controle. Niveau non-préviligié Un programme non-préviligié a un accès limité aux instructions MSR et MRS (Move Special Registers to GP registers et inversement) Ne peut pas utiliser les instructions CPS (Change Processor State) Ne peut pas accèder à certains périphériques du noyau (system timer, NVIC, system control block) Son accès aux mémoires et aux périphériques du noyau est limité Doit utiliser l’instruction SVC (Superviser Call) pour changer le niveau de traitement I.3. Registres du noyau Les registres GP (R0...R12) sont utilisés pour stocker les variables du programmes (opérandes). Un pointeur de pile SP (R13). Un registre de lien LR (R14). Un compteur de programme PC(R14). Un registre d'état du programme PSR. Un groupe de registres pour traiter les interruptions, des registres de masque d'exception, Registre de contrôle : CONTROL register Le tableau suivant contient le type de chaque enregistreur et la validité d'accès ainsi que sa valeur après le redémarrage. I.4. Piles du noyau La pile est un endroit spécifique dans la mémoire RAM où le processeur stocke les données pour la fonction au cas où une autre fonction serait préparée jusqu'à ce qu'elle lui soit renvoyée en plus d'autres données. Le pointeur de pile (Stack pointer) indique l’adresse du dernier programme empilé. Le processeur utilise 2 types de piles (Main Stack et Process Stack). La valeur du pointeur de pile est toujours enregistré dans le registre SP I.5 Registres du noyau Registres GP - Les registres GP (R0...R12) sont utilisés pour stocker les variables du programmes (opérandes). - Gestion des nombres signés ou non à 8, 16 ou 32 bits. - Les calculs sont faits à 32 bits et la gestion des valeurs plus petites est logicielle. II- Gestion des interruptions Gestion des interruptions au niveau architecture Contrôleur NVIC – Nested Vectored Interrupt Controller Les interruptions du STM32 sont dites « vectorisées » Quand une interruption intervient, la « bonne » routine doit être fournie : Interrupt Handler Pour cela il faut déterminer l’adresse du programme correspondant à cette routine Cette information est stockée dans une table des vecteurs d’interruption Par défaut cette table est stockée à l’adresse 0 Cette table est relogeable via le registre VTOR (Vector Table Offset Register), c’est à dire qui peut être mis en mémoire à un autre endroit) La table est organisée en mots de 4 octets (32 bits) L’adresse du vecteur d’une interruption est calculée en multipliant par 4 son numéro. Table des vecteurs d’interruption Registre Vector Table Offset – VTO Traitement d’une interruption par le Cortex M4 comporte trois phases : Phase 1 : Sauvegarde du contexte du programme Phase 2 : Chargement de la routine d’interruption – Handler Interrupt Phase 3 : Mise à jour du pointeur de pile SP (Stack Pointeur), du registre de lien LR (Link Register) et du compteur ordinal PC (compteur de programme) Phase 1 : Sauvegarde du contexte du programme Registrement des registres xPSR, PC, LR, R12, R3-R0 Sauvegarde de CPSR dans SPSR Sauvegarde de PC dans LR Phase 2 : Chargement de la routine d’interruption – Handler Interrupt Changement du mode du processeur PC = adresse du service d’interruption Exécution du code utilisateur Phase 3 : Mise à jour du pointeur de pile SP (Stack Pointeur), du registre de lien LR (Link Register) et du compteur ordinal PC (compteur de programme) Dépilement des registres après le service de l’interruption Restauration du contexte du programme avant l’interruption (xPSR, PC, LR, R12, R3-R0) Restauration de SPSR dans CPSR Restauration de PC à partir de LR