TP4: Gestion des interruptions et ordonnancement de processus

Date limite: 21 mars 2016 à 23h59

Ce travail pratique vaut 3% de la note totale du cours. À faire individuellement, il est à remettre au plus tard lundi le 21 mars 2016 à 23h59.

Objectifs

Ce travail pratique vise les objectifs suivants:

  1. Se familiariser avec les interruptions
  2. Comprendre le fonctionnement d'une table des vecteurs d'interruption;
  3. Mettre en place une table des vecteurs d'interruption rudimentaire en assembleur ARM;
  4. Implanter une routine de traitement d'interruption en assembleur ARM;
  5. Comprendre la sauvegarde de contexte effectuée par un système d'exploitation;

Préparation

Pour ce travail pratique, nous réutiliserons l'environnement « IAR Embedded Workbench ». Si vous n'êtes pas familier avec ce système, ou si vous n'êtes plus certain des étapes à effectuer pour créer un nouveau projet, il est important que vous consultiez les notes pour le travail pratique 2 afin d'assurer que vous démarrez le TP dans un environnement adéquat.

En plus des modifications usuelles au projet énumérées dans l'énoncé du TP2, nous allons mettre en place une interruption périodique dans IAR. Cela permettra de simuler l'utilisation d'une horloge interne au processeur, capable d'interrompre régulièrement son travail. Pour ce faire, une fois le projet créé et configuré, allez dans le menu Simulator et cliquez sur l'item Interrupt Setup :

Vous devriez alors voir apparaître la fenêtre suivante. Cliquez alors sur le bouton New :

Une nouvelle fenêtre s'ouvrira. Vous devez sélectionner les options suivantes :

Laissez les autres options à leur valeur par défaut. Votre fenêtre devrait alors présenter exactement le contenu de celle-ci :

Finalement, cliquez sur Ok pour fermer les deux fenêtres en sauvegardant les changements. Cette procédure fait en sorte que lors de la simulation, une interruption FIQ surviendra après 250 cycles processeurs (la valeur cyclecounter dans la vue des registres dans le débogueur), puis à tous les 90 cycles.

Afin de faciliter le débogage de ce TP, nous vous suggérons d'activer les views Breakpoints, Disassembly, Register et Memory. Au final, votre espace de travail pourrait ressembler à quelque chose du genre :

Questionnaire

Ce TP s'effectue en deux étapes, qui vous demanderont respectivement d'écrire du code (pour 70% de la note du TP), et de répondre à des questions (pour 30% de la note).

1. Code (70% de la note)

Premièrement, il vous faudra coder un système d'exploitation (très) rudimentaire, capable de gérer l'exécution alternative de deux processus distincts, sans que ces derniers ne soient affectés. Pour ce faire, le processeur génère périodiquement une interruption, indépendamment de ce que font les processus. Cette interruption est gérée par le système d'exploitation, qui peut alors décider d'arrêter temporairement un processus pour laisser la place à un autre. Ce système est qualifié de préemptif, puisqu'il peut interrompre un processus à n'importe quel moment, même si ce dernier est dans une boucle infinie. Nous verrons plus en détail les notions reliées à l'ordonnancement des processus dans la suite du cours, mais sachez pour l'instant que cette gestion des processus est tout à fait similaire à ce que fait votre ordinateur lorsque plusieurs programmes requièrent simultanément du temps de calcul.

Vous devrez coder trois sections de code distinctes :

  1. La table des vecteurs d'interruption;
  2. Le code initialisant le système et les processus;
  3. La routine d'interruption permettant au système de changer le processus en cours d'exécution tout en sauvegardant son contexte.

Vous trouverez plus d'informations sur chacune de ces sections dans la section détails ci-bas.

Le fichier asm.s fourni contient plus de précisions quant à la tâche exacte qui vous est demandée pour chacune de ces sections.

Téléversez votre fichier asm.s qui contient votre réponse dans la boîte de dépôt qui est disponible dans la section « Évaluations et résultats » du portail des cours.

2. Questions (30% de la note)

Deuxièmement, une fois votre code implanté et testé (nous verrons comment vous pouvez tester son bon fonctionnement), vous devez répondre à dix (10) questions sur le portail des cours. Notez que contrairement aux travaux pratiques précédents, ces questions ne portent pas sur des lignes en particulier, mais bien sur le fonctionnement global de votre programme et des interruptions en ARM.

Ces questions sont disponibles dans la section « Questionnaires » du portail des cours.

La politique des retards mentionnée dans le plan de cours sera appliquée. Comme il y a un fichier à téléverser et des questions à répondre, la date la plus tardive d'entre les deux sera utilisée pour le calcul des retards. Pour toutes questions concernant la procédure de remise ou le travail lui-même, posez vos questions sur le forum!

Détails

1. La table des vecteurs d'interruption

Comme beaucoup d'architectures, l'ARM utilise une table des vecteurs d'interruption pour permettre au programmeur de spécifier quoi faire pour chaque type d'interruption. Cette table est située au tout début de la mémoire, à partir de l'adresse 0x00. Le tableau suivant présente le détail de ces vecteurs d'interruption.

