Vous êtes sur la page 1sur 18

CHAPITRE 7 

: EXCEPTIONS et INTERRUPTIONS.

Ce sont des mécanismes fournis par la majorité des architectures embarquées à base de processeur.
Elles permettent de détourner le chemin d’exécution normal du processeur. Ce détournement peut etre
déclenché soit :

 De manière intentionnelle par l’application software ou par une erreur.


 Par des conditions non usuelles.
 Par des évènements externes non planifiés.
Beaucoup de RTOS fournissent des fonctions (appelant d’autres fonctions ou wrapper functions) pour
prendre en compte les exceptions et interruptions afin de réaliser, pour le développeur, une abstraction
par rapport aux détails de bas niveau. Ces wrapper functions sont un avantage pour le développeur de
l’application, en tant qu’abstraction, mais peuvent devenir problématique lorsque le développeur de
l’application doit devenir un développeur du système. 

1. Définitions des exceptions (Exceptions) et interruptions (Interrupts).


Une exception est un événement qui détourne l’exécution normale d’un processeur et force le
processeur à exécuter des instructions en mode privilégié. Les exceptions peuvent être classées en
deux catégories (les exceptions synchrones et les exceptions asynchrones).
Les exceptions levées par des évènements internes, comme des évènements générés par
l’exécution d’instructions processeurs, sont dites exceptions synchrones (synchronous
exceptions). Des exemples d’exceptions synchrones sont les suivants :

 Sur certaines architectures processeurs, les opérations de lectures et d’écritures doivent


commencer à une adresse paire pour certaines tailles de données. Les opérations de lectures et
d’écritures qui débutent à une adresse impaire provoquent un événement d’erreur d’accès
mémoire et lèvent une exception (alignment execption).
 Une opération arithmétique qui résulte par une division par 0 lève une exception.
Les exceptions levées par des évènements externes, qui sont des évènements non liés
l’exécution d’instructions processeurs, sont dites exceptions asynchrones (asynchronous
exeptions). En général, ces évènements externes sont associés à des signaux hardware. Les sources de
ces signaux hardware sont typiquement des signaux issus de dispositifs hardware externes. Des
exemples d’exceptions asynchrones sont les suivants :

 L’appuie sur un bouton de reset d’une carte déclenche une exception asynchrone (system
reset exception).
 La réception de données depuis un élément externe communicant.

 Une interruption, parfois appelée interruption externe (external interrupt), est une exception
asynchrone déclenchée par un événement produit par un dispositif hardware. Les interruptions
sont une classe d’exception. Ce qui différencie les interruptions des exceptions, plus précisément
ce qui différencie les exceptions synchrones des exceptions asynchrones, est la source de
l’événement. La source de l’événement pour une exception synchrone est générée de façon
interne par le processeur en raison de l’exécution d’une instruction. La source de l’événement pour
une exception asynchrone est générée par un dispositif hardware externe.

1
Dans la suite du texte, comme dans de nombreux ouvrages, on utilisera le terme exceptions pour les
exceptions synchrones, et interruptions pour les exceptions asynchrones.
Le terme general exceptions englobe les exceptions et interruptions.
Le terme interrupts et external interrupts sont identiques.

2. Applications des exceptions et interruptions.


Au niveau de l’application, les exceptions et interruptions fournissent des possibilités au hardware
embarqué d’obtenir l’attention du code d’application. On trouve principalement trois types
d’applications, présentées à la suite.

2.1. Management des erreurs internes et conditions spéciales.


Gérer des erreurs sans arrêter complétement le système est souvent une nécessité dans les
systèmes embarqués. Les exceptions sont soit des conditions d’erreurs ou des conditions spéciales
que le processeur détecte lorsqu’il exécute des instructions.

 Les conditions d’erreurs peuvent apparaitre pour de nombreuses raisons. Le système


embarqué peut implanter un algorithme de calcul. Si certaines conditions non anticipées
génèrent une division par 0, un overflow, ou d’autres erreurs mathématiques, l’application
doit en être informée. Dans ce cas, l’exécution de la tache réalisant le calcul s’arrête, et
une routine d’exception spéciale débute. Elle offre à l’application l’opportunité d’évaluer
et de prendre en compte cette erreur. D’autres types d’erreurs sont les lectures et écritures
mémoires, ou des tentatives d’utiliser des opérations en virgule flottante lorsqu’elles ne
sont pas installées.

De nombreuses architectures processeurs ont deux modes d’exécutions : le mode normal et le


mode privilégié. Certaines instructions, appelées instructions privilégiées, sont autorisées à
s’exécuter uniquement si le processeur est en mode privilégié. Une exception est levée
lorsqu’une instruction privilégiée est émise alors que le processeur est en mode d’exécution
normal.

 Les conditions spéciales sont des exceptions qui sont générées par des instructions
