Rapport du projet. Générateur de code

Documents pareils
Quelques éléments de compilation en C et makefiles

Cours Langage C/C++ Programmation modulaire

Jade. Projet Intelligence Artificielle «Devine à quoi je pense»

Génie Logiciel avec Ada. 4 février 2013

XML par la pratique Bases indispensables, concepts et cas pratiques (3ième édition)

Grandes lignes ASTRÉE. Logiciels critiques. Outils de certification classiques. Inspection manuelle. Definition. Test

REALISATION d'un. ORDONNANCEUR à ECHEANCES

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Introduction au langage C

Générer du code à partir d une description de haut niveau

1 Architecture du cœur ARM Cortex M3. Le cœur ARM Cortex M3 sera présenté en classe à partir des éléments suivants :

Cours d initiation à la programmation en C++ Johann Cuenin

MEGA ITSM Accelerator. Guide de Démarrage

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Cours de Génie Logiciel

Création et Gestion des tables

1 Description générale de VISFIELD

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie

Cahier Technique. «Développer une application intranet pour la gestion des stages des étudiants» Antonin AILLET. Remi DEVES

Informatique industrielle A Systèmes temps-réel J.F.Peyre. Partie I : Introduction

TP1. Outils Java Eléments de correction

Traduction des Langages : Le Compilateur Micro Java

Manipulation 4 : Application de «Change».

Mon premier rpm. 7 juin Avant de commencer RPM URPMI RPMBUILD... 2

MEGA ITSM Accelerator. Guide de démarrage

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Les structures de données. Rajae El Ouazzani

TP1 : Initiation à Java et Eclipse

Introduction aux systèmes temps réel. Iulian Ober IRIT

1 Mesure de la performance d un système temps réel : la gigue

Gouvernance des mesures de sécurité avec DCM-Manager. Présentation du 22 mai 2014

Métriques de performance pour les algorithmes et programmes parallèles

LES OUTILS D ALIMENTATION DU REFERENTIEL DE DB-MAIN

Programmer en JAVA. par Tama

as Architecture des Systèmes d Information

Nom de l application

basée sur le cours de Bertrand Legal, maître de conférences à l ENSEIRB Olivier Augereau Formation UML

Eléments de spécification des systèmes temps réel Pierre-Yves Duval (cppm)

Cours 420-KEG-LG, Gestion de réseaux et support technique. Atelier No5-1

C++ COURS N 2 : CLASSES, DONNÉES ET FONCTIONS MEMBRES Classes et objets en C++ Membres d'une classe Spécification d'une classe Codage du comportement

BIRT (Business Intelligence and Reporting Tools)

Mes documents Sauvegardés

La technologie Java Card TM

Structure fonctionnelle d un SGBD

TUTORIEL Qualit Eval. Introduction :

PARAGON Disk Wiper. Guide de l utilisateur. Paragon Technology GmbH, System Programmierung. Copyright Paragon Technology GmbH

Tutoriel d installation de Hibernate avec Eclipse

WINDOWS SHAREPOINT SERVICES 2007

Projet Active Object

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

Déploiement de SAS Foundation

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Gestion des sauvegardes

Les diagrammes de modélisation

MEGA Application Portfolio Management. Guide d utilisation

Plan du cours Cours théoriques. 29 septembre 2014

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Optimiser pour les appareils mobiles

Document de spécification du logiciel VALPO Définition du format des fichiers des

Créer le schéma relationnel d une base de données ACCESS

Sciences de Gestion Spécialité : SYSTÈMES D INFORMATION DE GESTION

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

ASR1 TD7 : Un microprocesseur RISC 16 bits

Architecture des ordinateurs

Partie 7 : Gestion de la mémoire

Institut Supérieure Aux Etudes Technologiques De Nabeul. Département Informatique

Francis BISSON ( ) Kenny CÔTÉ ( ) Pierre-Luc ROGER ( ) IFT702 Planification en intelligence artificielle

Langage HTML (2 partie) <HyperText Markup Language> <tv>lt La Salle Avignon BTS IRIS</tv>

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Java Licence Professionnelle CISII,

Définition des Webservices Ordre de paiement par . Version 1.0

NETWORK & SOFTWARE ENGINEERING MANUEL D UTILISATEUR. Logiciel TIJARA. NETWORK AND SOFTWARE ENGINEERING Manuel d'utilisateur "TIJARA" 1

Les chaînes de caractères

Urbanisation de système d'information. PLM 6 (Product Lifecycle Management) Collaboration et partage d'informations

Chapitre 2. Classes et objets

Chapitre VI- La validation de la composition.

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Production de documents avec XSLT. Production de documents p.1/??

SQL Server Installation Center et SQL Server Management Studio

Sage 100 CRM Guide de l Import Plus avec Talend Version 8. Mise à jour : 2015 version 8

Windows Internet Name Service (WINS)

Sommaire. G. Pujolle, F. Ravat, C. Soulé-Dupuy, G. Zurfluh

V- Manipulations de nombres en binaire

Protocoles DHCP et DNS

TAGREROUT Seyf Allah TMRIM

INSTALLATION ET CONFIGURATION DE OPENLDAP

Techniques de stockage. Techniques de stockage, P. Rigaux p.1/43

OCL - Object Constraint Language

Annexe 6. Notions d ordonnancement.

Organiser le disque dur Dossiers Fichiers

UE C avancé cours 1: introduction et révisions

OASIS Date de publication

Plateforme PAYZEN. Définition de Web-services

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Transcription:

Rapport du projet Générateur de code Majeure systèmes embarqués 4 ème Année (I4) - Mai / Juin 2006 Suiveurs : R. Kocik - R. Hamouche - du laboratoire COSI 1

Remerciements Nous remercions nos suiveurs Monsieur Rémy KOCIK et Monsieur Rédha HAMOUCHE enseignants et chercheurs du laboratoire COSI (Conception des Systèmes Industrialisés) pour l idée même du projet qui nous a fortement intéressée, pour nous avoir permis de participer à la conception d une partie d un outils novateur qu est le projet ARIANE, pour leur soutien dans la compréhension des aspects techniques, mais également pour l autonomie qu ils nous ont laissée dans la réalisation. Nous remercions également Siliya PERTOVA et Borislav GRIGOROV, étudiants Bulgares, avec qui nous avons collaboré sur différents aspects de ce projet. 2

SOMMAIRE 1. Présentation générale 5 1.1 Le contexte 5 1.2 L état initial du projet 6 1.3 Les objectifs 6 2. Le macro-code XML 8 2.1 Objectif 8 2.2 Format XML 8 2.3 Le vocabulaire de description, les balises XML 9 2.4 Saisie d une description 16 2.5 L exemple de l asservissement en vitesse d un moteur 19 2.5.1 Présentation 19 2.5.2 L exemple PID 3f 1T 19 2.5.3 L exemple PID 3f 3T 21 2.5.4 L exemple P - I - D 23 3. La transformation XSLT pour code C-RTAI 24 3.1 Structure générale 24 3.2 Définition des constantes 25 3.2.2 La constante TICK_PERIOD 25 3.2.3 La constante PHASE de chaque tâche 26 3.2.4 Exemple 27 3.3 Définition des variables 27 3.3.1 La variable depart_taches 27 3.3.2 Les nouvelles variables temporelles 27 3.3.3 Exemple 28 3.4 Définition des tâches 28 3.5 La fonction init_module 29 3.5.1 Appel de fonctions 29 3.5.2 rt_task_init 29 3.5.3 Initialisation de t0 30 3.6 La fonction cleanup_module 31 4. Exécution du code généré 32 4.1 Compilation 32 4.2 Exécution 33 5. Récupération des traces d exécution 35 5.1 Objectif 35 5.2 Description 35 6. Visualisation des traces d exécution 38 6.1 Objectif 38 6.2 Description 38 7. Résultats obtenus 43 3