AdresseCorrespond à l'interruption...
0x00000000Reset
0x00000004Instruction invalide
0x00000008SWI ou SVC (interruption logicielle)
0x0000000CPrefetch Abort
0x00000010Data Abort
0x00000014Inutilisé
0x00000018IRQ (Interruption Request)
0x0000001CFIQ (Fast Interrupt Request)

Comme vous pouvez le constater, vous utilisiez déjà une interruption sans le savoir, soit l'interruption Reset, en écrivant B main au tout début du programme. Cette instruction se retrouvait à l'adresse 0x00 et indiquait au processeur quoi faire lors d'un reset, à savoir aller à l'étiquette main.

Dans ce TP, nous avons implanté l'entrée de la table pour l'interruption Reset (voir B moninitialisation). Vous devrez écrire le code correspondant à l'interruption FIQ, qui devrait brancher vers votre routine de traitement de l'interruption, soit l'étiquette moninterruption.

2. Initialisation du système et des processus

Lorsqu'une interruption survient, le processus en cours d'exécution peut être n'importe où dans son code assembleur. Il nous faut par conséquent être capables d'enregistrer l'état du processus afin d'être en mesure de le restaurer plus tard, sans que ce dernier ne « remarque » qu'il a été interrompu. Plus précisément, dans ce TP, vous devrez sauvegarder :

Pour sauvegarder ces données, votre système dispose de deux piles différentes : Pile0, qui contient les informations nécessaires au processus 0, et Pile1 pour le processus 1. La figure suivante montre l'organisation mémoire déjà préparée pour vous dans le fichier asm.s. Sur la pile de chaque processus se trouve l'adresse de retour, suivie de l'état des drapeaux, suivi des registres R7 à R0, dans cet ordre. R0 est donc le registre qui est le premier élément de la pile lorsque cette dernière est remplie. N'oubliez pas que la pile fonctionne de bas en haut!

Il vous faudra tout d'abord initialiser les piles Pile0 et Pile1. Pour ce faire, vous devrez accomplir les trois étapes suivantes:

  1. Initialiser la pile du processus 0;
  2. Initialiser la pile du processus 1;
  3. Mettre à jour la variable ProcessusCourant pour indiquer au système que c'est le processus 0 qui est exécuté en premier.

Pour les deux premières étapes, utilisez la fonction initialiseProcessus, qui fait tout le travail pour vous. Vous n'avez qu'à l'appeler avec les bons paramètres (voyez sa documentation dans le fichier asm.s pour plus de détails).

3. Routine de traitement de l'interruption

Votre routine de traitement de l'interruption correspond à l'étiquette moninterruption. Lors d'une interruption, votre routine doit, dans l'ordre :

  1. Déterminer le processus qui s'exécute présentement. Vous pouvez utiliser la variable ProcessusCourant pour mémoriser cette valeur;
  2. Sélectionner la pile du processus courant. Il vous faudra donc modifier le pointeur de pile SP selon l'identifiant de ce processus.
  3. Sauvegarder les registres R0 à R7, les drapeaux et PC (qui est automatiquement transféré dans LR par le processeur avant de commencer l'interruption) sur la pile du processus courant;
  4. Déterminer le prochain processus à exécuter. Dans le cadre de ce TP, il n'y a que deux processus, il suffit donc d'alterner entre les deux;
  5. Restaurer les registres R0 à R7 et les drapeaux du processus à reprendre à partir de sa pile;
  6. Sortir de l'interruption, en revenant dans le nouveau processus à exécuter. Pour revenir dans le bon processus, quel registre devrez-vous modifier?

Comme nous utilisons une interruption de type FIQ, votre routine de traitement de l'interruption peut utiliser les registres R8 à R15 sans interférer avec les processus. Pour vous simplifier la vie, servez-vous de ces registres comme registres de travail dans votre fonction moninterruption, ce qui vous évitera d'avoir à sauvegarder les registres que vous utiliserez dans moninterruption.

Tester et valider le bon fonctionnement du système

Afin de vous aider à déboguer votre code, il est recommandé d'utiliser les points d'arrêt (« breakpoints »), comme au TP3. Vous pouvez par exemple mettre un de ces points d'arrêt dans la routine d'interruption elle-même, afin de vérifier son bon fonctionnement. Une autre vérification simple est de vous assurer que les blocs correspondant aux processus 0 et 1 sont bel et bien exécutés en alternance à chaque interruption.

En ce qui concerne la validation de votre code, le fichier asm.s prévoit un système capable de détecter certaines erreurs. Il fonctionne en écrivant un code correspondant à cette erreur dans le registre R7, nous vous demandons donc de vous abstenir d'utiliser ce registre. Au début du programme, la valeur de R7 est non-nulle, mais doit le devenir et le rester après la première exécution des deux processus. Si, après plusieurs millions de cycles, la valeur de R7 est toujours à 0, vous pouvez considérer votre système comme suffisamment stable. Dans le cas contraire, cela indique un problème dans votre procédure de sauvegarde/restauration de l'état des processus.

Ressources

Remerciements

Merci à Marc-André Gardner pour la création de ce TP!

Retour à la page web du cours.