spéciales (comme l’instruction TRAP sur les processeurs de la famille Motorola 68K).
Ces instructions permettent au programme de forcer le processeur à passer dans le mode
d’exécution privilégié, ce qui lui permet d’avoir accès au jeu d’instructions privilégié. Par
exemple, les instructions utilisées pour invalider les interruptions externes doivent être
réalisées en mode privilégié.

2.2. Gestion de la concurrence hardware et des requêtes de services.


Dans les systèmes embarqués, il est important de réaliser différents types de travaux
simultanément. De nombreux dispositifs hardware externes peuvent effectuer des opérations en
parallèle du processeur principal (core processor). Ces dispositifs nécessitent un minimum
d’intervention de la part du processeur principal.

2
La solution pour le problème de la concurrence est d’utiliser les interruptions externes.Par
exemple, une application embarquée fonctionnant sur un processeur principal (core processor)
émet une commande à un dispositif, lui demandant de faire un travail. L’application embarquée
continue son exécution, réalisant d’autres fonctions pendant que le dispositif essaye de terminé le
travail demandé. Dès que son travail est terminé, le dispositif déclenche une interruption externe
vers le processeur principal (core processor), ce qui indique que le dispositif est maintenant prêt à
accepter de nouvelles commandes.
Une autre utilisation des interruptions externes est de fournir un mécanisme de communication,
pour signaler ou alerter un processeur embarqué de l’arrivée d’un événement externe nécessitant
un service (par exemple, arrivée d’un paquet de données d’un bus de communication, expiration
d’un timer hardware,…).

3. Approfondissement des notions d’interruptions et d’exceptions.


Les exceptions au sens général (c.à.d. exception + interruptions) ont des classifications, et
possèdent des priorités basées sur ces classifications. Il est possible qu’il existe un autre niveau de
priorité, imposé par une interruption hardware, parmi les interruptions externes. Comprendre les
sources hardware qui déclenchent les exceptions au sen général, le hardware qui implémente le
transfert du contrôle, et les mécanismes, pour déterminer l’endroit où résident les vecteurs de
contrôle sont critiques pour installer et écrire correctement des routines d’exceptions.

3.1. Contrôleurs d’interruptions programmable (Programmable Interrupt Controllers ou PIC) et


interruptions externes.
La majorité des systèmes embarqués ont plusieurs sources d’interruptions externes, et ces sources
possèdent des priorités. Pour comprendre cette notion, prenons le cas du PIC.
Le PIC peut avoir diverses implémentations et posséder plusieurs noms. Mais son rôle est le même
et il fournit deux fonctions principales :

 Donner des priorités à de multiples sources d’interruptions de telle sorte qu’à n’importe
quel instant la plus haute priorité est présentée au cœur CPU pour le traitement.
 Décharger le cœur CPU du traitement qui consiste à déterminer la source exacte de
l’interruption.
Le PIC possède un ensemble de lignes de requêtes d’interruptions. Une source externe génère une
interruption en émettant un signal physique sur une ligne de requête d’interruption. Chaque ligne
de requête d’interruption a une priorité qui lui est assignée.

La figure de la page suivante illustre un PIC avec 4 sources d’interruptions. Chaque source
d’interruption est connectée à une ligne de requête d’interruption : un capteur airbag, un capteur de
frein, un capteur de niveau d’essence, et une RTC ( Real Time Clock ou Horloge temps réel ou
HTR).

3
La figure suivante est une table d’interruptions associée à notre exemple (interruption table).
Elle liste toutes les interruptions disponibles du système embarqué.

Comprendre les priorités des sources d’interruptions permet au programmeur de mieux appréhender le
concept d’interruptions imbriquées (nested interrupts). Ce terme recouvre la possibilité d’une
interruption de priorité supérieure de préempter le traitement d’une interruption de priorité inférieure.
Il est facile de voir comment une source d’interruption de faible priorité est affectée par une
interruption de plus haute priorité, et leurs temps d’exécutions et fréquences si la table est ordonnée
selon les priorités. Cette information aide le programmeur à concevoir et implémenter de meilleures
ISR qui permettent des interruptions imbriquées (nested interrupts).
La colonne de la fréquence maximale de la table d’interruptions spécifie la contrainte du temps de
traitement placée sur toutes les ISR qui ont le plus faible impact sur le système.
La colonne vector adress de la table d’interruptions spécifie l’endroit mémoire où l’ISR doit être
installée (elle dépend du processeur). Le processeur va automatiquement chercher l’instruction à partir
de l’une de ces adresses mémoire basée sur un numéro d’interruption, qui est spécifié dans la colonne
IRQ. Ces instructions commencent la routine spécifique à chaque interruption.

