TP4 Temps Réel :
Ordonnanceur Arduino
L'objectif de ce TP est de faire un ordonnanceur minimaliste
de processus pour Arduino.
- On ne se servira pas de Lustre.
- La liste des processus ne change pas au cours du temps.
- Les processus utilisent 100% du temps CPU.
Intallez les paquets gcc-avr et arduino et l'environnement du TP :
GET http://perso.univ-lyon1.fr/thierry.excoffier/COURS/COURS/TEMPS_REEL/tp4.tar.gz | zcat | tar -xvf -
Tout ce dont vous avez besoin est dans main.c :
- Pour lancer l'exécution sur Arduino : make
Cela ne fera rien tant que vous n'aurez pas écrit l'ordonnanceur...
- Les fonctions blink_led1, blink_led2,
ephemere, incremente et check
définissent ce qu'exécutent les processus.
- La variable tasks définit la liste des processus
à faire fonctionner ainsi que l'endroit ou est stockée la
pile du processus.
- ISR(TIMER0_COMPA_vect) est l'ordonnanceur.
On ne peut pas changer son nom.
-
La fonction sched_init() programme une horloge
pour qu'elle envoit une interruption à intervalle régulier
(documentation).
Algorithme de l'ordonnanceur :
- Quand l'ordonnanceur est appelé,
il fonctionne avec la pile du processus interrompu.
Sauf la première fois bien sûr car il est dans la boucle infinie
du main().
- L'ordonnanceur doit sauvegarder tous les registres
du processeur, sinon il ne pourra pas redémarrer la
tâche avec le même état : SAVE_CONTEXT().
Cette sauvegarde est faite dans la pile du processus.
- Pour suspendre la tâche courante, il suffit de sauver
le pointeur de pile nommé SP dans le bon stack_pointer.
- On choisit ensuite la tâche suivante qui aura le CPU,
le plus simple est de prendre la suivante.
- On stocke le pointeur de pile de la tâche à redémarrer
dans SP.
- Deux cas suivant que la tâche ait été démarrée ou pas,
c'est indiqué par l'attribut state :
- Si elle est déjà démarrée :
- on récupère les registres du processeur de la
tâche en exécutant RESTORE_CONTEXT()
- Si c'est sa première fois :
- On indique qu'elle est démarré.
- On active les interruptions avec sei().
- On fait un appel classique à la fonction.
- Quand la fonction ordonnanceur (le gestion d'interruption)
se termine, elle utilise l'adresse
de retour qui est dans la pile et donc redémarre
le bon processus.
Votre travail :
- Faire l'ordonnanceur indiqué.
- La led jaune doit clignoter 3*+ vite que la led rouge.
- L'afficheur 8 segments s'allume car il y a des
zones critiques non protégées.
- Décommenter la tâche ephemere,
après le démarrage des leds, on entend un son saccadé,
pourquoi ?
- Le son s'arrête quand la tâche ephemere se termine,
mais les leds aussi, corriger ce bug
de la manière la plus simple possible,
mais sans gaspiller de temps CPU.
- Le clignotement des leds accélère : pourquoi ?
- Dans quel cas la correction du bug en a entraîné un autre,
mais dont la probabilité de déclenchement est très faible ?
Si vous n'avez pas de bug, expliquez comment vous l'avez évité.
N'essayez pas de le corriger.
- Protégez la section critique avec cli() et sei().
N'utilisez pas le paramètre des fonctions get_mutex
et release_mutex.
Vérifiez que l'afficheur 7 segments ne clignote plus.
- Dans la réalité, les processus utilisateurs ne peuvent suspendre
les interruptions pour se protéger.
Donc, utilisez maintenant le paramètre mutex et
ne mettez le cli() et sei() que
dans la fonction get_mutex.
- Avec cette solution, on perd du temps CPU à attendre
la libération du verrou : la solution du pauvre est de mettre
le quantum de temps à 0 (au lieu de 255)
quand on doit attendre le verrou.
La durée du quantum est définie par OCR0A.
- Si vous avez le temps, vous faites une solution plus propre...
Pour rendre ce TP, je veux un simple fichier texte sans aucun formatage
répondant aux questions en inserrant les bouts de codes directement
dans vos réponses.
Donc pas de PDF ou Doc, du RST si vous voulez.