7.1 Asservissement d un moteur en vitesse par un PID 43 7.2 Asservissement d un pendule et d un moteur 47 8. Conclusion 48 8.1 Le bilan résultats / objectifs 48 8.2 Bilans personnels 48 8.3 Les évolutions 49 4

Générateur de code Mai - Juin 2006 1. Présentation générale 1.1 Le contexte Le générateur de code s intègre dans le projet ARIANE, dirigé par M. Rémy KOCIK et M. Rédha HAMOUCHE, enseignants-chercheurs du laboratoire COSI (Conception des Systèmes Industrialisés) de l ESIEE. L outils ARIANE permettra à terme de : modéliser des systèmes graphiquement à l aide de blocs fonctionnels, à la manière de SIMULINK ou SCICOS, de caractériser les spécifications logicielles également graphiquement, c est à dire définir des regroupements de blocs fonctionnels dans des tâches (définies par une période, une priorité...) à la manière de TRUETIME, d importer des architectures systèmes d autres plates-formes, de définir les implémentations logicielles, de générer un code compilable pour différentes cibles, de visualiser des ordonnancements théoriques ou des traces d exécutions de tâches réelles, afin d estimer la qualité de l ordonnancement, qui permettra de valider le code, ou au contraire d améliorer la représentation du modèle et/ou de modifier les caractéristiques de l ordonnancement. Ces étapes forment un cycle bien connu des concepteurs de logiciels de contrôle temps réel. L outils ARIANE est novateur et permet d atteindre les 2 principaux objectifs que visent les entreprises qui travaillent dans le domaine de la conception de systèmes de contrôle temps réel, à savoir la fiabilité des systèmes et la réduction du temps de développement, donc du coût.!"#"$%&'($)%(&*+%&,-(').')/*.' 0*($)(#)*(&,1).')+*."1,2%&,*#3,+01%#&%&,*#)1*!,/,'11' /*#&'R&')D)?BO9E<CC989>6)?UH>)<H6FE)?9);<>;9C6F<>)?95)54567895)98N=@PHB5)698C5)@B9E)<@F9>6B5);<>6@XE9 *VS'/&,W)D);<>;9O<F@)E=)C=@6F9)IB>B@=6F<>)=H6<8=6FPH9)?9);<?9)?9);96)<H6FE! #!"#$%&%$'(%)*+,)-%$%.,,. A7@9)B6=C9)D)8<?BEF59@)E9)5456789)96)?BGF>F@)H>9)5CB;FGF;=6F<>)E<IF;F9EE9 9>6@B9)A -#*#/'(%)*+0.+$)0. L789)B6=C9)D)6@=>5G<@89@)E=)5CB;FGF;=6F<>) E<IF;F9EE9)9>);<?9);<8CFE=NE9 5<@6F9)A &K;J9)A &K;J9)L 5<@6F9)L 9>6@B9)L R+1 &K;J9)M 2456789):);<88=>?9@ " +<?BEF5=6F<>)96)54>6J759)?9)E=)E<F)?9);<88=>?9.B;<HC=I9)?9)E=)E<F)?9);<88=>?9) 9>)6K;J95)698C5)@B9E!B>B@=6F<>)=H6<8=6FPH9)?UH>) 8=;@<3;<?9)?=>5)H>)G<@8=6)R+1 1.!2/.!+.(+'*',3!.+0.+"./&)/1'*$.!,Y+)?9);@B=6F<>)96);<>GFIH@=6F<>)?UH>)GF;JF9@)R+1 R21 M789) B6=C9 )D) 895H@9@) E95) C9@G<@8=>;95)?9) EU=EI<@F6J89) F8CEB89>6B)96)=>=E459@)E9);<8C<@6989>6)698C5)@B9E 1FN@=F@F95)?9)6@=?H;6F<>)?95)8=;@<5) R+1)9>);<?9)5<H@;9 %>=E459)698C<@9EE9)D)6@=;9@) EU9QB;H6F<>)?95)6K;J95 *N59@O=6F<>)?H);<8C<@6989>6) <N69>H R+1 /<?9)5<H@;9 /3$&%, /<?9)5<H@;9 S%T%)&98C5)$B9E!B>B@=6F<>)?UH>)GF;JF9@)?9) 6@=;95)?=>5)H>)G<@8=6)R+1!! /FNE9)5H@)E=PH9EE9)E9);<?9)956)9QB;H6B!"#$%&'(")*+))",-.'"/001'"2/&'3$'"*45(-.'5").6/$7315"89""!":(3;</0(5"="+;><?"@AB"C"D<E%F/5"B)GHIG)J"89"!"K3('3$5"="J1.4"LMI+L"C"J1;N/"GA2MHIG)"89"!"B/6%$/(%<$'"IM*+"89 5

Notre projet a contribué à 2 étapes de cet édifice. L un des modules permet d automatiser la génération de code, phase la plus coûteuse en temps de mise au point. Pour générer ce code compilable il faut partir d une description complète des lois de commande et de leur implantation. Nous avons travaillé sur le vocabulaire de description et la validation de celui-ci. Un autre module fournit des représentations graphiques des informations recueillies sur l ordonnancement des tâches. Cette partie permettait jusqu à présent de visualiser des ordonnancements théoriques. Nous avons fait évoluer ce module en permettant l importation de traces de chronométrages réels. 1.2 L état initial du projet Nous sommes partis du projet Génération d un code compilable à partir d un macro-code XML, réalisé par Saïsana SOUVANLASY, Nicolas PERROT, et Moulay Omar KHALID, qui proposait : la description des systèmes avec un certain nombre de balises XML, un programme permettant la saisie de la description d un système, un programme générant un code C-RTAI ou JAVA MindStorms 1 au moyen d un fichier XSLT. Notre projet a donc pour vocation l évolution de la description en XML des systèmes nécessitant un contrôle temps réel. Nous axerons donc la rédaction de ce rapport sur les apports et modifications de notre contribution, et invitons le lecteur à ce reporter au rapport Génération d un code compilable à partir d un macro-code XML, notamment sur ce qu est le XML et son utilité dans le cadre de ce projet, ainsi que sur la transformation d un fichier XML par un fichier XSL, aspects fort bien décrits dans ce rapport que nous ne voulons plagier. 1.3 Les objectifs L objectif du générateur de code est d aboutir de façon automatique à un logiciel, compilable pour une cible définie, qui réalise les fonctions décrites dans un macro-code XML selon l ordonnancement sélectionné. Pour y arriver il faut partir d une description détaillée du système. Nous avons cherché à faire évoluer ce format XML et valider celui-ci. Néanmoins ce format est voué à une évolution constante en fonction des difficultés rencontrées. Ces difficultés peuvent être au niveau de la description du système, ou de la cible choisie. L évolution de ce format implique la mise à jour de 4 éléments : le document de référence un fichier TEX décrivant le vocabulaire de description, le fichier de validation XMLSchema.xsd, le fichier de transformation RTAI.xsl, l application de saisie. Un deuxième objectif était d améliorer l application de saisie composée de nombreuses classes dont les 2 principales étaient Interface.java et Creation.java. La première ce voulait être une interface d un modèle de système décrivant les librairies, les tâches, les variables... Il convenait d en faire une véritable interface au sens JAVA, pouvant être implémentée par différentes classes. La classe Creation.java crée une fenêtre permettant la saisie des données. Cette dernière est vouée à disparaître quand le projet ARAINE proposera ses propres fenêtres de saisie graphique. Néanmoins pour les besoins du projet il fallait permettre la saisie, la modification, et l importation de systèmes dans un cadre plus conviviale. Pour pouvoir modifier et importer des systèmes il fallait donner une orientation plus OBJET aux constituants des systèmes. 1 The LEGO Group 6

L évolution du format de description XML impliquait de valider celui-ci en situation réelle sur des cibles temps réel, après génération du code compilable. Enfin en cours de projet nous avons été confronté au même problème que les concepteurs de systèmes temps réels, à savoir : Notre système semble correctement asservi, mais comment en être sûr. D où la nécessité de visualiser les traces d exécution des tâches. Nous avons donc pu nous pencher sur la génération d un fichier de traces le plus léger possible pour perturber le moins possible le fonctionnement du calculateur, mais suffisamment complet pour pouvoir être importé dans le module TraceViewer de l outils ARIANE. 7

2. Le macro-code XML 2.1 Objectif Ce macro-code doit décrire les fonctions du système, les taches qui seront exécutées dans le calculateur, et les librairies nécessaires à la bonne compilation du logiciel qui sera généré. Le tout est écrit dans un fichier au format XML. Après nous être familiarisés avec les programmes, nous avons dans un premier temps épuré le format des balises superflues, puis simplifié la description des dépendances de données, et ajouté la description de séquence de blocs fonctionnels pour chaque tâche. En même temps nous faisions évoluer le fichier XMLSchema.xml qui sert à valider les fichiers au format XML décrivant des systèmes (contenant donc un code générique), ainsi que les fichiers RTAI.xsl et JAVA.xsl servant à transformer le code générique en langage C RTAI ou JAVA MindStorm. Pour valider ces modifications nous avons choisi d utiliser un projet d asservissement d un moteur par un PID (Projet Intégration d une loi d ordonnancement dans un modèle réalisé par Charles COMBES, Christophe David, et Sébastien LEGUEUT). L asservissement du moteur par un PID n est pas une tâche ardue pour les calculateurs actuels, ils ont donc ajouté 2 autres tâches plus prioritaires pour perturber la tâche qui s occupe de l acquisition, le calcul du PID et applique la commande au moteur. Le but étant d obtenir un ordonnancement limite qui permette de visualiser une trace avec des préemptions entre tâches. La mise au point de ce contrôleur nous a permis d être confronté à plusieurs difficultés : Comment intégrer des fonctions de chronométrage, qui n ont aucun rapport avec la description du système, sans ajout au vocabulaire de description? Comment ajouter des fonctions avant le démarrage des tâches, ou après que celles-ci se terminent? Par exemple pour ouvrir ou fermer des canaux de communication entre les tâches temps réel et les programmes côté utilisateur. Quelles sont les paramètres des fonctions RTAI, et comment les générer à partir de la description XML du système? Par exemple l argument StackSize de la fonction rt_task_init (...,...,..., STACK_SIZE_t1,...,...,...). Comment définir des constantes dans la génération automatique de code, tout en laissant la possibilité à l utilisateur des les redéfinir dans des librairies? Utilisation de directives comme #ifndef... #endif. 2.2 Format XML Au 27 juin 2006, le format XML utilisé pour ce projet a été mis à jour dans le document : Format XML du code générique généré par l'outil Ariane. La modification la plus importante concerne la description du graphe de la spécification logicielle dans lequel une tâche comprend désormais une séquence de blocs fonctionnels, nommés «IC» pour Implementation Component. Cette modification apporte une représentation logicielle plus détaillée. 8

Afin de mieux se rendre compte de l évolution apportée, voici ce que nous avions auparavant et avons maintenant schématiquement : Avant : entrée Tâche 1 (code 1) Tâche 2 (code 2) Tâche 3 (code 3) sortie Les codes exécutés et les dépendances de données se trouvent au niveau des tâches. Après : entrée IC 1 (code 1) IC 2 (code 2) IC 3 (code 3) sortie Tâche 1 Tâche 2 Les codes exécutés et les dépendances de données se trouvent désormais au niveau des IC. 2.3 Le vocabulaire de description, les balises XML Version et racine de l'arborescence : Le fichier XML doit obligatoirement posséder une balise spécifiant la version du fichier et une balise ouverte servant de racine de l'arborescence. Ces 2 balises où viendront s'emboîter l'ensemble des autres balises sont définies comme suit : <?xml version= 1.0 encoding= iso-8859-1?> <ARIANE_Impl_Model>... </ARIANE_Impl_Model> Politique d'ordonnancement : Dans un premier temps le type d'ordonnancement utilisé doit être spécifié par la balise XML suivante : où : <Scheduling Policy = Fixed Preemptif= Yes Running_Time= 15000 /> Scheduling Policy définit la gestion des priorités des tâches. Ce champ peut prendre la valeur Fixed pour un ordonnancement à priorités fixes et Dynamic pour un ordonnancement à priorités dynamiques. Preemptif permet de spécifier si l'ordonnancement est préemptif ou non : yes où no 9

Running_Time est un paramètre qui définit le temps d'exécution alloué à l'ordonnanceur. Ce champs est spécifique à certains environnement, notamment pour la génération de code Java Temps Réel. Il n'est par contre pas utilisé dans le cadre d'une génération de code RTAI mais reste quand même obligatoire. Remarque : Il faudra dans les version futures faire évoluer le champ Running_Time afin soit qu'il ne soit pas obligatoire, soit en créant un fichier de paramètres spécifique à chaque générateur de code. Librairies : Il faut définir les librairies qui doivent être inclues dans le code (équivalent du include du langage C) afin de prendre en compte, à la compilation, les fichiers contenant notamment le code des différentes tâches à exécuter. La balise Import permet de spécifier une librairie à inclure, tous les imports étant regroupés au sein d'une balise Headers. La syntaxe est la suivante : <Headers> <Import FileName= programme1.h /> <Import FileName= programme2.h /> </Headers> Variables : Les communications entre les blocs de fonctions nécessitent généralement de déclarer des variables qui contiendront les données échangées. La déclaration de toutes les variables sera réalisée dans une balise <SharedMemory> qui contiendra une ou plusieurs balises fermantes <Var> ayant comme attributs : Name qui indique le nom de cette variable qui représente le lien de communication, Type le type de la variable. Les variables <In> et <Out> des composants d'implantation doivent faire référence à ces variables (cf.\ref{sub_in_out}). Example <SharedMemory> <Var Name= Vitesse Type= Integer /> <Var Name= Acceleration Type= Float /> </SharedMemory> Composant d'implantation : Un composant d'implantation est déclaré dans le fichier XML en utilisant une balise <IC>. Cette balise contiendra d'autres balises - <In>, <Out>, <Body> - pour référencer complètement le fonctionnement de ce bloc. Tous les composants d'implantation sont 10

déclarés à l'intérieur de la balise <Seq> (décrite dans la section sur les tâches (cf.\ref {sub_seq})) comme suit : la balise <IC> <Seq> <IC Name= Convertisseur >...... <IC Name= Multiplexeur >... </Seq> Cette balise comporte deux attributs qui sont Name le nom et ID l'identifieur du composant d'implantation, cette dernière est optionnelle pour les composants d'implantations spécifiques qui ne nécessitent pas de chronométrage ou de communication avec les programmes côtés utilisateur. les balises <Param>, <In> et <Out> La balise <IC> pourra contenir des balises <Param>, <In> et <Out>, elles représentent les ports d'entrées sorties de ces composant d'implantation, ainsi que les paramètres utiles aux fonctions. L'ordre dans lequel elles sont déclarées est important puisqu'il conditionnera l'ordre d'appel des paramètres de la fonction exécutée par ce composant d'implantation. <Param> prend trois attributs qui sont Name le nom du port, Type le type du paramètre, et Value la valeur de ce paramètre. <In> et <Out> prennent toutes les deux deux attributs qui sont Name le nom du port et Var celui de la variable consommée ou produite, déclarée auparavant (cf. \ref{sec_variables}). la balise <Body> Cette balise possède 6 attributs : Pre définit le nom de la fonction à appeler à l'initialisation du composant d'implantation, CapaPre définit la capacité mémoire nécessaire au bon fonctionnement de la fonction nommée après l'attribut Pre, Exe définit le nom de la fonction à appeler en cas de boucle dans le composant d'implantation, CapaExe définit la capacité mémoire nécessaire au bon fonctionnement de la fonction nommée après l'attribut Exe, Post définit le nom de la fonction à appeler à la finalisation du composant d'implantation, CapaPost définit la capacité mémoire nécessaire au bon fonctionnement de la fonction nommée après l'attribut Post. 11

Les capacités sont cumulées par tâches et additionnées à 2000 octets pour initialiser la StackSize de chaque tâche. Les attributs Pre, Exe, et Post ne sont pas tous obligatoires. Example de Composant d'implantation <IC Name= Derivateur ID= 00002 > <In Name= e1 Var= Vitesse /> <Out Name= s1 Var= Acceleration /> <Body Pre= Init_Derivateur CapaPre= 0 Exe= Exe_Derivateur CapaExe= 1000 Post= Fin_Derivateur CapaPost= 0 /> Tâches : Une tâche est déclarée dans le fichier XML en utilisant une balise <Task>. Cette balise contiendra une balise - <Seq> - pour décrire les IC attribués à cette tâche. Toutes les tâches sont déclarées à l'intérieur d'une balise <TaskSet> comme suit : <TaskSet> <Task Name= Capteur...... </Task>... <Task Name= Controle...... </Task> </TaskSet> la balise <Task> Cette balise comporte plusieurs attributs qui sont les paramètres de la tâche soit : Name le nom de la tâche Id l'id de la tâche Priority la priorité d'exécution Period la période de la tâche Deadline la deadline StartTime la date de démarrage NBIteration le nombre d'exécution de la tâche avant arrêt StackSize la capacité mémoire nécessaire au bon fonctionnement de la tâche, selon les données manipulées. 12

la balise <Seq> Cette balise peut contenir plusieurs balises ouvertes <IC> contenant les composants d'implantation décrits précédemment (cf.\ref{sec_ic}). Example de Tâche <Task Name= Capteur Id= 1 Priority= 1 Period= 10 Deadline= 10 StartTime= 0 NBIteration= 100 StackSize= 2000 > <Seq> <IC Name= Derivateur ID= 00002 > <In Name= e1 Var= Vitesse /> <Out Name= s1 Var= Acceleration /> <Body Pre= Init_Derivateur CapaPre= 0 Exe= Exe_Derivateur CapaExe= 0 Post= Fin_Derivateur CapaPost= 0 /> <IC Name= Sommateur ID= 00003 >...... </Seq> </Task> Initialisation et finalisation : Avant la création des tâches, un système peut avoir besoin d'être initialisé ou dérouler un certain nombre d'opération. De même quand son exécution se termine. Les balises <Init> et <CleanUp> permettent d'intégrer des composants d'implantation pour ce contexte. Ces balises contiendront une balise - <Seq> - pour décrire les IC attribués à l'initialisation et à la finalisation. Example d'initialisation et de finalisation <Ini> <Seq> <IC Name= Chrono > <Param Name="Schedule" Type="String" Value='"RMS"'/> <Param Name="Prempt" Type="String" Value='"YES"'/> <Body Pre="fifo_Ordo"/> <IC Name="Chrono"> <Param Name="NameTask" Type="String" Value='"t1"'/> <Param Name="Id" Type="Integer" Value="1"/> <Param Name="Period" Type="Integer" Value="1000"/> <Param Name="Dead" Type="Integer" Value="1000"/> <Param Name="Phase" Type="Integer" Value="1000"/> <Body Pre="fifo_Tasks"/> <IC Name= Chrono >...... </Seq> </Init> <Cleanup> 13

<Seq> <IC Name="Chrono"> <Body Exe="fifo_Clean"/> </Seq> </Cleanup> Example complet : <?xml version="1.0" encoding="iso-8859-1"?> <ARIANE_Impl_Model > <Headers> <Import FileName="MonProgramme1.h"/> <Import FileName="MonProgramme2.h"/> </Headers> <Scheduling Policy="Fixed" Preemptif="Yes" Running_Time="15000"/> <SharedMemory> <Var Name="capteur1b" Type="Boolean"/> <Var Name="capteur2b" Type="Boolean"/> <Var Name="capteur3b" Type="Boolean"/> <Var Name="capteur1i" Type="Integer"/> <Var Name="capteur2i" Type="Integer"/> <Var Name="capteur3i" Type="Integer"/> <Var Name="actif1" Type="Boolean"/> <Var Name="actif2" Type="Boolean"/> <Var Name="actif3" Type="Boolean"/> <Var Name="CaptLum" Type="Integer"/> <Var Name="avancerA" Type="Boolean"/> <Var Name="reculerA" Type="Boolean"/> <Var Name="avancerB" Type="Boolean"/> <Var Name="reculerB" Type="Boolean"/> <Var Name="avancerC" Type="Boolean"/> <Var Name="reculerC" Type="Boolean"/> <Var Name="powerA" Type="Integer"/> <Var Name="powerB" Type="Integer"/> <Var Name="powerC" Type="Integer"/> </SharedMemory> <Ini> <Seq> <IC Name= Chrono > <Param Name="Schedule" Type="String" Value='"RMS"'/> <Param Name="Prempt" Type="String" Value='"YES"'/> <Body Pre="fifo_Ordo"/> <IC Name="Chrono"> <Param Name="NameTask" Type="String" Value='"t1"'/> <Param Name="Id" Type="Integer" Value="1"/> <Param Name="Period" Type="Integer" Value="1000"/> <Param Name="Dead" Type="Integer" Value="1000"/> <Param Name="Phase" Type="Integer" Value="1000"/> <Body Pre="fifo_Tasks"/> </Seq> </Init> <Cleanup> <Seq> <IC Name="Chrono"> <Body Exe="fifo_Clean"/> 14

</Seq> </Cleanup> <TaskSet> <Task Name="Entrees" Id="1" Priority="1" Period="10" Deadline="10" StartTime="0" NBIteration="100" StackSize= 0 > <Seq> <IC Name="Contacteurs" ID= 00001 > <Out Name="Poussoir1" Var="capteur1b"/> <Out Name="Poussoir2" Var="capteur2b"/> <Out Name="Poussoir3" Var="capteur3b"/> <Out Name="Detecteur1" Var="actif1"/> <Out Name="Detecteur2" Var="actif2"/> <Out Name="Detecteur3" Var="actif3"/> <Body Pre= Init_Contacteurs Exe= Exe_Contacteurs Post= Fin_Contacteurs /> <IC Name="Temperature" ID= 00002 > <Out Name="Sonde1" Var="capteur1i"/> <Out Name="Sonde2" Var="capteur2i"/> <Out Name="Sonde3" Var="capteur3i"/> <Body Pre= Init_Temperature Exe= Exe_Temperature Post= Fin_Temperature /> <IC Name="Lumiere" ID= 00003 > <Out Name="Detecteur1" Var="CaptLum"/> <Body Pre= Init_Lumiere Exe= Exe_Lumiere Post= Fin_Lumiere /> </Seq> </Task> <Task Name="Gestion" Id="2" Priority="2" Period="15" Deadline="15" StartTime="0" NBIteration="100" StackSize= 0 > <Seq> <IC Name="Derivateur" ID= 00004 > <In Name="Poussoir1" Var="capteur1b"/> <In Name="Poussoir2" Var="capteur2b"/> <In Name="Poussoir3" Var="capteur3b"/> <In Name="Detecteur1" Var="actif1"/> <In Name="Sonde1" Var="capteur1i"/> <In Name="Sonde2" Var="capteur2i"/> <In Name="Sonde3" Var="capteur3i"/> <Out Name="Commande1" Var="avancerA"/> <Out Name="Commande2" Var="reculerA"/> <Out Name="Commande3" Var="avancerB"/> <Out Name="Commande4" Var="reculerB"/> <Out Name="Commande5" Var="avancerC"/> <Out Name="Commande6" Var="reculerC"/> <Body Pre= Init_Derivateur Exe= Exe_Derivateur Post= Fin_Derivateur /> <IC Name="Sommateur" ID= 00005 > <In Name="Detecteur2" Var="actif2"/> <In Name="Detecteur3" Var="actif3"/> <In Name="Sonde" Var="CaptLum"/> <Out Name="Commande1" Var="PowerA"/> <Out Name="Commande2" Var="PowerB"/> <Out Name="Commande3" Var="PowerC"/> <Body Pre= Init_Sommateur Exe= Exe_Sommateur 15

Post= Fin_Sommateur /> </Seq> </Task> <Task Name="Sorties" Id="3" Priority="3" Period="10" Deadline="10" StartTime="0" NBIteration="100" StackSize= 0 > <Seq> <IC Name="Eclairage" ID= 00006 > <In Name="Lampe1" Var="powerA"/> <In Name="Lampe2" Var="powerB"/> <In Name="Lampe3" Var="powerC"/> <Body Pre= Init_Eclairage Exe= Exe_Eclairage Post= Fin_Eclairage /> <IC Name="MoteurX" ID= 00007 > <In Name="RelaisA1" Var="avancerA"/> <In Name="RelaisA2" Var="reculerA"/> <Body Pre= Init_MoteurX Exe= Exe_MoteurX Post= Fin_MoteurX /> <IC Name="MoteurY" ID= 00008 > <In Name="RelaisB1" Var="avancerB"/> <In Name="RelaisB2" Var="reculerB"/> <Body Pre= Init_MoteurY Exe= Exe_MoteurY Post= Fin_MoteurY /> <IC Name="MoteurZ" ID= 00009 > <In Name="RelaisC1" Var="avancerC"/> <In Name="RelaisC2" Var="reculerC"/> <Body Pre= Init_MoteurZ Exe= Exe_MoteurZ Post= Fin_MoteurZ /> </Seq> </Task> </TaskSet> </ARIANE_Impl_Model> 2.4 Saisie d une description Lorsque le projet ARIANE sera plus abouti, il proposera une interface graphique de saisie de schéma d une loi de commande, et permettra également de caractériser graphiquement le découpage en tâches. Pour le moment une application qui a été initiée par nos prédécesseurs et que nous avons fait évoluer permet la saisie de cette description et de générer le macro-code respectant le format XML que nous venons de présenter. Cette fenêtre a été aménagées pour respecter un ordre naturel de saisie. Saisie des librairies utilisées : 16

Saisie des variables reliant les composants d implantation : Nom et type des variables peuvent être saisis. Les types proposés ne sont pas exhaustifs et devront certainement être complétés. Saisie des composants d implantation : Les composants d implantation sont caractérisés par leur nom, un identifieur, les noms des fonctions initialisation, exécution, et finalisation, ainsi que les capacités mémoires supplémentaires requises pour ces fonctions, selon les variables manipulées. Chaque composant d implantation peut posséder paramètres, entrées, et sorties. Ces 2 dernières étant liées aux variables de liaisons. Les paramètres donnent la possibilité de passer des constantes comme par exemple le choix d un canal de carte d acquisition. Saisie des tâches : Les tâches sont caractérisées par leur nom, un identifieur, leur priorité, leur période, leur deadline, leur date de départ, un nombre d itérations, et une séquence de composants d implantation. Si le nombre d itérations est à zéro il devrait être calculé en fonction du temps d exécution et de la période de la tâche. Si le temps d exécution (décrit dans la partie ci-dessous) est nul alors il faudrait 17

générer dans le code compilable une boucle sans fin while(1). Ce calcul et ce test devrait être effectué dans les fichiers XSL, mais cela n a pas été fait dans cadre de ce projet. Saisie des caractéristiques d évaluation : Cette partie permet de spécifier un temps d exécution dans le cadre d une évaluation ou pour certaine cibles qui nécessitent ce paramètre (JAVA MindStorm), de sélectionner un ordonnancement dynamique ou fixe selon un mode acceptant la préemption ou non. Le bouton radio Chronos permet d insérer automatiquement des composants d implantation qui permettront de générer un fichier de trace d exécution. Exploitation du macro-code : Il est possible de visualiser le résultat de la description dans une fenêtre, et de l exporter dans un f i c h i e r p o r t a n t l extension xml. Le b o u t o n I m p o r t e r permet d ouvrir un fichier de description XML et de créer les objets qui y sont décrits, ce qui permet de visualiser la description ainsi que les objets dans les listes, mais également de compléter ou modifier cette description. Outre cette fenêtre de saisie générée par la classe Creation, une interface du modèle XML et une classe qui implémente cette interface ont été développée pour permettre une utilisation par d autres programmes notamment par l application graphique du projet ARIANE. Toute l application a été organisée en packages pour une meilleure organisation, et orientée objet pour tout les constituants du modèle XML pour simplifier leurs manipulations (modification, importation, suppression). 18

2.5 L exemple de l asservissement en vitesse d un moteur 2.5.1 Présentation Comme nous l avons dit précédemment, nous avons repris le travail réalisé dans le cadre du projet Intégration d une loi d ordonnancement dans un modèle qui utilisait l exemple de l asservissement en vitesse d un moteur par PID. Pour ce projet, trois tâches avaient été créées : - l une qui réalisait la fonction PID en 3 étapes : acquisition de la vitesse, calcul de la commande et envoi de celle-ci ; - deux autres tâches perturbatrices qui prenaient du temps au processeur et sont plus prioritaires que la première. En utilisant notre générateur de code, nous avons pu facilement implanter plusieurs spécifications logicielles que nous allons présenter. 2.5.2 L exemple PID 3f 1T Pour cet exemple nous avons repris la spécification 1 tâche pour le PID et 2 tâches perturbatrices, la tâche PID comprenant 3 IC : l un pour l acquisition de la vitesse, l un pour le calcul de la commande et l un pour l envoi de celle-ci. Nous avons alors le graphe suivant : e k-1 u k-1 Acquisition PID Commande vitesse Tâche 1 commande Perte 1 Tâche 2 Perte 2 Tâche 3 19

XML généré : <?xml version="1.0" encoding="iso-8859-1"?> - <!-- Ce fichier décrit le système AsservVitMoteur_RM_3f_1T.xml - version??? - date??? - auteurs??? --> - <ARIANE_Impl_Model> <Scheduling Policy="Fixed" Preemptif="Yes" Running_Time="00000" /> - <Headers> <Import FileName="constantes.h" /> <Import FileName="1710.h" /> <Import FileName="fonctions.h" /> </Headers> - <SharedMemory> <Var Name="vitesse" Type="Integer" /> <Var Name="commande" Type="Integer" /> <Var Name="ek" Type="Float" /> <Var Name="uk" Type="Float" /> </SharedMemory> - <TaskSet> - <Task Name="t1" Id="00001" Priority="00003" Period="01000" Deadline="00000" StartTime="00000" NBIteration="00030" StackSize="2000"> - <Seq> - <IC Name="Acquisition" Id="00001"> <Param Name="Canal" Type="Integer" Value="0" /> <Out Name="s1" Var="vitesse" /> <Body Pre="initConv" CapaPre="0" Exe="lecture" CapaExe="0" /> - <IC Name="PID" Id="00002"> <In Name="e1" Var="ek" /> <In Name="e2" Var="uk" /> <In Name="e3" Var="vitesse" /> <Out Name="s1" Var="ek" /> <Out Name="s2" Var="uk" /> <Out Name="s3" Var="commande" /> <Body Pre="init_pid" CapaPre="0" Exe="fn_PID" CapaExe="0" /> - <IC Name="Commande" Id="00003"> <Param Name="Canal" Type="Integer" Value="0" /> <In Name="e1" Var="commande" /> <Body Exe="ecriture" CapaExe="0" /> </Seq> </Task> - <Task Name="t2" Id="00002" Priority="00002" Period="00800" Deadline="00000" StartTime="00000" NBIteration="00030" StackSize="2000"> - <Seq> - <IC Name="perte1" Id="00004"> <Body Exe="perte1" CapaExe="0" /> </Seq> </Task> - <Task Name="t3" Id="00003" Priority="00001" Period="00500" Deadline="00000" StartTime="00000" NBIteration="00030" StackSize="2000"> - <Seq> - <IC Name="perte2" Id="00005"> <Body Exe="perte2" CapaExe="0" /> </Seq> </Task> </TaskSet> </ARIANE_Impl_Model> 20

2.5.3 L exemple PID 3f 3T Pour ce deuxième exemple, nous avons découpé la tâche 1 précédente en 3 tâches, chacune contenant cette fois un seul IC. Nous avons alors le graphe suivant : Acquisition vitesse Tâche 1 u k-1 e k-1 PID Tâche 2 commande Commande Tâche 3 Perte 1 Tâche 4 Perte 2 Tâche 5 XML généré : <?xml version="1.0" encoding="iso-8859-1"?> - <!-- Ce fichier décrit le système AsservVitMoteur_RM_3f_3T2.xml - version??? - date??? - auteurs??? --> - <ARIANE_Impl_Model> 21

<Scheduling Policy="Fixed" Preemptif="Yes" Running_Time="0" /> - <Headers> <Import FileName="constantes.h" /> <Import FileName="1710.h" /> <Import FileName="fonctions.h" /> </Headers> - <SharedMemory> <Var Name="vitesse" Type="Integer" /> <Var Name="commande" Type="Integer" /> <Var Name="ek" Type="Float" /> <Var Name="uk" Type="Float" /> </SharedMemory> - <TaskSet> - <Task Name="t1" Id="1" Priority="3" Period="1000" Deadline="0" StartTime="0" NBIteration="30" StackSize="3200"> - <Seq> - <IC Name="Acquisition" Id="1"> <Param Name="Canal" Type="Integer" Value="0" /> <Out Name="s1" Var="vitesse" /> <Body Pre="initConv" CapaPre="200" Exe="lecture" CapaExe="1000" /> </Seq> </Task> <Task Name="t2" Id="2" Priority="3" Period="1000" Deadline="0" StartTime="0" NBIteration="30" StackSize="2800"> - <Seq> - <IC Name="PID" Id="2"> <In Name="e1" Var="ek" /> <In Name="e2" Var="uk" /> <In Name="e3" Var="vitesse" /> <Out Name="s1" Var="ek" /> <Out Name="s2" Var="uk" /> <Out Name="s3" Var="commande" /> <Body Pre="init_PID" CapaPre="0" Exe="fn_PID" CapaExe="800" /> </Seq> </Task> - <Task Name="t3" Id="3" Priority="3" Period="1000" Deadline="0" StartTime="0" NBIteration="30" StackSize="2000"> - <Seq> - <IC Name="Commande" Id="3"> <Param Name="Canal" Type="Integer" Value="0" /> <In Name="e1" Var="commande" /> <Body Exe="ecriture" CapaExe="0" /> </Seq> </Task> - <Task Name="t4" Id="4" Priority="2" Period="800" Deadline="0" StartTime="0" NBIteration="30" StackSize="2000"> - <Seq> - <IC Name="perte1" Id="4"> <Body Exe="perte1" CapaExe="0" /> </Seq> </Task> - <Task Name="t5" Id="5" Priority="1" Period="500" Deadline="0" StartTime="0" NBIteration="30" StackSize="2000"> - <Seq> - <IC Name="perte2" Id="5"> <Body Exe="perte2" CapaExe="0" /> </Seq> </Task> </TaskSet> </ARIANE_Impl_Model> 22

2.5.4 L exemple P - I - D Un troisième exemple consisterait à décomposer le PID en 4 fonctions : une pour le calcul proportionnel, une pour le calcul intégral, une pour le calcul dérivé et une pour sommer le tout. Ce cas de figure n a pas été implanté. Nous aurions alors le graphe suivant en omettant les fonctions perturbatrices et la fonction dérivée : Acquisition vitesse Tâche 1 P e k-1 u kp Tâche 2 u k-1 I u ki Tâche 3 Somme u k Tâche 4 Commande Tâche 5 23

3. La transformation XSLT pour code C-RTAI 3.1 Structure générale Le code C-RTAI généré automatiquement provient de la transformation, à partir d un code écrit en langage XSL, d une description faite en XML. Nous avons fait évoluer le fichier XSL de départ issu du travail de nos prédécesseurs. Notre fichier est dans sa structure identique à celui de départ, à savoir l utilisation de six templates (ou modèles) correspondant aux 6 grandes parties du code généré : - définition des librairies - définition des constantes - définition des variables - définition des tâches - fonction init_module - fonction cleanup_module Pour information, les templates du langage XSL, qui peuvent être comparés aux procédures ou fonctions des langages informatiques, permettent de définir une mise en forme des données particulière qui pourra être utilisée à plusieurs reprises et évitera la redondance de code. Nous avons ici un template principal qui fait appel à 6 templates : <xsl:template match="/"> <xsl:call-template name="definition_librairies" /> <xsl:call-template name="definition_constantes" /> <xsl:call-template name="definition_variables" /> <xsl:call-template name="definition_taches" /> <xsl:call-template name="init_module" /> <xsl:call-template name="cleanup_module" /> </xsl:template> Nous allons expliquer et décrire ci-dessous les modifications apportées au fichier XSL et le code C- RTAI généré. Un point important qu il faut préciser ici est la ligne de conduite qui a été la nôtre pour tout ce qui concerne la transformation XML vers un code compilable via un fichier XSL. Cette ligne a été de factoriser au maximum les traitements, c est-à-dire de les réaliser en amont au niveau de la génération du fichier XML plutôt que de les intégrer au XSL. Il est en effet préférable, dans la mesure du possible, d enrichir et donc complexifier le XML plutôt que le fichier XSL servant à transformer ce XML. Car il faut bien garder à l esprit que le but de ce générateur de code est de pouvoir générer différents codes pour différentes cibles et ce grâce à différents fichiers XSL. Si l on choisit d intégrer une modification aux fichiers XSL alors qu il est possible de le faire au niveau du XML cela augmente la charge de travail à réaliser pour implémenter cette modification. Il est donc plus judicieux de préférer l intégrer au XML. 24

3.2 Définition des constantes Du fait du nouveau format dans lequel chaque tâche comporte désormais une séquence d IC, nous avons jugé pertinent de définir différemment la constante STACK_SIZE qui représente la taille de pile attribuée aux tâches. En effet, auparavant cette constante était définie de manière unique et était donc identique pour toutes les tâches. Afin de pouvoir créer des tâches avec des tailles de pile adaptées aux IC qu elles contiennent, il est plus judicieux d attribuer une valeur de taille par IC et, au niveau de la tâche, de calculer la valeur utilisée en additionnant une valeur par défaut avec toutes les valeurs de taille des IC de la tâche. Les valeurs de taille des IC sont définies dans le fichier XML à transformer, au niveau de la balise <Body>, et le calcul est fait en amont à la génération de ce fichier XML, la valeur à utiliser devenant un nouvel attribut, StackSize, de la balise <Task>. Le travail, au niveau XSLT, consiste à récupérer cette valeur et à définir une constante nommée comme les autres caractéristiques des tâches, c est-à-dire sous la forme STACK_SIZE_nom_de_la_tache. Nous avons donc ajouté dans le XSL : <xsl:call-template name="declaration_constante"> <xsl:with-param name="nom_cte" select="concat($nom_pile,@name)" /> <xsl:with-param name="valeur_cte" select="@stacksize" /> </xsl:call-template> Nous faisons appel au template declaration_constante avec passage des paramètres STACK_SIZE_nom_de_la_tache et la valeur de la taille de pile. 3.2.2 La constante TICK_PERIOD La constante TICK_PERIOD, exprimée en nanosecondes, est une valeur utilisée par le timer en mode périodique et passée en argument de la fonction start_rt_timer. Elle est ignorée en mode oneshot. Elle définit la période du timer, autrement dit la durée entre deux tops d horloge, et influe sur la précision de la mesure du temps. Nous avons été amené, pour tester nos codes générés, à utiliser un fichier constantes.h dans lequel cette valeur était également définie. Aussi avons nous jugé utile d encadrer sa définition dans le code générique par #ifndef et #endif. Ainsi, si au moment de la compilation elle a déjà été définie, cette nouvelle définition n est pas prise en compte. A ce titre, deux templates, declaration_test et declaration_test_fin ont été créés. Pour la déclaration nous avons donc : <xsl:call-template name="declaration_test"> <xsl:with-param name="nom_cte" select="$nom_debut_periode" /> </xsl:call-template> - <xsl:call-template name="declaration_constante"> <xsl:with-param name="nom_cte" select="$nom_debut_periode" /> <xsl:with-param name="valeur_cte" select="$valeur_debut_periode" /> </xsl:call-template> <xsl:call-template name="declaration_test_fin" /> avec l utilisation des templates suivants : 25

<!-- declaration des tests define --> - <!-- cela permet de creer #ifndef nom_cte --> - <xsl:template name="declaration_test"> <xsl:param name="nom_cte" /> <xsl:param name="valeur_cte" /> - <xsl:call-template name="declaration_generique"> <xsl:with-param name="type" select="$test_define" /> <xsl:with-param name="nom" select="$nom_cte" /> </xsl:call-template> </xsl:template> - <!-- declaration des tests define --> - <!-- cela permet de creer #ifndef nom_cte --> - <xsl:template name="declaration_test_fin"> <xsl:param name="nom_cte" /> <xsl:param name="valeur_cte" /> - <xsl:call-template name="declaration_generique"> <xsl:with-param name="type" select="$test_fin" /> </xsl:call-template> </xsl:template> On commence par faire appel au template declaration_test avec passage du paramètre TICK_PERIOD. Le template declaration_test fait alors appel au template declaration_generique avec passage des paramètres #ifndef et TICK_PERIOD. Suit l appel du template declaration_constante puis l appel du template declaration_test_fin qui fait appel au template declaration_generique avec passage du paramètre #endif. 3.2.3 La constante PHASE de chaque tâche Dans les caractéristiques d une tâche telles que définies dans la théorie de l ordonnancement, la phase (ou offset) représente la durée entre une date de référence et la date de première activation de la tâche. Lorsque toutes les phases de plusieurs tâches sont nulles, l activation est dite synchrone. Dans le cas contraire elle est dite non synchrone. Cette caractéristique faisant défaut dans le générateur de code de départ, elle devra être ajoutée dans l avenir dans le format XML. Néanmoins, nous avons modifié le XSL pour une utilisation future de ce paramètre notamment dans la partie «Définition des tâches». Une constante est donc déclarée, de manière similaire aux autres caractéristiques des tâches, c est-àdire sous la forme PHASE_nom_de_la_tache. xsl:call-template name="declaration_constante"> <xsl:with-param name="nom_cte" select="concat($nom_phase,@name)" /> <xsl:with-param name="valeur_cte" select="0 * 1000000" /> </xsl:call-template> Nous faisons toujours appel au template declaration_constante avec passage des paramètres PHASE_nom_de_la_tache et valeur de cette phase, aujourd hui considérée nulle puisque absente dans le fichier XML. Bien sûr, lorsque cette valeur sera présente dans le XML, il faudra alors apporter la petite modification suivante : le 0 devra être remplacé par @phase dans la ligne 26

<xsl:with-param name="valeur_cte" select="0 * 1000000" /> 3.2.4 Exemple Voici ce que l on obtient finalement pour la déclaration des constantes : /*************************************/ /* Declaration des constantes */ /*************************************/ #ifndef TICK_PERIOD #define TICK_PERIOD 1000000 #endif /**Declaration des constantes pour la tache t1**/ #define NUMERO_t1 00001 #define PRIORITE_t1 00001 #define PERIODE_t1 3.4E7 #define DEADLINE_t1 1.0E7 #define START_TIME_t1 00000 #define PHASE_t1 0 #define N_BOUCLE_t1 00005 #define STACK_SIZE_t1 2000 3.3 Définition des variables 3.3.1 La variable depart_taches La variable depart_taches de type RTIME, qui représente la date de début de mesure du temps et que l on peut considérer comme la date «0», est déclarée en globale et non plus dans l init_module comme auparavant car il nous a été nécessaire que les tâches puissent accéder à sa valeur pour les fonctions de chronométrage. Son initialisation est faite dans la fonction init_module. 3.3.2 Les nouvelles variables temporelles Nous avons également ajouter les variables de type RTIME suivantes : maxperiod, t0 et delta ceci afin de pouvoir synchroniser l exécution périodique de tâches sur leur 2 ème activation, la 1 ère activation étant dédiée à l exécution des fonctions d initialisation (voir explication plus détaillée dans la fonction init_module). La variable t0 sera initialisée dans la fonction init_module. La variable delta est initialisée à 1 ms. Son utilisation étant propre au code C-RTAI elle ne devrait pas à priori être définie au niveau du XML. La variable maxperiod est créée pour contenir la plus grande période des tâches définies dans le fichier XML. Pour son initialisation, nous faisons appel à un nouveau template, recherche_maxperiod, qui trouve par traitement récursif la plus grande période des tâches. <xsl:template name="recherche_maxperiod"> <xsl:param name="listeperiodes" /> - <xsl:choose> - <xsl:when test="$listeperiodes"> <xsl:variable name="periode" select="$listeperiodes[1]" /> 27

- <xsl:variable name="valeurmax"> - <xsl:call-template name="recherche_maxperiod"> <xsl:with-param name="listeperiodes" select="$listeperiodes [position()!= 1]" /> </xsl:call-template> </xsl:variable> - <xsl:choose> - <xsl:when test="$periode > $valeurmax"> <xsl:value-of select="$periode" /> </xsl:when> - <xsl:otherwise> <xsl:value-of select="$valeurmax" /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise>0</xsl:otherwise> </xsl:choose> </xsl:template> Le principe est le suivant : on fait appel à ce template, au sein de la déclaration de la variable valeurmax, en passant comme paramètre la liste de toutes les valeurs de période définies dans le fichier XML, ceci étant réalisé en envoyant la valeur du nœud où se trouvent ces valeurs. xsl:variable name="valeurmax"> - <xsl:call-template name="recherche_maxperiod"> <xsl:with-param name="listeperiodes" select="ariane_impl_model/taskset/ Task/@Period" /> </xsl:call-template> </xsl:variable> Ensuite, le template recherche_maxperiod récupère la première valeur puis fait appel à lui-même toujours au sein d une déclaration de variable, valeurmax, et avec passage du paramètre la liste des périodes à laquelle on retire la première. Ceci jusqu à ce que la liste soit vide ce qui a pour conséquence d initialiser valeurmax à 0. Ensuite le template compare la valeur récupérée, c est-àdire la première valeur de chaque liste, à valeurmax pour modifier cette dernière si elle est inférieure. La valeur recherchée «remonte» ainsi tous les appels du template. Ce traitement a été intégré au XSL car propre au code C-RTAI. 3.3.3 Exemple Voici donc ce que l on obtient pour la déclaration des variables temporelles : /**Declaration des allocations memoires pour les variables temporelles**/ RTIME depart_taches; RTIME maxperiod = 1.0E9; RTIME t0; RTIME delta = 1000000; 3.4 Définition des tâches Etant donné que le format XML a changé pour avoir désormais une séquence d IC au sein de chaque balise <Task>, il a fallu modifier au sein du XSL les nœuds utilisés. Pour rappel, chaque IC peut contenir jusqu à trois fonctions : une fonction d initialisation (attribut Pre de la balise <Body> dans XML), une fonction d exécution (attribut Exe de la balise <Body>) et une fonction de finalisation (attribut Post de la balise <Body>). 28

On fait dorénavant appel, avant la boucle while() de chaque tâche du code généré, à la fonction d initialisation de chaque IC. De plus, ces fonctions reçoivent désormais respectivement les mêmes arguments (valeurs des paramètres et pointeurs sur variables) que la fonction d exécution de l IC. Ceci pour répondre à des besoins qui se sont faits sentir lors des tests réalisés sur l exemple de l asservissement d un moteur par PID où il fallait procéder, dans la fonction d initialisation, à l initialisation des variables de liaison. Dans la boucle while(), afin de pouvoir, à la première activation des tâches, avoir uniquement l exécution des fonctions d initialisation, nous avons déplacé l instruction rt_task_wait_period() au début de la boucle pour faire ensuite appel à la fonction d exécution de chaque IC de la séquence. Après la boucle while(), nous faisons appel à la fonction de finalisation de chaque IC de la séquence avec passage également des mêmes arguments que dans la fonction d exécution. 3.5 La fonction init_module 3.5.1 Appel de fonctions Lors de nos tests, nous avons eu besoin de faire appel à des fonctions au sein de la fonction init_module, fonction propre au code C-RTAI qui sert à initialiser un module et dans lequel on crée les tâches et les rend périodiques. Aussi, au niveau du format XML, nous avons ajouté une séquence d IC non destinée aux tâches et ce dans une nouvelle balise nommée <Init>. Cette séquence est utilisée de la manière suivante au niveau XSLT : aux trois fonctions définies au niveau des attributs de la balise <Body> des IC nous avons attribué trois emplacements dans l init_module pour l appel de ces fonctions. Soit : - Pour la fonction d initialisation (attribut Pre) : l appel est réalisé après /** Modes oneshot et preemptif ou non **/ ; - Pour la fonction d exécution (attribut Exe) : l appel est réalisé après /** Initialisation des taches **/ ; - Pour la fonction d initialisation (attribut Post) : l appel est réalisé après /** Lancement du temps **/. La présence des attributs Pre, Exe et Post étant optionnelle on peut faire un appel à l un des trois emplacements. 3.5.2 rt_task_init Dans l initialisation des tâches, deux arguments passés à la fonction rt_task_init qui initialise les tâches ont été modifiés. Tout d abord, pour le 4 ème argument int stack_size, puisque désormais chaque tâche possède une valeur qui lui est propre, on passe cette valeur qui est la constante STACK_SIZE_nom_de_la_tache. 29

Pour le 6 ème argument, int uses_fpu, qui si différent de zéro permet de travailler en valeurs flottantes et était jusque là mis à 0, on passe désormais la valeur 1. <xsl:for-each select="ariane_impl_model/taskset/task"> - <!-- pour chaque tache, on affiche ierr_nomtache= rt_task_init(...) --> <xsl:text></xsl:text> <xsl:value-of select="concat($variable_erreur,@name)" /> <xsl:value-of select="$affectation_variable" /> <xsl:text>rt_task_init(&</xsl:text> <xsl:value-of select="@name" /> <xsl:text>,</xsl:text> <xsl:value-of select="concat($nom_code,@name)" /> <xsl:text>,</xsl:text> <xsl:value-of select="concat($nom_numero,@name)" /> <xsl:text>,</xsl:text> <xsl:value-of select="concat($nom_pile,@name)" /> <xsl:text>,</xsl:text> <xsl:value-of select="concat($nom_priorite,@name)" /> <xsl:text>, 1, 0);</xsl:text> </xsl:for-each> 3.5.3 Initialisation de t0 Afin de synchroniser les activations des tâches sur leur 2 ème activation, nous initialisons la variable t0 par l écriture : t0 = depart_taches + nano2count(maxperiod + delta) Pour la périodisation des tâches, la date de départ passée en argument de la fonction rt_task_make_periodic est devenue : t0 PERIODE_Nom_de_la_tache + PHASE_Nom_de_la_tache. On a ainsi, si les phases sont nulles : 1 ères activations : exécution des fonctions d initialisation A partir des 2 èmes activations : exécution du corps des boucles while() tâche 1 P1 = maxperiod tâche 2 P2 tâche 3 P3 delta depart_tach es t0 = depart_taches + maxperiod + delta 30

L exécution des tâches est ainsi synchronisée sur leur 2 ème activation, la première étant réservée à l exécution des fonctions d initialisation précédant la boucle while(). 3.6 La fonction cleanup_module Comme pour la fonction init_module, nous avons eu besoin de faire des appels de fonctions dans la fonction cleanup_module, fonction propre au code C-RTAI utilisée pour libérer les allocations mémoire réalisées dans l init_module. Nous avons retenu le même principe que pour la fonction init_module, à savoir l utilisation d une nouvelle séquence d IC définie dans le fichier XML au sein d une nouvelle balise nommée <Cleanup>. A chaque attribut Pre, Exe et Post de la balise <Body>, trois emplacements dans la fonction cleanup_module ont été assignés. Soit : - Pour la fonction d initialisation (Pre) : l appel est réalisé au début ; - Pour la fonction d exécution (Exe) : l appel est réalisé après /** Mise en arret du temps **/ ; - Pour la fonction de finalisation (Post) : l appel est réalisé à la fin. 31

4. Exécution du code généré 4.1 Compilation Les modules sont compilés pour la cible souhaitée. Nous avons eu l occasion de tester l asservissement en vitesse du moteur sur un PC de bureau sous Linux-RTAI 3.3 et sur un PCembarqué sous Linux-RTAI 2.4. Tout les 2 étaient équipés d une carte d acquisition Adventech 1710. Voici les makefiles pour ces 2 cibles : PC sous Linux-RTAI 3.3 : TARGET1 := module_1710 TARGET := module_fonctions_v3 TARGET2 := AsservVitMoteur_RM_3f_1T2 TARGET3 := AsservVitMoteur_RM_3f_3T INCLUDE := -I/lib/modules/`uname -r`/build/include -I/usr/lib/realtime/ include CFLAGS := -O2 -Wall -DMODULE -D KERNEL -DLINUX CC := gcc ${TARGET}.o: ${TARGET}.c constantes.h fonctions.h $(CC) $(CFLAGS) ${INCLUDE} -c ${TARGET}.c 1710.o: 1710.c 1710.h $(CC) -o $@ -c $< calculus: calculus4.c fonctions.h constantes.h $(CC) -o $@ $< PC Embarqué sous Linux-RTAI 2.4 : KERNELDIR=/usr/lib/arcom/rtai-24.1.11 TARGET=/usr/lib/arcom/linux KIT = kit3.esiee.fr MI_OBJS +=module_1710.o module_fonctions_v3.o AsservVitMoteur_RM_3f_1T2.o A_TARG := CURRENT_DIR = $(PWD) ifdef TOPDIR include $(TOPDIR)/Rules.make else all: make -C $(KERNELDIR) modules SUBDIRS=$(CURRENT_DIR) clean: rm -f *.o *~ # make -C $(TARGET) subclean SUBDIRS=$(CURRENT_DIR) endif send:$(mi_objs) scp $(MI_OBJS) rtai@$(kit):/home/rtai sendcal: scp calculus rtai@$(kit):/home/rtai 32