4
3.2. Classifications des exceptions générales.
La majorité des processeurs classent les exceptions de la manière suivante :

 Asynchrones – non maskables (Asynchronous Non Maskable).


 Asynchrones – maskables (Asynchronous Maskable).
 Synchrones– precise (Synchronous Precise).
 Synchrones – imprécises (synchronous Imprecise).

Les exceptions asynchrones sont classées en exceptions masquable et non masquables. Les
interruptions externes sont des exceptions non masquables. Les exceptions asynchrones qui sont
bloquées ou validées par software sont dites masquables. De manière identique, les exceptions
asynchrones qui ne peuvent pas être bloquées par software sont dites non masquables.
Les exceptions non masquables sont toujours reconnues par le processeur et traitées immédiatement.
L’exception hardware reset est non masquable. De nombreux processeurs possèdent une ligne de
requete d’interruption non masquable (broche NMI, Non Maskable Interrupt). Un dispositif connecté à
cette broche NMI peut générer une interruption non masquable.

Les exceptions synchrones sont classées en exceptions précises et imprécises. Avec une exception
précise, le compteur programme du processeur pointe l’instruction exacte (offending instruction) qui
a provoqué l’exception, et le processeur sait alors à partir de quel endroit reprendre l’exécution
après la fin du traitement de la routine associée à l’exception.
Dans les architectures modernes qui implémentent le pipeline pour les données et les instructions, les
exceptions sont levées dans l’ordre d’écriture des instructions, et pas dans l’ordre d’exécution des
instructions. En particulier, les architecturent assurent que les instructions qui suivent l’offending
instruction et qui ont débuté leur exécution dans le pipeline durant l’exception n’affectent pas l’état de
la CPU. Il devient impossible de déterminer l’instruction exacte qui a provoqué l’exception. On
parle d’exception imprécise, le compteur programme est incapable de pointer sur l’offending
instruction.

3.3. Les priorités des exceptions générales.


Tous les processeurs gèrent les exceptions dans un ordre prédéfini. Malgré la possibilité d’observer
certaines variations, l’ordre communément établi est le suivant.

Les priorités les plus élevées sont réservées aux reset de systèmes ou aux autres évènements ou erreurs
qui imposent un reset complet du système.
Les deux autres niveaux de priorités intermédiaires concernent l’ensemble des erreurs et des
conditions spéciales d’exécutions internes au processeur. Une exception synchro.ne est générée et
acquittée seulement pour certains états internes du processeur.

5
Le niveau de priorité le plus bas est celui des exceptions asynchrones externes au cœur du processeur.
Vu de l’application, toutes les exceptions ont une priorité supérieure à celle des objets du RTOS, c’est-
à-dire taches, FAM, sémaphores, …Cela est précisé dans la figure suivante.

4. Traitement des exceptions général.


Le mécanisme de prise en compte des exceptions est identique à celui des interruptions. D’une
manière simplifiée, le processeur réalise les actions lorsqu’une exception (au sens général) est
levée :

 Sauve les informations relatives à l’état courant du processeur.


 Charge l’adresse de la routine dans le compteur programme.
 Transfère le contrôle à la routine (handler function) et commence son exécution.
 Rétablit l’état du processeur après la fin de l’exécution de la routine.
 Retourne depuis la routine et reprend l’exécution d’avant l’exception.

Typiquement, une routine réalise les actions suivantes :

 Commute vers la pile d’interruption.


 Sauve les informations relatives à l’état courant du processeur.
 Masque le niveau de l’interruption courante mais autorise les niveaux d’interruption de
priorité supérieure.
 Réalise un minimum de travail.

6
4.1. Installation des routines d’exceptions (execption handlers).
Les ESR (exception service routine) et les ISR (interrupt service routine) doivent être installées
dans le système avant que les exceptions et interruptions puissent être gérées. Cela nécessite la
connaissance d’une table d’exception et d’interruption (general execption table). Nous avons déjà
rencontré ce type de table, rappelée ci-dessous.

Dans cette table, que l’on appelle aussi la table des vecteurs (vector table), chaque ligne de la colonne
vector adresses pointe vers le début d’une ESR ou ISR. L’installation d’une ESR ou ISR nécessite de
remplacer l’entrée appropriée de la table des vecteurs par l’adresse de l’ESR ou ISR.
Le code de démarrage (startup code) du système embarqué installe les ESR au moment de
l’initialisation. Les drivers des dispositifs hardware installent typiquement les ISR au moment de
l’initialisation des drivers.
Si une exception ou bien une interruption apparait alors qu’aucune routine associée n’est installée, le
système souffre d’un dysfonctionnement et peut s’arrêter. Pour éviter ce problème, de nombreux
RTOS embarqués possède une routine par défaut (default handler function) installée dans la table des
vecteurs pour chaque ISR et ESR possibles du système. La routine par défaut (default handler
function) réalise une petite quantité de travail pour assurer une réception propre et un retour propre de
l’exception). De nombreux RTOS fournissent un mécanisme qui permet au programmeur la possibilité
de réécrire la routine par défaut (default handler function) à son gout, ou d’insérer un traitement
supplémentaire à la suite de la routine par défaut (default handler function). Cela permet au
programmeur de coder des actions spécifiques avant et après les actions par défaut.
Dans ce cours, le terme routine de service (service routine) signifie indifféremment ESR et ISR.

