Le support de cours est disponible en ligne.
Nous rappelons également l’URL du cours sur RT-POSIX, qui pourrait vous être utile.
Notes:
– le TP devra se faire sur la même machine virtuelle que le TP RT-POSIX. Ou celle disponible sur ce lien>>
– pour exécuter le code, il faut être root et forcer l’exécution sur un coeur:
$sudo taskset -c 0 ./fault_detection_app
TP sur les erreurs temporelles
Les objectifs du TP sont:
- vous faire implémenter un watchdog logiciel sous RT-POSIX pour détecter des dépassements d’échéance
- vous faire implémenter une stratégie de recouvrement par passage en mode dégradé
Cas d’étude
Nous allons considérer un véhicule dont la vitesse doit être asservie à une vitesse V_cmd. Ce véhicule est équipé d’un capteur de position. L’application que nous considérons est une application de contrôle de la trajectoire du véhicule. Cette application est constituée de quatre tâches fonctionnelles:
- pos_sensor : cette tâche récupère la position courante du véhicule.
- speed_cmp : à partir d’un tableau de positions successives dont on connaît la fréquence de mesure, cette tâche calcule la vitesse du véhicule.
- obst_detec : cette tâche récupère la distance qui sépare le véhicule d’éventuels obstacles sur sa trajectoire.
- traject_ctrl : cette tâche contrôle la trajectoire du véhicule en calculant les commandes à envoyer aux moteurs en fonction (i) de l’évolution de la vitesse, et (ii) de la présence d’obstacles sur la trajectoire.
Paramètres d’ordonnancement
L’ordonnancement considéré est RMS, et nous considérerons l’hypothèse deadline=période. Les Période des tâches sont :
- pos_sensor : 100 ms
- speed_cmp : 1000 ms
- obst_detec : 50 ms
- traject_ctrl : 2000 ms
PARTIE 1 : dépassement d’échéance
Nous vous fournissons le code de l’exemple ci-dessus. Dans le code fourni, la détection des dépassements d’échéance n’est pas implémentée. Seul le code correspondant au mode initial est fourni.
Cette archive contient les fichiers sources suivants:
- main.c/.h: creation et initialisation des tâches fonctionnelles
- threads_dispatch.c/.h: ensemble de fonctions pour l’implémentation de tâches périodiques
- wdlibs.c/.h: ensemble de fonctions pour l’implémentation de la tâche watchdog
- functions.c: code des fonctions de calcul/contrôle des tâches
- types.h: définition des types utilisés dans main.c, threads_dispatch.c, et wdlib.c
- periods.h: macros #define pour les périodes des tâches
Nous vous demandons ici de modifier le code fourni pour implémenter un watchdog logiciel qui se chargera de détecter qu’une tâche dépasse son échéance. Nous suggérons l’implémentation suivante :
- Au début de son exécution, une tâche fonctionnelle arme un timer auquel est associé un signal. A la fin de son exécution, la tâche fonctionnelle désarme ce timer. Un signal sig_watchdog doit être associé au timer de sorte que si il expire, l’OS émet ce signal.
- Une tâche watchdog de très forte priorité attend sur la réception du signal sig_watchdog. Si toutes les tâches fonctionnelles terminent leurs travaux avant leurs échéances, le timer est désarmé et la tâche watchdog ne se réveille pas. Au contraire, si (au moins) une tâche fonctionnelle dépasse son échéance alors la tâche watchdog se réveillera. Reste à savoir laquelle, ou lesquelles pour journaliser cette information …
Questions préliminaires : En relisant le code dans la partie main.c et fonction.c, déterminer les paramètres WCETs des différentes tâches.
Indiquez ensuite pour l’ordonnancement choisi les défaillances que vous pourriez observer. Que pouvez vous dire d’un point de vu ordonnancement ?
Que se serait il passé si speed_cmp avait eu un temps d’exécution pire cas multiplié par 10 et traject_ctrl ait vu le sien divisé par 10 ?
Exercice 1 : modifiez le code fourni pour implémenter le mécanisme décrit ci-dessus. En cas de dépassement d’échéance, affichez l’identifiant de la tâche défaillante.
Indications : les modifications à apporter se limitent au contenu du fichier wdlib.c. Les commentaires dans le code visent à vous aider à compléter ce fichier. Les fonctions définis dans wdlib.c sont utilisés dans main.c et threads_dispatch.c. Le types de données sont définis dans le fichier types.h. Pour modifier les temps d’exécution des tâches (cela ne devrait pas être nécessaire), voir le fichier functions.c. Pour tester votre code, lancer le sur un unique cpu en utilisant taskset -c0 ./prg. N’oubliez pas aussi de passer en mode superutilisateur (sudo ou su ).
Voici la liste des fonctions de (RT-)POSIX dont vous pourriez avoir besoin. sigwaitinfo, timer_create, timer_settime, timer_delete, sigemptyset, et sigaddset. Vous pouvez utiliser les signaux temps réel (voir le cours sur RT-POSIX) s’ils sont supportés.
Exercice 2 :
- Modifiez la signature et le contenu de void wd_recovery () de sorte de pouvoir afficher le PID du thread ayant dépassé son échéance
- Modifiez la fonction wd_recovery en utilisant pthread_cancel() pour retirer la tâche du lot de tâche à ordonnancer.
Le corrigé de ce TP est disponible en ligne.
PARTIE 2 : modes de fonctionnement (pas couverte dans la séance de TP).
Vous allez maintenant implémenter un mécanisme de tolérance aux fautes basé sur la notion de mode de fonctionnement vu en cours.
Nous allons considérer trois modes de fonctionnement :
- le mode nominal : mode initial du système et qui correspond au mode dans lequel la vitesse d’asservissement du véhicule est la plus grande.
- un mode dégradé : mode dans lequel doit passer le système en cas de détection de dépassements d’échéance. Le but est de diminuer la fréquence des tâches, ainsi que la vitesse d’asservissement du véhicule. On divisera la fréquence de chaque tâche par 2 et la vitesse du véhicule d’asservissement du véhicule par 3.
- un mode d’arrêt d’urgence : mode dans lequel doit passer le système si (i) un obstacle se trouve à une distance qui met en péril le système, ou (ii) si on continue de détecter des dépassements d’échéance alors qu’on n’est dans le mode dégradé. Dans ce mode, les tâches pos_sensor, speed_cmp, traject_ctrl sont désactivées. Le mode nominal est réactivé par une commande utilisateur.
Exercice : implémentez un mécanisme de tolérance aux fautes s’appuyant sur la notion de mode de fonctionnement dégradé vu en cours.
Indications: voici les contraintes que nous imposons :
1 – le changement de mode se produit sur occurrence d’un dépassement d’échéance, il est donc déclenché à partir du handler de dépassement d’échéance identifié par .. dans le code fourni.
2 – le comportement fonctionnel doit conserver la propriété suivante : la valeur de vitesse calculée dans le mode nominal est V_cmd. La valeur calculée dans le mode dégradé est V_cmd/3. Hormis à l’initialisation (vitesse=0) on ne doit pas voir d’autres valeurs de vitesses s’afficher.
Dans le code, V_cmd est identifié avec la variable speed_cmd dans le fichier functions.c de l’archive.
PARTIE 3 : Recouvrement
Exercice : complétez votre solution pour revenir au mode nominal après 3 hyper-périodes dans le mode dégradé.