Sujet du TP5, Prise en main de uC/OS-II sous ... - ETIS - ENSEA
Sujet du TP5, Prise en main de uC/OS-II sous ... - ETIS - ENSEA
Sujet du TP5, Prise en main de uC/OS-II sous ... - ETIS - ENSEA
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Université <strong>de</strong> CergyPontoise<br />
TP <strong>de</strong> prise <strong>en</strong> <strong>main</strong> <strong>de</strong> <strong>uC</strong>/<strong>OS</strong><strong>II</strong><br />
Le noyau temps réel<br />
Informatique Embarquée<br />
1. Intro<strong>du</strong>ction<br />
a. Le noyau temps réel <strong>uC</strong>/<strong>OS</strong><strong>II</strong><br />
<strong>uC</strong>/<strong>OS</strong> (ou microC/<strong>OS</strong>) est un système d’exploitation temps réel multitâches préemptif.<br />
Développé par le Canadi<strong>en</strong> Jean J. Labrosse, <strong>uC</strong>/<strong>OS</strong> est un exécutif temps réel <strong>de</strong>stiné à<br />
<strong>de</strong>s <strong>en</strong>vironnem<strong>en</strong>ts <strong>de</strong> très petite taille construits autour <strong>de</strong> Microcontrôleurs. Il est<br />
<strong>main</strong>t<strong>en</strong>ant disponible sur un grand nombre <strong>de</strong> processeurs et peut intégrer <strong>de</strong>s<br />
protocoles standards comme TCP/IP (µC/IP) pour assurer une connectivité IP sur une<br />
liaison série par PPP. Il est utilisable gratuitem<strong>en</strong>t pour l'<strong>en</strong>seignem<strong>en</strong>t.<br />
Il est aujourd’hui développé et <strong>main</strong>t<strong>en</strong>u par la société Micrium :<br />
http://www.ucosii.com/<br />
<strong>uC</strong>/<strong>OS</strong> est développé <strong>en</strong> C, sauf <strong>en</strong> ce qui concerne les portions <strong>de</strong> co<strong>de</strong> qui sont cibledép<strong>en</strong>dant<br />
(portage), comme l’implantation <strong>de</strong>s opérations <strong>de</strong> changem<strong>en</strong>t <strong>de</strong> contexte<br />
qui sont écrites <strong>en</strong> assembleur.<br />
<strong>uC</strong>/<strong>OS</strong> fait partie <strong>de</strong>s nombreux systèmes d’exploitation temps réel aujourd’hui<br />
disponibles sur le marché : A<strong>de</strong>os, Chorus<strong>OS</strong>, eCos, ITRON, Lynx<strong>OS</strong>, MicroC/<strong>OS</strong><strong>II</strong>,<br />
Nucleus, <strong>OS</strong>9, <strong>OS</strong>E, <strong>OS</strong>EK/VDX, pS<strong>OS</strong>, QNX, RSX11, RT11, RT<strong>OS</strong>UH, SCIOPTA,<br />
VRTX, VxWorks, Windows CE, RTLinux, RTAI …<br />
b. Objectif <strong>de</strong> la séance<br />
i. Objectif<br />
L’objectif <strong>de</strong> la séance <strong>de</strong> TP est la prise <strong>en</strong> <strong>main</strong> <strong>de</strong>s comman<strong>de</strong>s <strong>de</strong> base (API 1 )<br />
d’un RT<strong>OS</strong> et <strong>de</strong> compr<strong>en</strong>dre le principe fondam<strong>en</strong>tal <strong>de</strong> fonctionnem<strong>en</strong>t <strong>de</strong> ce type <strong>de</strong><br />
système. <strong>uC</strong><strong>OS</strong> étant un exemple représ<strong>en</strong>tatif <strong>du</strong> fonctionnem<strong>en</strong>t d’un RT<strong>OS</strong>, le travail<br />
réalisé <strong>sous</strong> cet <strong>en</strong>vironnem<strong>en</strong>t serait facilem<strong>en</strong>t instanciable avec un autre système<br />
d’exploitation.<br />
Cette intro<strong>du</strong>ction au développem<strong>en</strong>t d’applications embarquées temps réel<br />
comm<strong>en</strong>ce par une utilisation <strong>de</strong> l’<strong>OS</strong> sur PC mais sera <strong>en</strong>suite suivi d’une utilisation<br />
sur une carte <strong>de</strong> développem<strong>en</strong>t embarquée. La compréh<strong>en</strong>sion <strong>de</strong>s mécanismes <strong>de</strong> base<br />
est donc primordiale pour la suite <strong>de</strong>s TPs.<br />
A ce titre, vous <strong>de</strong>vrez à l’issue <strong>de</strong>s séances <strong>de</strong> TP réaliser une sout<strong>en</strong>ance sur les<br />
manipulations, développem<strong>en</strong>ts et tests que vous aurez réalisés.<br />
ii. Sout<strong>en</strong>ance<br />
10 minutes <strong>de</strong> sout<strong>en</strong>ance seront allouées par personne plus 5 minutes <strong>de</strong> questions.<br />
Lors <strong>de</strong> cette sout<strong>en</strong>ance, il vous sera <strong>de</strong>mandé une ou <strong>de</strong>ux démonstrations sur les 7<br />
exercices réalisés. Vous <strong>de</strong>vrez pour chacune expliquer le co<strong>de</strong> <strong>de</strong> l’exercice. Des<br />
1 Application Protocole Interface<br />
1
Université <strong>de</strong> CergyPontoise<br />
questions sont pour cela insérées dans ce sujet pour vous gui<strong>de</strong>r dans la compréh<strong>en</strong>sion<br />
<strong>du</strong> système <strong>uC</strong>/<strong>OS</strong>.<br />
Cette sout<strong>en</strong>ance <strong>de</strong>vra r<strong>en</strong>dre compte <strong>de</strong> la particularité <strong>du</strong> développem<strong>en</strong>t dans un<br />
cadre temps réel d’une part et embarqué d’autre part.<br />
Par ailleurs <strong>en</strong> tant que développeur d’applications temps réel au sein <strong>de</strong> l’équipe <strong>de</strong><br />
développem<strong>en</strong>t pédagogique <strong>du</strong> Départem<strong>en</strong>t Sci<strong>en</strong>ces Informatiques, vous pourrez si<br />
nécessaire r<strong>en</strong>dre compte <strong>de</strong>s problèmes techniques r<strong>en</strong>contrés, <strong>de</strong>s limites et contraintes<br />
<strong>de</strong> l’<strong>en</strong>vironnem<strong>en</strong>t <strong>de</strong> développem<strong>en</strong>t actuel, et <strong>de</strong>s év<strong>en</strong>tuels Buggs r<strong>en</strong>contrés à faire<br />
corriger par l’équipe <strong>de</strong> développem<strong>en</strong>t <strong>de</strong>s Outils d’exploitation.<br />
c. Environnem<strong>en</strong>t <strong>de</strong> développem<strong>en</strong>t<br />
Vous allez au cours <strong>de</strong> ces séances pr<strong>en</strong>dre connaissance <strong>de</strong> 2 <strong>en</strong>vironnem<strong>en</strong>ts <strong>de</strong><br />
développem<strong>en</strong>t selon que l’application que l’on cherche à implanter sera <strong>de</strong>stinée à une<br />
exécution sur PC ou à une exécution embarquée.<br />
L’<strong>en</strong>vironnem<strong>en</strong>t <strong>de</strong> développem<strong>en</strong>t sur PC est directem<strong>en</strong>t lié au langage <strong>de</strong><br />
programmation utilisé pour développer <strong>de</strong>s applications <strong>sous</strong> <strong>uC</strong><strong>OS</strong> : le langage C.<br />
Vous pourrez donc utiliser pour le développem<strong>en</strong>t <strong>de</strong>s programmes l’éditeur <strong>de</strong> votre<br />
choix.<br />
Le compilateur C est quand à lui soumis à quelques contraintes. En effet, les librairies<br />
<strong>de</strong> fonctions <strong>uC</strong>/<strong>OS</strong><strong>II</strong> disponibles à l’Université ont été développées et compilées avec<br />
BorlandC/C++ version 4.51 pour Windows. Ce compilateur payant n’est pas disponible à<br />
l’Université. Aussi l’<strong>OS</strong> atil été porté pour une version antérieure <strong>du</strong> compilateur<br />
Borland, la version TCPP1.01.<br />
L’<strong>en</strong>vironnem<strong>en</strong>t minimal <strong>de</strong> développem<strong>en</strong>t est l’utilisation d’un logiciel d’édition <strong>de</strong><br />
texte pour la programmation et le lancem<strong>en</strong>t <strong>de</strong>s comman<strong>de</strong>s <strong>de</strong> compilation par<br />
comman<strong>de</strong>s D<strong>OS</strong>.<br />
Vous pouvez selon les logiciels <strong>de</strong> votre PC utiliser un <strong>en</strong>vironnem<strong>en</strong>t <strong>de</strong> développem<strong>en</strong>t<br />
paramétré pour faire appel aux comman<strong>de</strong>s <strong>du</strong> compilateur (make, cc, asm…).<br />
Le compilateur est installé dans le répértoire c:\TOOLS\TCPP101\<br />
Si ce n’est pas le cas, décompresser l’archive prés<strong>en</strong>te sur<br />
http://wwwetis.<strong>en</strong>sea.fr/Members/bmiramond/Cours/M1/UEF5.html<br />
à cet emplacem<strong>en</strong>t.<br />
Vos répertoires <strong>de</strong> travail seront situés dans c:\SOFTWARE\UC<strong>OS</strong><strong>II</strong>\. Ce répertoire<br />
sera désigné dans la suite par $WORK_DIR.<br />
d. Les primitives utiles <strong>de</strong> la librairie <strong>uC</strong>/<strong>OS</strong><strong>II</strong><br />
Vous trouverez <strong>en</strong> annexe à la fin <strong>de</strong> ce docum<strong>en</strong>t les fonctions C principales <strong>de</strong> la<br />
librairie ucos_ii (API).<br />
Note : En cours <strong>de</strong> TP, vous pouvez <strong>de</strong>man<strong>de</strong>r un livre <strong>uC</strong>/<strong>OS</strong><strong>II</strong> disponible dans les armoires<br />
<strong>de</strong> la salle pour le détail <strong>de</strong> certains appels ou paramètres d’appel à l’API.<br />
2. Exercice 1 : Concurr<strong>en</strong>ce <strong>de</strong> tâches<br />
a. Un modèle <strong>de</strong> co<strong>de</strong><br />
Vous trouverez dans le répertoire $WORK_DIR\EX1_X86L\TCPP101\TEST les fichiers<br />
nécessaires à la compilation <strong>du</strong> premier exercice : Test.mak (Makefile), Maketest.bat<br />
(script).<br />
2
Université <strong>de</strong> CergyPontoise<br />
Pour lancer la compilation, vous <strong>de</strong>vez lancer le script Maketest.bat.<br />
L’affichage qui apparaît n’est pas complet, ce sera à vous <strong>de</strong> compléter le co<strong>de</strong> et <strong>de</strong><br />
compr<strong>en</strong>dre sa fonctionnalité.<br />
Vous trouverez pour cela dans l’annexe B le co<strong>de</strong> complet <strong>de</strong> l’application temps réel<br />
simple développée avec les fonctions <strong>de</strong> la librairie ucos_ii.<br />
L’objectif <strong>de</strong> ce premier exercice est tout d’abord <strong>de</strong> compr<strong>en</strong>dre la structure d’un<br />
programme <strong>sous</strong> cet <strong>en</strong>vironnem<strong>en</strong>t, puis d’analyser l’utilité <strong>de</strong>s fonctions <strong>uC</strong><strong>OS</strong>.<br />
Pour satisfaire au premier objectif, la première étape <strong>de</strong> ce TP est <strong>de</strong> recopier le co<strong>de</strong><br />
fourni <strong>en</strong> annexe dans le fichier test.c prés<strong>en</strong>t dans<br />
$WORK_DIR\EX1_X86L\TCPP101\SOURCE<br />
Au cours <strong>de</strong> l’écriture <strong>du</strong> co<strong>de</strong>, vous placerez <strong>de</strong>s comm<strong>en</strong>taires indiquant la<br />
fonctionnalité <strong>de</strong>s fonctions <strong>de</strong> l’<strong>OS</strong> <strong>en</strong> vous aidant <strong>de</strong> l’annexe A.<br />
D’autres fichiers sont déjà prés<strong>en</strong>ts dans ce répertoire comme Inclu<strong>de</strong>.h et Os_cfg.h.<br />
b. Analyse <strong>du</strong> co<strong>de</strong><br />
Après avoir correctem<strong>en</strong>t compilé le co<strong>de</strong> et réaliser son exécution, vous allez<br />
<strong>main</strong>t<strong>en</strong>ant procé<strong>de</strong>r aux modifications suivantes :<br />
Enlever l’appel à la fonction PCDosSaveReturn() dans la fonction <strong>main</strong>.<br />
Recompiler et exécuter. Que se passetil ? Expliquer pourquoi.<br />
En quoi l’utilisation <strong>de</strong> <strong>uC</strong><strong>OS</strong> sur PC estelle différ<strong>en</strong>te d’une utilisation sur plateforme<br />
embarquée ?<br />
3. Exercice 2 : Mesure <strong>de</strong> taille <strong>de</strong> pile d’exécution<br />
a. Compréh<strong>en</strong>sion <strong>de</strong> co<strong>de</strong><br />
Vous allez <strong>main</strong>t<strong>en</strong>ant dans le répertoire<br />
$WORK_DIR\EX2_x86l\TCPP101\<br />
Vous y retrouvez la même organisation que dans l’exemple précéd<strong>en</strong>t.<br />
Compiler le co<strong>de</strong> et exécuter l’application.<br />
Observer ce qui se passe. Id<strong>en</strong>tifier le problème.<br />
Vous allez <strong>main</strong>t<strong>en</strong>ant <strong>en</strong>trer dans le co<strong>de</strong> (répertoire SOURCE) et écrire la fonction<br />
d’affichage TaskStartDispInit() <strong>de</strong> manière à ce qu’un utilisateur compr<strong>en</strong>ne les<br />
données brutes affichées à l’écran. Vous <strong>de</strong>vez pour cela à partir <strong>du</strong> co<strong>de</strong> déjà prés<strong>en</strong>t<br />
compr<strong>en</strong>dre la nature <strong>de</strong>s informations affichées et vous inspirer <strong>du</strong> co<strong>de</strong> <strong>de</strong> l’exercice 1<br />
pour apporter <strong>de</strong>s indications à l’affichage.<br />
Cette application est composée <strong>de</strong> 9 tâches, que font chacune <strong>de</strong> ces tâches ?<br />
b. Analyse <strong>de</strong> comportem<strong>en</strong>t<br />
Cet exercice fait appel à la fonction <strong>OS</strong>TaskStkChk() qui réalise <strong>de</strong>s vérifications et <strong>de</strong>s<br />
mesures <strong>de</strong> taille <strong>de</strong> la pile d’exécution.<br />
L’analyse <strong>de</strong> pile d’exécution est primordiale <strong>en</strong> informatique embarqué et <strong>en</strong> temps réel<br />
lorsque l’on ne connaît pas <strong>de</strong> manière statique et déterministe la place mémoire utilisée<br />
par chaque tâche.<br />
Dans ce cas, une solution est d’allouer plus <strong>de</strong> place que nécessaire et <strong>de</strong> laisser <strong>uC</strong>/<strong>OS</strong><br />
<strong>II</strong> mesurer la pile réellem<strong>en</strong>t utilisée. Pour cela l’application doit être lancée<br />
3
Université <strong>de</strong> CergyPontoise<br />
suffisamm<strong>en</strong>t longtemps pour être représ<strong>en</strong>tative d’une exécution <strong>en</strong> <strong>en</strong>vironnem<strong>en</strong>t<br />
réel. Votre mesure finale doit pouvoir s’adapter à <strong>de</strong>s variations non prévues <strong>de</strong><br />
l’<strong>en</strong>vironnem<strong>en</strong>t. Une marge <strong>de</strong> 15 à 20 % est donc nécessaire.<br />
Dans les applications critiques, une marge <strong>de</strong> 100% est indisp<strong>en</strong>sable.<br />
Après mesure, adapter la taille <strong>de</strong> pile <strong>de</strong> chaque tâche et vérifier le bon comportem<strong>en</strong>t<br />
<strong>du</strong> système. Que se passetil si la taille <strong>de</strong> pile allouée est insuffisante ?<br />
La fonction <strong>OS</strong>TaskStckChk() rempli l’espace réservé pour la pile <strong>de</strong> valeurs nulles à<br />
la création <strong>de</strong> chaque tâche.<br />
La vérification et la mesure <strong>de</strong> la taille <strong>de</strong> pile comm<strong>en</strong>ce au bas <strong>de</strong> la pile (pointeur<br />
Bottom Of Stack : B<strong>OS</strong>). En avançant dans la pile le pointeur est incrém<strong>en</strong>té jusqu’à<br />
trouver une <strong>en</strong>trée non nulle. Le compteur donne le nombre d’emplacem<strong>en</strong>ts utilisés.<br />
Cette vérification pr<strong>en</strong>ds <strong>du</strong> temps et n’est donc utilisée qu’<strong>en</strong> cours <strong>de</strong> développem<strong>en</strong>t<br />
et d’analyse <strong>de</strong> co<strong>de</strong>. Une fois implantée sur cible, ces vérifications sont supprimées.<br />
A vous <strong>de</strong> mesurer le coût <strong>en</strong> temps d’exécution <strong>de</strong> cette vérification <strong>en</strong> utilisant<br />
successivem<strong>en</strong>t les fonctions PC_ElapsedStart() et PC_ElapsedStop() (cf. Annexe).<br />
c. Communications <strong>en</strong>tre tâches<br />
<strong>uC</strong><strong>OS</strong> permet évi<strong>de</strong>mm<strong>en</strong>t <strong>de</strong> faire communiquer <strong>de</strong>s tâches <strong>en</strong>tre elles, par exemple <strong>en</strong><br />
<strong>en</strong>voyant <strong>de</strong>s messages par l’intermédiaire d’une boîte aux lettres (mailbox).<br />
Nous allons ici faire communiquer les tâches 4 et 5 : T4 <strong>en</strong>voie un message à T5 et T5<br />
répondra à T4 <strong>en</strong> lui <strong>en</strong>voyant un Ack(nowledge).<br />
Pour cela nous avons besoin <strong>de</strong> créer 2 mailboxes qui permett<strong>en</strong>t <strong>de</strong> cont<strong>en</strong>ir un (et un<br />
seul) pointeur sur une donnée. Cette donnée est spécifique à l’application et doit être<br />
définie <strong>en</strong> commun par l’expéditeur et le <strong>de</strong>stinataire.<br />
Les étapes pour faire communiquer T4 et T5 sont simples :<br />
• Déclarer 2 mailboxes <strong>en</strong> variables globales. Ce sont <strong>de</strong>s pointeurs sur<br />
<strong>de</strong>s <strong>OS</strong>_EVENT<br />
• Créer les 2 mailboxes par la fonction <strong>OS</strong>MboxCreate (void *) qui<br />
retourne un pointeur sur les structures mailbox<br />
• Dans les fonctions T4 et T5 utiliser les fonctions d’<strong>en</strong>voie<br />
<strong>OS</strong>MboxPost() et d’att<strong>en</strong>te <strong>OS</strong>MboxP<strong>en</strong>d() pour que T4 <strong>en</strong>voie un<br />
caractère qui change à chaque Ack reçu <strong>de</strong> ‘A’ à ‘Z’ <strong>de</strong> manière<br />
circulaire. T5 affichera ce caractère.<br />
4. Exercice 3 : Analyse <strong>de</strong> temps d’exécution<br />
a. Mesure <strong>de</strong> temps d’exécution<br />
Les sources <strong>de</strong> l’exercice 3 sont dans $WORK_DIR\EX3_x86L\TCPP101\SOURCE.<br />
L’objectif <strong>de</strong> cet exercice est inverse à celui <strong>de</strong> l’exercice précéd<strong>en</strong>t.<br />
La fonction d’affichage TaskStartDispInit() est écrite. Elle indique différ<strong>en</strong>tes<br />
mesures pour les tâches <strong>de</strong> l’application.<br />
Combi<strong>en</strong> <strong>de</strong> tâches compos<strong>en</strong>t l’application. Quelles sont les mesures que doit<br />
afficher l’exécution.<br />
Votre objectif est d’utiliser les comman<strong>de</strong>s <strong>uC</strong><strong>OS</strong> pour donner ces mesures à<br />
l’affichage <strong>de</strong> données actuellem<strong>en</strong>t constantes.<br />
4
Université <strong>de</strong> CergyPontoise<br />
<strong>uC</strong><strong>OS</strong> est un <strong>OS</strong> ouvert au s<strong>en</strong>s ou le co<strong>de</strong> source <strong>de</strong> l’<strong>OS</strong> est fourni et modifiable<br />
par les utilisateurs.<br />
Nous allons ici utiliser cette propriété pour réaliser nos mesures <strong>en</strong> ajoutant cette<br />
fonctionnalité par l’intermédiaire <strong>de</strong>s fonctions appelées Hook.<br />
9 fonctions Hook exist<strong>en</strong>t. Nous aurons pour notre cas uniquem<strong>en</strong>t besoin <strong>de</strong><br />
modifier la fonction <strong>OS</strong>TaskSwHook.<br />
Celleci est appellé par l’<strong>OS</strong> au mom<strong>en</strong>t <strong>de</strong> chaque changem<strong>en</strong>t <strong>de</strong> contexte.<br />
Au mom<strong>en</strong>t <strong>de</strong> son appel, le pointeur global <strong>OS</strong>TCBCur pointe sur le TCB <strong>de</strong> la<br />
tâche <strong>en</strong> cours d’exécution, alors que <strong>OS</strong>TCBHighRdy pointe sur le TCB <strong>de</strong> la<br />
nouvelle tâche plus prioritaire. Nous n’utiliserons ici que le premier pointeur.<br />
Le champ <strong>OS</strong>TCBExtPtr <strong>de</strong> la structure TCB conti<strong>en</strong>t la structure <strong>de</strong> donnée qui lui<br />
est passée <strong>en</strong> paramètre à la création par la fonction <strong>OS</strong>TaskCreateExt().<br />
C’est cette structure <strong>de</strong> donnée que nous allons utiliser pour mémoriser les<br />
informations dynamiques sur chaque tâche.<br />
Le principe est donc le suivant<br />
• Déclaration d’une structure <strong>de</strong> données TASK_USER_DATA<br />
mémorisant les informations mesurées (déjà écrite <strong>en</strong> tête <strong>de</strong><br />
fichier). Mettre <strong>de</strong>s comm<strong>en</strong>taires pour chaque champ <strong>de</strong> la<br />
structure.<br />
• Passage <strong>de</strong> cette structure <strong>de</strong> données <strong>en</strong> 8 e paramètre <strong>de</strong> la<br />
fonction <strong>OS</strong>TaskCreateExt() jusqu’à prés<strong>en</strong>t laissé à un pointeur<br />
vi<strong>de</strong>.<br />
• Mise à jour <strong>de</strong>s champs <strong>de</strong> cette structure par la fonction<br />
<strong>OS</strong>TaskSwHook à chaque changem<strong>en</strong>t <strong>de</strong> contexte.<br />
• Le temps d’exécution <strong>de</strong> chaque tâche est obt<strong>en</strong>u <strong>en</strong> lancant la<br />
fonction PC_ElapsedStart() à la fin <strong>de</strong> la fonction<br />
<strong>OS</strong>TaskSwHook() et <strong>en</strong> récupérant un INT16U <strong>en</strong> valeur <strong>de</strong><br />
retour <strong>de</strong> la fonction PC_ElapsedStop().<br />
Réaliser ces modifications.<br />
Quelle est la tâche la plus longue. La priorité <strong>de</strong>s tâches appar<strong>en</strong>te estelle conforme<br />
à celle donnée à leur création ?<br />
Que fait la tâche T1 par rapport aux autres tâches ?<br />
Pourquoi utilisetelle un autre mécanisme <strong>de</strong> communication que celui <strong>de</strong> la boîte<br />
aux lettres utilisé précé<strong>de</strong>mm<strong>en</strong>t ?<br />
5. Exercice 4 : Emulation d’un jeu d’instructions à virgule<br />
flottante<br />
a. Architecture cible<br />
Rechercher sur le web l’architecture <strong>du</strong> processeur <strong>de</strong> votre machine.<br />
Donner le schéma <strong>en</strong> bloque <strong>du</strong> processeur.<br />
Disposetelle d’une unité <strong>de</strong> calcul <strong>en</strong> virgule flottante ?<br />
Comm<strong>en</strong>t réaliseton <strong>de</strong>s calculs <strong>en</strong> virgule flottante dans le cas ou le processeur<br />
n’<strong>en</strong> dispose pas.<br />
5
Université <strong>de</strong> CergyPontoise<br />
6. Conclusion<br />
Dé<strong>du</strong>iser <strong>de</strong> cette expéri<strong>en</strong>ce un patron (modèle) général d’écriture d’applications <strong>sous</strong><br />
<strong>uC</strong><strong>OS</strong>.<br />
Ce patron doit être indép<strong>en</strong>dant <strong>de</strong> l’application visée et doit <strong>en</strong>suite pouvoir être rempli <strong>de</strong><br />
manière à répondre aux besoins <strong>de</strong> l’application.<br />
Lancer à nouveau un <strong>de</strong> vos exécutables. Au cours <strong>de</strong> son exécution et sans l’interrompre,<br />
lancer égalem<strong>en</strong>t le gestionnaire <strong>de</strong> tâches <strong>de</strong> Windows. Quelle est l’utilisation <strong>du</strong><br />
processeur ? Quelle l’utilisation CPU occupé par le co<strong>de</strong> <strong>uC</strong><strong>OS</strong> ? Que dé<strong>du</strong>isezvous <strong>de</strong> ces<br />
mesures <strong>du</strong> fonctionnem<strong>en</strong>t <strong>de</strong> <strong>uC</strong>/<strong>OS</strong><strong>II</strong> <strong>sous</strong> un <strong>en</strong>vironnem<strong>en</strong>t PC.<br />
7. Annexe A : Fonctions <strong>uC</strong>/<strong>OS</strong><strong>II</strong><br />
PC_VectSet(() Fixe le vecteur d'interruption: premier paramètre<br />
est le numéro d'interruption, second paramètre<br />
est le pointeur sur le handler d'interruption.<br />
PC_SetTickRate() Modifie l'unité <strong>de</strong> mesure temporel <strong>de</strong> l'<strong>OS</strong><br />
(standard: 18.20648Hz)<br />
<strong>OS</strong>MboxP<strong>en</strong>d Susp<strong>en</strong>d une tâche <strong>en</strong> att<strong>en</strong>te <strong>de</strong> message (dans<br />
une boîte aux lettres) tant qu'elle ne l'a pas reçu.<br />
<strong>OS</strong>MboxPost() Envoie un message<br />
<strong>OS</strong>Init() Doit être appelé avant toute autre fonction <strong>de</strong><br />
l’<strong>OS</strong>. Elle créée 2 tâches : 1 Tâche Idle et 1<br />
Tâche statistique<br />
<strong>OS</strong>SemCreate() Crée un sémaphore et retourne un pointeur sur<br />
une structure <strong>de</strong> type <strong>OS</strong>_EVENT<br />
<strong>OS</strong>TaskCreate() Création <strong>de</strong> tâche<br />
Argum<strong>en</strong>ts : pointeur sur le co<strong>de</strong> <strong>de</strong> la tâche,<br />
pointeur sur les données d’initialisation,<br />
pointeur sur la pile utilisée, taille <strong>de</strong> la pile,<br />
priorité <strong>de</strong> la tâche<br />
<strong>OS</strong>Start() Lance l’<strong>OS</strong> : création <strong>de</strong>s structures <strong>de</strong> données,<br />
lancem<strong>en</strong>t <strong>du</strong> sche<strong>du</strong>ler<br />
<strong>OS</strong>StatInit() Initialise les statistiques relatives à <strong>uC</strong>/<strong>OS</strong><strong>II</strong>.<br />
PC_DispChar() Affiche un caractère quelque part dans une<br />
f<strong>en</strong>être D<strong>OS</strong> (position <strong>en</strong> premier et second<br />
argum<strong>en</strong>t, caractère à afficher <strong>en</strong> troisième et<br />
couleurs <strong>en</strong> <strong>de</strong>rnier)<br />
<strong>OS</strong>TimeDly retar<strong>de</strong> une tâche <strong>de</strong> N unités <strong>de</strong> mesure<br />
temporel (cf PC_SetTickRate()), N étant passé<br />
6
Université <strong>de</strong> CergyPontoise<br />
<strong>en</strong> argum<strong>en</strong>t.<br />
<strong>OS</strong>TimeDlyHMSM(int,int,int,int) même fonctionnalité que <strong>OS</strong>TimeDly mais <strong>en</strong><br />
heures/minutes/secon<strong>de</strong>s/millisecon<strong>de</strong>s<br />
<strong>OS</strong>SemP<strong>en</strong>d(*<strong>OS</strong>_EVENT, INT16U, INT8U) <strong>Prise</strong> <strong>de</strong> semaphore : premier paramètre est un<br />
pointeur sur l’évènem<strong>en</strong>t, 2 e paramètre est un<br />
timeout, 3 e paramètre est un co<strong>de</strong> d'erreur :<br />
<strong>OS</strong>_NO_ERR si le sémaphore est dispo<br />
<strong>OS</strong>_TIMEOUT si le sémaphore n'est pas relâché<br />
avant le timeout spécifié<br />
<strong>OS</strong>_ERR_EVENT_TYP si le premier argum<strong>en</strong>t<br />
ne pointe pas vers un sémaphore<br />
<strong>OS</strong>_ERR_PEVENT_NULL si le premier<br />
argum<strong>en</strong>t est NULL.<br />
<strong>OS</strong>emPost(*<strong>OS</strong>_EVENT) Relâche le sémaphore<br />
<strong>OS</strong>TimeDly(int) La tâche s’<strong>en</strong>dort (état WAITING) p<strong>en</strong>dant le<br />
temps donné <strong>en</strong> paramètre. (Une valeur <strong>de</strong> 1<br />
signifie 1 cycle d’horloge système)<br />
PC_DispClrScr() Fonction <strong>de</strong> réinitialisation <strong>de</strong> l’écran (D<strong>OS</strong>)<br />
PC_DispStr() Affiche une chaîne <strong>de</strong> caractère quelque part à<br />
l’écran<br />
PC_D<strong>OS</strong>SaveReturn() Sauvegar<strong>de</strong> l'<strong>en</strong>vironnem<strong>en</strong>t D<strong>OS</strong> avant le retour<br />
<strong>en</strong> mo<strong>de</strong> console<br />
PC_D<strong>OS</strong>Return Permet <strong>de</strong> rev<strong>en</strong>ir <strong>en</strong> mo<strong>de</strong> D<strong>OS</strong> (utiliser au<br />
préalable PC_D<strong>OS</strong>SaveReturn() pour<br />
sauvegar<strong>de</strong>r les registres importants <strong>du</strong><br />
<strong>OS</strong>TaskCreateExt(*<strong>OS</strong>_STK,* struct,<br />
*<strong>OS</strong>_STK,int,int,*<strong>OS</strong>_STK,sk_size)<br />
processeur pour permettre ce retour à D<strong>OS</strong>).<br />
Version ét<strong>en</strong><strong>du</strong>e <strong>de</strong> <strong>OS</strong>TaskCreateExt() pr<strong>en</strong>ant<br />
<strong>en</strong> plus les argum<strong>en</strong>ts suivants:<br />
id <strong>de</strong> la tâche<br />
l'adresse <strong>du</strong> bas <strong>de</strong> la pile<br />
la taille <strong>de</strong> la pile alloué pour la tâche (<strong>en</strong><br />
nombre d'élém<strong>en</strong>ts: INT8U, INT16U par<br />
exemple suivant le type que pr<strong>en</strong>d <strong>OS</strong>_STK)<br />
un pointeur vers une structure <strong>de</strong> données (peut<br />
cont<strong>en</strong>ir le temps que met une tâche pour<br />
s'exécuter, le cont<strong>en</strong>u <strong>de</strong> registres virgule<br />
flottante...)<br />
une option <strong>de</strong> partage <strong>en</strong>tre tâches :<br />
<strong>OS</strong>_TASK_OPT_STK_CHK spécifie quel<br />
contrôle <strong>de</strong> pile est permis pour la tâche<br />
<strong>OS</strong>_TASK_OPT_STK_CLR spécifie quelle pile<br />
doit être réinitialisée<br />
<strong>OS</strong>_TASK_OPT_SAVE_FP spécifie quels<br />
registres flottant sont sauvés.<br />
Cette fonction r<strong>en</strong>voie:<br />
soit <strong>OS</strong>_NO_ERR <strong>en</strong> cas <strong>de</strong> succès<br />
soit <strong>OS</strong>_PRIO_EXIST si la priorité <strong>de</strong>mandée<br />
7
Université <strong>de</strong> CergyPontoise<br />
existe déjà<br />
<strong>OS</strong>_NO_MORE_TCB si mucos n'a plus <strong>de</strong><br />
<strong>OS</strong>_TCB à affecter.<br />
Rem: certains indices <strong>de</strong> priorité sont réservés à<br />
certains fonctions système mucos: 0,1,2,3,<br />
<strong>OS</strong>_LOWEST_PRIO3, <strong>OS</strong>_LOWEST_PRIO2<br />
<strong>OS</strong>_ENTER_CRITICAL() active et désactive les interruptions <strong>du</strong><br />
processeur.<br />
<strong>OS</strong>MboxCreate() crée une boîte à lettres<br />
PC_GetKey() R<strong>en</strong>voie vrai ou faux <strong>en</strong> fonction <strong>de</strong> la touche<br />
tapée sur le clavier et celle spécifiée <strong>en</strong><br />
argum<strong>en</strong>t <strong>de</strong> cette fonction.<br />
PC_ElapsedInit() Initialise le processus <strong>de</strong> mesure <strong>de</strong> temps<br />
PC_ElapsedStart() Démarrage <strong>de</strong> la mesure <strong>de</strong> temps d’exécution<br />
d’une portion <strong>de</strong> co<strong>de</strong><br />
PC_ElapsedStop() Fin <strong>de</strong> la mesure <strong>de</strong> temps<br />
<strong>OS</strong>TaskStkChk() R<strong>en</strong>voie <strong>de</strong>s informations relatives à la pile<br />
d'exécution:<br />
premier argum<strong>en</strong>t: indice <strong>de</strong> priorité <strong>de</strong> la tâche<br />
second argum<strong>en</strong>t: pointeur sur la donnée <strong>de</strong> type<br />
<strong>OS</strong>_STK_DATA cont<strong>en</strong>ant les champs suivants:<br />
INT32U <strong>OS</strong>Free (nb d'octets dispos sur la pile)<br />
INT32U <strong>OS</strong>Used (nb d’octets utilisés par la<br />
pile)<br />
<strong>OS</strong>QP<strong>en</strong>d Susp<strong>en</strong>d une tâche <strong>en</strong> att<strong>en</strong>te <strong>de</strong> message (d'une<br />
file d’att<strong>en</strong>te) tant qu'elle ne l'a pas reçu.<br />
<strong>OS</strong>QPost Envoie un message à une autre tâche au moy<strong>en</strong><br />
d'une file d’att<strong>en</strong>te<br />
PC_GetDateTime() Donne l'heure et la date <strong>du</strong> PC<br />
8
Université <strong>de</strong> CergyPontoise<br />
8. Annexe B : Co<strong>de</strong> <strong>de</strong> l’exercice 1<br />
/*<br />
****************************************************************************************<br />
* <strong>uC</strong>/<strong>OS</strong><strong>II</strong><br />
*<br />
*****************************************************************************************<br />
*/<br />
#inclu<strong>de</strong> "inclu<strong>de</strong>s.h"<br />
/*<br />
****************************************************************************************<br />
* CONSTANTS<br />
******************************************************************************************<br />
*/<br />
#<strong>de</strong>fine TASK_STK_SIZE 512 /* Size of each task's stacks (# of WORDs) */<br />
#<strong>de</strong>fine N_TASKS 10 /* Number of id<strong>en</strong>tical tasks */<br />
/*<br />
******************************************************************************************<br />
* VARIABLES<br />
******************************************************************************************<br />
*/<br />
<strong>OS</strong>_STK TaskStk[N_TASKS][TASK_STK_SIZE]; /* Tasks stacks */<br />
<strong>OS</strong>_STK TaskStartStk[TASK_STK_SIZE];<br />
char TaskData[N_TASKS]; /* Parameters to pass to each task */<br />
<strong>OS</strong>_EVENT *RandomSem;<br />
/*<br />
******************************************************************************************<br />
* FUNCTION PROTOTYPES<br />
******************************************************************************************<br />
*/<br />
void Task(void *data); /* Function prototypes of tasks */<br />
void TaskStart(void *data); /* Function prototypes of Startup task */<br />
static void TaskStartCreateTasks(void);<br />
static void TaskStartDispInit(void);<br />
static void TaskStartDisp(void);<br />
/*<br />
******************************************************************************************<br />
* MAIN<br />
******************************************************************************************<br />
*/<br />
void <strong>main</strong> (void)<br />
{<br />
PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); /* */<br />
<strong>OS</strong>Init(); /* */<br />
PC_D<strong>OS</strong>SaveReturn(); /* */<br />
PC_VectSet(<strong>uC</strong><strong>OS</strong>, <strong>OS</strong>CtxSw); /* */<br />
RandomSem = <strong>OS</strong>SemCreate(1); /* */<br />
<strong>OS</strong>TaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE 1], 0);<br />
<strong>OS</strong>Start(); /* */<br />
9
Université <strong>de</strong> CergyPontoise<br />
}<br />
/*<br />
******************************************************************************************<br />
* STARTUP TASK<br />
******************************************************************************************<br />
*/<br />
void TaskStart (void *pdata)<br />
{<br />
#if <strong>OS</strong>_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */<br />
<strong>OS</strong>_CPU_SR cpu_sr;<br />
#<strong>en</strong>dif<br />
char s[100];<br />
INT16S key;<br />
}<br />
pdata = pdata; /* Prev<strong>en</strong>t compiler warning */<br />
TaskStartDispInit(); /* Initialize the display */<br />
<strong>OS</strong>_ENTER_CRITICAL();<br />
PC_VectSet(0x08, <strong>OS</strong>TickISR); /* */<br />
PC_SetTickRate(<strong>OS</strong>_TICKS_PER_SEC); /* */<br />
<strong>OS</strong>_EXIT_CRITICAL();<br />
<strong>OS</strong>StatInit(); /* Initialize <strong>uC</strong>/<strong>OS</strong><strong>II</strong>'s statistics */<br />
TaskStartCreateTasks(); /* */<br />
for (;;) {<br />
TaskStartDisp(); /* Update the display */<br />
}<br />
if (PC_GetKey(&key) == TRUE) { /* See if key has be<strong>en</strong> pressed */<br />
if (key == 0x1B) { /* Yes, see if it's the ESCAPE key */<br />
PC_D<strong>OS</strong>Return(); /* */<br />
}<br />
}<br />
<strong>OS</strong>CtxSwCtr = 0; /* Clear context switch counter */<br />
<strong>OS</strong>TimeDlyHMSM(0, 0, 1, 0); /* */<br />
/*<br />
***************************************************************************************<br />
* CREATE TASKS<br />
*****************************************************************************************<br />
*/<br />
static void TaskStartCreateTasks (void)<br />
{<br />
INT8U i;<br />
for (i = 0; i < N_TASKS; i++) { /* Create N_TASKS id<strong>en</strong>tical tasks */<br />
TaskData[i] = '0' + i; /* Each task will display its own letter */<br />
<strong>OS</strong>TaskCreate(Task, (void *)&TaskData[i], &TaskStk[i][TASK_STK_SIZE 1], i + 1);<br />
10
Université <strong>de</strong> CergyPontoise<br />
}<br />
}<br />
/*<br />
******************************************************************************************<br />
* TASKS<br />
******************************************************************************************<br />
*/<br />
void Task (void *pdata)<br />
{<br />
INT8U x;<br />
INT8U y;<br />
INT8U err;<br />
}<br />
for (;;) {<br />
<strong>OS</strong>SemP<strong>en</strong>d(RandomSem, 0, &err); /* Acquire semaphore to perform random numbers */<br />
x = random(80); /* Find X position where task number will appear */<br />
y = random(16); /* Find Y position where task number will appear */<br />
<strong>OS</strong>SemPost(RandomSem); /* Release semaphore */<br />
/* Display the task number on the scre<strong>en</strong> */<br />
PC_DispChar(x, y + 5, *(char *)pdata, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);<br />
<strong>OS</strong>TimeDly(1); /* Delay 1 clock tick */<br />
}<br />
11