4.2. Sauvegarde des états du processeur.


Lors de l’apparition d’une exception ou interruption, juste avant d’invoquer la routine de service, le
processeur doit réaliser un ensemble d’opération pour assurer un retour correct au programme en
exécution après que la routine de service soit terminée. Les routines de services d’exceptions et
d’interruptions ont besoin de sauvegarder des blocs d’informations, appelés informations d’état du
processeur (processor state information), quelque part en mémoire.
Le processeur sauve un minimum d’informations concernant son état, comme :

 Le registre d’état (status register ou SR) qui contient les bits d’état courants du processeur.
 Le compteur programme (program counter ou PC) qui contient l’adresse de retour, c’est-à-
dire l’adresse à exécuter après la fin de la routine de service.
 D’autres registres pour permettre une reprise correcte du programme préémpté, cela sera
détaillé plus loin dans ce chapitre.

7
Définition : Les piles (stacks) sont utilisées pour le stockage des informations de l’état du
processeur. Dans un environnement avec OS embarqué, la pile est composée d’un bloc mémoire
réservé statiquement et d’un pointeur dynamique, dit pointeur de pile (stack pointer).

Lorsque des données sont sauvées dans la pile, le pointeur de pile est incrémenté pour refléter le
nombre d’octets recopiés dans la pile. Ce procédé est souvent appelé empiler (pushing) des valeurs
dans la pile.
Lorsque des données sont recopiées depuis la pile, le pointeur de pile est décrémenté pour refléter le
nombre d’octets recopiés depuis la pile. Ce procédé est souvent appelé dépiler (popping) des
valeurs dans la pile. Le pointeur de pile pointe toujours vers le premier endroit susceptible
d’enregistrer une donnée dans la pile. Dans notre cours, on suppose que la pile grandit vers le haut
(dans certains autres processeurs, elle peut grandir vers le bas). Notez qu’une pile typique ne stocke
pas d’intensificateurs pour les contenus. Les utilisateurs devront utiliser l’opération d’empilage
(push) et de dépilage (pop) de la pile de manière symétrique. Si cette règle n’est pas
scrupuleusement respectée durant les traitements d’ESR et d’ISR, des résultats inattendus seront
possibles.

Dans ce cours, nous avons précisé que dans les RTOS embarqués, tous les objets taches possèdent un
bloc de contrôle de tache (ou TCB). Durant la création d’une tache, un bloc de mémoire est réservé en
tant que pile pour l’usage de la tâche, comme indiqué à la figure suivante.

8
Les langages de programmation de haut niveau (comme le C et le C++), utilise l’espace de la pile pour
passer les variables entre les fonctions et les objets du langage.
Le pointeur de pile actif (active SP) est réinitialisé vers le SP de la tache active lors de chaque
apparition de changement de contexte. C’est le noyau qui réalise cette opération en arrière-plan.
Comme indiqué précédemment, le processeur utilise n’importe quelle pile vers laquelle le SP pointe
pour stocker son état d’information minimal avant d’invoquer la routine d’interruption.
Bien que des disparités dans l’implémentation des ISR et ESR entre systèmes existent, l’idée générale
pour déterminer et réserver de l’espace mémoire pour la pile lors des interruptions est la même. Dans
de nombreux cas, lorsque des exceptions générales apparaissent et qu’une tache est en exécution, la
pile de la tâche est utilisée pour gérer l’exception ou l’interruption. Si une ESR ou ISR de plus
faible priorité est en exécution au moment de l’arrivée d’une nouvelle exception ou interruption, la
pile utilisée par l’ESR ou l’ISR de plus faible priorité est aussi la pile utilisée par la nouvelle exception
ou interruption. Cette approche peut devenir problématique dans le cas d’exceptions ou interruptions
imbriquées.
4.3. Chargement et appel des routines d’exceptions (execption handlers).
Comme indiqué plus tôt, certaines différences existent entre le travail réalisé en amont par le
processeur pour les ESR et ISR. Cela est dû au fait qu’une interruption externe est seul type
d’exception qui peut être invalidée par software. Dans beaucoup d’architecture à processeur
embarquée, les interruptions externes peuvent être validées ou invalidées à travers un registre de
contrôle du processeur. Ce registre de contrôle contrôle directement les opérations du PIC et détermine
quelles interruptions le PIC lève dans le processeur. Le PIC filtre les interruptions selon la
configuration du registre de contrôle et détermine l’action nécessaire. Dans la suite de ce cours, on
suppose ce modèle d’architecture comme la référence.
Formellement, une interruption peut être :

 Invalidée (disabled).
 Active (active).
 En attente (pending).
