Tatiana Curelli - Support système pour l'ordonnancement d'applications synchrones dans les noyaux de systèmes critiques embarqués - Résultats

De Ensiwiki
Aller à : navigation, rechercher


Support système pour l'ordonnancement d'applications synchrones dans les noyaux de systèmes critiques embarqués

Labo Verimag
Equipe Synchrone
Encadrants pascal.raymond@imag.fr,christophe.rippert@imag.fr

Etudiant

Curelli, Tatiana

Introduction

Les systèmes critiques ou systèmes temps-réel sont des systèmes qui essayent de contrôler leur environnement grâce à des capteurs et à des actionneurs. La vitesse d'interaction du système avec l'environnement est contrainte par l'environnement ; elle doit être suffisamment rapide afin que le système ne manque pas d'informations significatives sur l'évolution de l'état de l'environnement.

Le développement de systèmes critiques nécessitent donc l'utilisation de méthodes spécialisées permettant de garantir que les contraintes de temps auxquelles sont soumis les systèmes seront respectées.

Les systèmes temps-réel peuvent être programmés de façon totalement déterministe grâce aux langages synchrones. Dans le TER, nous avons utilisé le langage synchrone Lustre. Dans le cas d'un système multi-tâches, les tâches écrites en langage synchrone sont ensuite généralement ordonnancées "à la main", sans utiliser d'OS, afin de ne pas introduire d'indéterminisme dans le système. Cependant, cette méthode est fastidieuse et est susceptible d'introduire des erreurs : en particulier, elle est difficile à mettre en œuvre en présence de tâches longues car il faut alors procéder à des découpages des tâches longues en sous-tâches afin de respecter les dates d'éxécution des autres tâches.

La tendance est donc d'utiliser un minimum de support système afin de faciliter la gestion des tâches longues tout en respectant la contrainte de déterminisme du système.

Dans ce TER, notre objectif était de programmer des systèmes multi-tâches sur le robot LEGO MINDSTORM NXT. Pour la brique LEGO, il existe un OS, nxtOSEK, permettant à un programmeur de contrôler l'ordonnancement de ses tâches en spécifiant notamment leur période et leur priorité. Ainsi, notre principale travail a consisté à prendre ce système et à en extraire les briques de base afin de faire du multi-tâches sur la brique.

Eléments de pré-requis

Lustre et compilation de Lustre en C

Le langage Lustre est un langage synchrone dit à flot de données ie les variables en Lustre sont considérées comme une séquence infinie de valeurs. Un programme écrit en Lustre peut-être compilé en C ; on obtient 3 fonctions :

  • une fonction step : corps de la tâche lustre
  • des fonctions tache_I_entree : pour lire les entrées (ie les capteurs dans un système réel)
  • des fonctions tache_O_sortie : pour affecter les sorties (ie les actionneurs)

nxtOSEK

nxtOSEK est un système d'exploitation temps-réel open source pour la brique LEGO MINDSTORM NXT.

Structure de nxtOSEK

Ci-dessous, une représentation de la structure de nxtOSEK.

Struct nxtOSEK.jpg

L'utilisateur doit écrire le corps de ses tâches en C. Puis, dans un autre langage, le langage OIL, il spécifie la configuration des tâches ie au moins leur périodes et leur priorités. Il dispose pour cela d'objets nxtOSEK comme par exemple les objets TASK , ALARM, COUNTER ou encore l'objet EVENT qui permet la gestion des tâches urgentes.

Exemple de code OIL : configuration d'une TASK et d'une ALARME

TASK myTask {

  AUTOSTART = FALSE;
  PRIORITY = 2;
  ACTIVATION = 1;
  SCHEDULE = FULL;
  STACKSIZE = 512;
  RESOURCE = lcd;

} ;


ALARM cyclic_alarm1 {

  COUNTER = SysTimerCnt;
  ACTION = ACTIVATETASK
  {
     TASK = myTask;
  };
  AUTOSTART = TRUE
  {
     ALARMTIME = 1;
     CYCLETIME = 1000;
     APPMODE = appmode1;
  };

};