Une interruption invalidée (disabled) est aussi appelée interruption masquée (masked interrupt). Le
PIC les ignore.
Une interruption en attente (pending) est une interruption qui n’est pas acquittée, elle apparait alors
que le processeur est en train de traiter une interruption de priorité supérieure. L’interruption en attente
(pending) est acquittée et traitée après que toutes les interruptions de priorités supérieures qui étaient
aussi dans l’état pending aient été traitées.
Une interruption active est une interruption qui est en train d’être acquittée et traitée par le processeur.
Pour les exceptions synchrones, le processeur détermine d’abord la première exception apparue puis
calcule l’index correct dans la table des vecteurs pour retourner l’ESR. Ce calcule dépend de
l’implémentation.
Dans le cas d’une exception asynchrone, une étape supplémentaire est nécessaire. Le PIC doit
déterminer si l’interruption a été invalidée ou masquée (disabled). Si c’est le cas, le PIC ignore
l’interruption et l’état du processeur est inchangé. Si l’interruption n’est pas masquée, le PIC lève
l’interruption dans le processeur et le processeur calcule l’adresse du vecteur puis charge cette adresse
afin d’exécuter la routine de service.

9
La figure suivante présente ces situations.

Certains vendeurs implémentent des tables de correspondance sous forme hardware, d’autres sous
forme software. Mais le mécanisme de fonctionnement reste le même. Lorsqu’une exception
apparait, la valeur de l’index est calculé depuis la table. Le contenu de la table à cet index ou
offset est l’adresse de la routine de service. Le conteur programme est initialisé avec cette adresse
(vector adress) et l’exécution commence à cette adresse.

4.4. Exceptions imbriquées (nested) et dépassement de la pile (stack overflow).


Les exceptions imbriquées (nested execptions) concernent la capacité d’exceptions de plus haute
priorité de préempter le traitement d’exceptions de plus faible priorités. Un peu comme la
commutation des taches lorsqu’une tache de priorité supérieure devient prête, l’exception de plus
faible priorité est préemptée, ce qui permet à l’ESR de plus haute priorité de s’exécuter. Lorsque
la routine de service de l’interruption de plus haute priorité est terminée, l’exécution retourne à la
routine de priorité inférieure qui était en exécution.
La figure suivante illustre ce fonctionnement.

10
Sur cette précédente figure, une tache s’exécute. A un moment, une interruption de faible priorité
devient active, et la routine de service associée commence à s’exécuter. Alors que cette routine
s’exécute, une priorité de niveau supérieure devient active, la routine de priorité inférieure devient
préemptée. La routine de priorité supérieur s’exécute jusqu’à son terme, puis le contrôle retourne à
la routine de faible priorité. Avant que la routine de faible priorité puisse prendre fin, une autre
interruption devient active. Comme précédemment, la routine de faible priorité est préemptée
pour permettre à la routine de priorité moyenne de s’exécuter complétement. Une fois de plus,
avant que la routine de faible priorité puisse se terminer, une autre priorité de niveau supérieure
devient active et s’exécute jusqu’à son terme. La routine de faible priorité est alors capable de
s’exécuter jusqu’à son terme. A ce moment, la tâche qui était interrompue précédemment peut
reprendre son exécution.
Lorsque les interruptions sont emboitées, la pile (stack) de l’application doit être assez large pour
s’accommoder au maximum d’appels successifs des fonctions imbriquées de l’application, au
maximum d’exceptions et d’interruptions imbriquées possibles, si l’application s’exécute avec
toutes les interruptions autorisées (enabled). Ce problème est fréquemment observé dans les
interruptions imbriquées.
En reprenant l’exemple précédent, N taches ont été créées, chacune avec son propre TCB et sa pile
allouée statiquement. Supposons que la pile de la tâche en exécution est utilisée pour les
exceptions, un scénario simple utilisant la figure suivante peut être :

1. La tache 2 est en exécution.


2. Une interruption de faible priorité apparait.
3. La tache 2 est préemptée alors que le traitement de la priorité de faible interruption débute.
4. La pile grandit pour gérer l’espace mémoire nécessaire au traitement de l’interruption.
5. Une interruption de priorité moyenne est reçue avant que le traitement de l’exception
précédente soit terminé.
6. La pile grossit encore pour gérer l’espace mémoire nécessaire au traitement de
l’interruption de priorité moyenne.
7. Une interruption de priorité élevée est reçue avant que le traitement de l’exception de
priorité moyenne soit terminé.
8. La pile grossit encore pour gérer l’espace mémoire nécessaire au traitement de
l’interruption de priorité élevée.
Dans chaque cas de traitement des exceptions, la taille de la pile grossit. Notez qu’en absence de
MMU (Memory Management Unit), aucune vérification de limite n’est réalisée lors de
l’utilisation d’une pile comme espace de stockage. Comme décrit dans cet exemple, la somme des

11
espaces nécessaires (application stack space + execption stack space) est inférieure à la taille de
la pile allouée à la tache 2. En conséquence, lorsque des données sont copiées dans la pile
dépassent les limites définies statiquement, le TCB de la tache 3 devient corrompu, c’est ce qu’on
appelle le stack overflow.
Malheureusement, le TCB corrompu n’est pas indiqué jusqu’à ce que la tache 3 passe en état
d’exécution. Ce type d’erreurs peut être très difficile à détecter. Ces erreurs sont fonctions de la
combinaison des taches en exécution et de leurs fréquences, ainsi que des séquences
d’interruptions. Cette situation donne l’impression à l’utilisateur ou au développeur d’avoir un
système qui fonctionne de manière sporadique.
Deux solutions à ce problème sont possibles :

 augmenter la pile de l’application pour s’accommoder à toutes les possibilités et les


niveaux les plus profonds d’exceptions ou d’interruptions imbriquées
 avoir une ESR ou ISR qui commute vers sa propre pile d’exception, appelée exception
frame.
La taille maximale d’une pile pour exception est fonction du nombre d’exceptions, du nombre de
dispositifs externes connecté à chacune ligne d’IRQ distincte, et aux niveaux de priorités
supportés par le PIC. La solution simple est d’avoir une application qui alloue assez d’espace pour
la pile pour prendre en compte le cas le plus défavorable, qui est celui dans lequel la routine
d’exception de plus faible priorité est préemptée par toutes les exceptions ou interruptions de
niveau de priorité plus élevé. Une meilleure approche est d’utiliser une exception frame à
l’intérieur de l’ESR ou l’ISR. Cette approche nécessite une mémoire totale bien moins importante
que celle qui consiste à augmenter considérablement la taille de la pile pour chaque tâche.

4.5. Gestionnaires d’exceptions (execption handler).


Après que le contrôle soit transféré au gestionnaire d’exception, l’ESR ou l’ISR réalise un
traitement associé à l’exception. Habituellement, l’exception comporte deux parties :

 Une première qui s’exécute dans un contexte de l’interruption ou de l’exception.


 Une seconde partie qui s’exécute dans le contexte de la tâche.
Une execption frame est une pile d’interruption dans le contexte d’exception asynchrone. 
Deux raisons existent pour la nécessité de l’execption frame :

 Une raison est la gestion des exceptions imbriquées (nested).


 L’autre raison est que, les architectures embarquées devenant de plus en plus complexes, les
ESR et ISR augmentent en termes de complexité. Fréquemment, les exceptions sont écrites à
la fois en langage machine et en langage de haut niveau, comme du C et C++. Comme
indiqué précédemment, la partie de l’ESR ou ISR rédigée en C ou C++ nécessite une pile à
laquelle on passe les paramètres des fonctions durant leur appel. Cela est également vrai si
l’ESR ou l’ISR invoque une fonction d’une bibliothèque écrite en langage de haut niveau.

L’approche commune pour les execption frame est que les ESR ou ISR alloue un block mémoire, soit
statiquement, soit dynamiquement, avant de s’installer dans le système. Le gestionnaire d’exception
(execption handler) sauve alors le pointeur de pile dans une zone mémoire temporaire, réinitialise le
pointeur de pile de cette pile privée (private stack), puis commence le traitement. Cela est décrit à la
figure suivante.  

12
Le gestionnaire d’exception (execption handler) peut réaliser d’autres actions, comme
enregistrer des informations supplémentaires sur l’état du processeur, dans sa pile.

Différences entre ESR et ISR.


Une différence entre les ESR et ISR est le type d’informations sauvées sur l’état du
processeur. Les trois manières de masquer une interruption sont :

 Invalider (disable) le dispositif de telle sorte qu’il ne puisse plus délivrer


d’interruptions additionnelles. Les interruptions de tous niveaux peuvent encore
apparaitre.
 Masquer les interruptions de niveau de priorité égal ou inférieur, tout en permettant à
celle de niveau supérieure d’apparaitre. Le dispositif continue de générer des
interruptions, mais le processeur les ignore.
 Invalider (disable) le système complet de lignes de requête d’interruptions vers le
processeur (les lignes entre le PIC et le cœur du processeur comme indiqué figure
suivante). Les interruptions, quel que soit leur priorité, n’atteignent plus le
processeur. Cela est équivalent à masquer les interruptions de plus haute priorité.

13
Une ISR va typiquement utiliser une de ces trois méthodes pour invalider (disable) les
interruptions pour une ou toutes les raisons suivantes :

 L’ISR tente de réduire le nombre total d’interruptions levées par le dispositif.


 L’ISR est non réentrante.
 L’ISR a besoin de réaliser certaines opérations atomiques.