Le fichier OIL est ensuite transformé par un compilateur OIL en 2 fichiers kernel_id.h et kernel_cfg.c qui contiennent des structures de données qui sont exploitées par l'OS nxtOSEK pour ordonnancer les tâches sur la brique LEGO. Enfin, ces 2 fichiers sont compilés avec le code des tâches et les sources de l'OS pour obtenir un éxécutable qui peut-être chargé dans la RAM de la brique.

Ordonnancement des tâches par nxtOSEK

Chaque tâche possède une priorité. A chaque instant, l'OS exécute la tâche dont la priorité est la plus élevée. Si une tâche longue est en train de s'exécuter sur le système et qu'une tâche plus courte mais plus prioritaire devient prête c'est l'OS qui se charge de découper la tâche longue en sous-tâches et de donner la main à la tâche courte.

Voici un exemple d'exécution avec deux tâches T1 et T2, T2 étant la plus prioritaire.

Ord OS.jpg

Travail réalisé

Objectifs

L'objectif principal était de faire du multi-tâches sur la brique LEGO en utilisant le minimum de briques systèmes de nxtOSEK. D'autre part, nous souhaitions ne pas avoir à utiliser un autre langage pour spécifier la configuration des tâches. L'idéal serait de disposer d'un langage pseudo Lustre, que l'on note Lustre+, qui permettrait à la fois de spécifier le corps des tâches et de spécifier leur configuration.

Extraction des briques de bases

J'ai extrait les briques de bases de nxtOSEK pour faire du multi-tâches. Cette étape a consisté à identifier les sources de nxtOSEK dont nous avions besoin pour le TER et à faire un nouveau Makefile pour recompiler l'OS avec uniquement ces sources.

Le système actuel permet de déclarer des tâches caractérisées par leur période et leur priorité et de déclarer des verrous pour la communication entre tâches.

Solution alternative au compilateur OIL

A défaut d'avoir un compilateur Lustre+, j'ai écrit des scripts afin de simuler le compilateur OIL. Ces scripts prennent en paramètres le nombre de tâches et le nombre de verrous du système et produisent donc les fichiers kernel_id.h et kernel_cfg.c ; ils produisent également des squelettes de fichiers C où l'utilisateur doit appeler le code C qu'il a obtenu en compilant ses tâches lustre et où il doit également compléter des macros afin de spécifier les périodes et les priorités de ses tâches.

Programmation d'exemples de systèmes multi-tâches

Afin de vérifier que le système obtenu fonctionnait correctement, j'ai implémenté des exemples de systèmes multi-tâches.

J'ai écrit 2 tâches permettant de contrôler la position du robot. Une tâche de petite période qui commande la distance du robot par rapport à un mur et une tâche plus lente mais moins prioritaire que la première dont la fonction est de contrôler l'angle du robot par rapport à un mur. Ces 2 tâches communiquent par l'intermédiaire de variables globales. Pour éviter d'avoir à utiliser des verrous, les tâches ont des périodes multiples : il est ainsi possible avec un compteur de savoir dans quelle condition une tâche prend la main et si elle a le droit d'accéder aux variables partagées. Ce mécanisme de communication est un mécanisme général pour garantir le déterminisme des communications sans utiliser de verrous. Il est entièrement automatisable et, à long terme, ceci sera fait par le compilateur Lustre+.

Ci-dessous une représentation schématique des 2 tâches.

Bob.jpg

Le robot ne tourne pas toujours assez vite pour éviter le mur. Ceci n'est pas dû à un problème dans TER mais à un problème d'automatique. Les coefficients des contrôleurs ont encore besoin d'être réglés.

Conclusion

Il a pu être vérifié sur plusieurs exemples que le système actuel fonctionne : il permet de faire du multi-tâches sur la brique LEGO.

Ce TER s'inscrit dans un projet à long terme dont le but est de proposer une démarche automatisée pour la programmation multi-tâches des systèmes critiques embarqués. Une première étape consisterait à découper une tâche lustre en sous-tâches. Ce problème a été abordé par Sarah Moussouni dans un autre TER. Les sous-tâches seraient ensuite compilées avec les briques de base extraites de nxtOSEK et le fichier de configuration écrit en Lustre+ pour obtenir un exécutable.

Ci-dessous une représentation schématique du système :

Syst cplet.jpg

Références

Documents additionnels