Certaines architectures processeurs conservent l’information sur les interruptions ou niveaux
d’interruptions invalidées (disable) dans le registre d’état du système. D’autres architectures
utilisent un registre de masque d’interruption (interrupt mask register ou IMR). En
conséquence, une ISR a besoin de sauver l’IMR courant dans la pile et invalider des
interruptions en fonction de ses besoins en créant un nouveau masque à enregistrer dans
l’IMR. L’IMR s’applique uniquement aux exceptions asynchrones masquables, et par
conséquent, n’est pas sauvé par les routines d’exceptions synchrones.
Une autre différence entre l’ESR et l’ISR est que le gestionnaire d’exception (exception
handler), dans de nombreux cas, ne peux empêcher d’autres exceptions d’apparaitre, alors que
l’ISR peut empêcher les interruptions de même priorité ou de priorité inférieure d’apparaitre.

Les Timing des Execeptions.


Très souvent, il est demandé aux ESR et ISR d’être très courte. Mais que cela signifie-t-il
concrètement ? Pour répondre à cette question, focalisons-nous sur les interruptions externes
et ISR.
C’est le rôle du concepteur hardware d’utiliser les bonnes priorités d’interruption au niveau du
PIC, mais c’est la responsabilité du programmeur de l’ISR de connaitre les besoins temporels
de chaque dispositif lorsqu’une ISR s’exécute avec le même niveau ou toutes les interruptions
invalidées.
Le programmeur du système embarqué, lorsqu’il conçoit et implémente une ISR, doit être
informé de la fréquence des interruptions de chaque dispositif susceptible d’en générer. La
table suivante comporte une colonne appelée Maximum Frequency, qui indique la fréquence
à laquelle un dispositif peut générer une interruption lorsque le dispositif fonctionne à sa
capacité maximale. La durée permise pour l’exécution d’une ISR avec les interruptions
invalidées (disable) peut être déduite de la table suivante.

Sans entrer dans les détails, une ISR, quand elle s’exécute avec les interruptions invalidées
(disable), peut permettre au système de manquer des interruptions (interrupt miss) si l’ISR est
trop longue. Dans cette situation, les interruptions sont levées mais le processeur ne peut
enregistrer leurs occurrences car il est occupé. L’ISR n’est donc pas appelée pour ces
occurrences manquées. Ce problème est souvent présent pour des dispositifs qui utilisent des
mécanismes de déclenchement sur front (edge triggering). Ce point sera abordé plus loin dans
ce polycopié.

14
L’ordonnanceur du noyau RTOS ne peut pas fonctionner lorsqu’une ISR invalide (disable)
toutes les interruptions du système lors de son fonctionnement. Comme indiqué
précédemment, le traitement des interruptions a une priorité supérieure que celui des taches.
Donc, les taches temps réel qui ont des deadlines strictes peuvent aussi être affectées par une
ISR mal conçue.
La figure suivante illustre un nombre de concepts liés à une interruption unique.

La valeur T A est basée sur la fréquence d’interruption du dispositif.

La latence de l’interruption, T B , est l’intervalle de temps entre l’instant où l’interruption est


levée et l’instant où l’ISR commence à s’exécuter. La latence de l’interruption est attribuée est
à :

 La durée prise par le processeur pour acquitter l’interruption et réaliser le travail initial
de sauvegarde.
 La présence à ce moment d’une interruption de priorité supérieure.
 L’interruption est invalidée puis plus tard revalidée par software.
Le premier cas contribue toujours à la latence de l’interruption. Comme on peut le voir, la
latence de l’interruption peut être non bornée, donc le temps de réponse également. La latence
de l’interruption est hors de contrôle de l’ISR. Le temps de traitement T C, en revanche, est
déterminé par la manière dont est implémentée l’ISR.

Le temps de réponse de l’interruption est T D =T B +T C.

Il est possible que le traitement complet soit réalisé dans le contexte de l’interruption, c’est-à-
dire avec les interruptions invalidées. Notez que le temps de traitement d’une interruption
d’une plus haute priorité est une source de latence d’interruption pour l’interruption de plus
basse priorité.
Une autre approche est d’avoir une partie de l’ISR s’exécutant dans le contexte de
l’interruption et une autre partie s’exécutant dans le contexte d’une tache. La première partie
du code de l’ISR sert le dispositif de manière que la requête de service soit acquittée et que le
dispositif soit placé dans un état opérationnel connu de telle sorte qu’il puisse rependre son
opération. Cette portion de l’ISR prépare la requête de service du dispositif puis l’envoie au

15
reste de la section de l’ISR qui l’exécute dans le contexte d’une tache. Cette dernière partie de
l’ISR est typiquement implantée comme une tache daemon (daemon task) dédiée.
Il existe deux raisons principales de partitionner l’ISR en deux pièces :

 La première est de réduire le temps de traitement dans le contexte de l’interruption.


 La seconde, plus complexe, est que l’architecture traite une interruption
prioritairement à une tache, mais en pratique, ce n’est pas toujours le cas. Par
exemple, si le dispositif qui contrôle le clignotement de LED rapporte une
défaillance, il devient définitivement de plus faible priorité qu’une tache qui doit
envoyer une réponse pour maintenir une communication avec son homologue. Si
l’ISR, pour cette interruption particulière, est partitionnée en deux sections, la tache
daemon qui continue le traitement de l’interruption des LED peut avoir une plus
faible priorité que les autres taches. Cela permet aux autres taches de plus autres
priorité de terminer leur travail avec un impact limité. La figure suivante illustre ce
concept.

Les avantages de ce concept sont les suivants :

 Les interruptions de plus faibles priorités peuvent être gérées avec moins de priorité
que les taches critiques s’exécutant sur le système.
 Cette approche réduit les chances de rater des interruptions.
 Cette approche permet plus de concurrence car les dispositifs sont servis de manière
minimale, de telle sorte qu’ils peuvent continuer à fonctionner alors que leurs
précédentes requêtes sont accumulées sans pertes.

D’un autre côté, le temps de réponse de l’interruption augmente.

Il devient T D =T B +T C + T E +T F . Cette augmentation est attribuée au délai


d’ordonnancement, et la tache daemon qui peut obtenir une priorité supplémentaire.

16
Le délai d’ordonnancement apparait lorsque d’autres taches de plus haute priorité sont en
exécution po sont ordonnancées pour être exécutées. Ce délai d’ordonnancement inclue
également le temps nécessaire au changement de contexte après que la tache daemon soit
déplacée de la file Ready vers la file en exécution.

En conclusion, la durée d’exécution d’une ISR dans le contexte d’une interruption dépend du
nombre d’interruptions et de la fréquence de chaque source d’interruption existant dans le
système. Bien qu’une approche générale pour concevoir une interruption existe, aucune
solution unique n’existe pour implanter une ISR qui fonctionnera pour tous les systèmes
embarqués. Le développeur devra, pour concevoir son l’ISR, prendre en compte les
considérations présentées dans ce cours.

Recommandations générales.
Dans les architectures où les interruptions imbriquées (nested) sont permises :

 Une ISR doit invalider (disable) les interruptions de même niveau si l’ISR est non
réentrante.
 Une ISR doit masquer toutes les interruptions si elle a besoin d’exécuter une séquence
de code de façon atomique.
 Une ISR doit éviter d’appeler des fonctions non réentrantes. Certaines fonctions de
bibliothèque standard sont non réentrantes, comme beaucoup d’implémentation de
malloc et printf. Comme une interruption peut apparaitre au milieu de l’exécution
d’une tache, et parce qu’une tache peut être au milieu d’un appel de fonction malloc,
le résultat peut être catastrophique si l’ISR appelle cette même fonction réentrante.
 Une ISR ne doit jamais faire un appel bloquant ou suspensif (suspend). Cela peut
entrainer l’arrêt complet du système.
Si l’ISR est partitionnée en deux sections avec une section daemon task, la daemon task n’a
pas une priorité élevée par défaut. La priorité doit être fixée en respectant le reste du système.

5 . Nature des interruptions brèves ou parasites (spurious).


Une interruption est dite spurious si un signal de très courte durée apparait sur une ligne
d’interruption. Ce signal peut être provoqué par un glitch.
Un dispositif externe utilise un mécanisme déclencheur pour lever des interruptions dans le
cœur du processeur. Deux types de mécanismes déclencheurs existent : déclenchement sur
niveau et déclenchement sur front.
La figure suivante illustre les déclenchements sur front montant (rising edge) et descendant
(falling edge). Ce type de déclenchement est typiquement utilisé avec des signaux
numériques.

17
Au contraire, les déclenchements sur niveau (level) sont utilisés avec des signaux analogiques.
La figure suivante en donne un exemple. Il est important de noter que dans ce type de
déclenchement, le PIC ou le microcontrôleur doit définir une valeur de ce seuil de
déclenchement.

Comment les interruptions parasites (spurious) apparaissent ?


Dans le monde réel, les signaux analogiques et numériques ne sont pas aussi propres que
décrit précédemment. Les environnements, les types de capteurs, les méthodes de câblages ont
des conséquences sur la propreté des signaux générés. De nombreux signaux ont alors besoin
d’être filtrés. La figure suivante illustre la réalité des formes des signaux numériques et
analogiques.

Ces signaux, sans anti rebond (debouncing) ou filtrage se comportent comme des sources
sporadiques.

18

Vous aimerez peut-être aussi