Ministère de l’Enseignement Supérieur et de la Recherche Scientifique وزارة التعليـم العالي و البحث العلمي Université de Carthage جامعـة قرطاج Ecole Nationale d’Ingénieurs de Carthage المدرسـة الوطنية للمهندسين بقرطاج Gestion d'un distributeur automatique de billets par FreeRTOS On désire concevoir les tâches FreeRTOS pour la gestion des échanges de flux de données lors d'un retrait par carte bancaire. Le diagramme d'interdépendances des tâches est illustré dans la figure ci-dessous. Le porteur introduit sa carte bancaire dans le DAB. Après la lecture de la puce, des contrôles préliminaires dont l’authentification de la carte sont effectués grâce à la cryptographie asymétrique. Si tous les premiers contrôles sont passants, alors le porteur est invité à saisir son code PIN. Ce code est envoyé au serveur de la banque (eBank) pour une vérification de l'identité bancaire RIB. Après trois fausses tentatives, la carte sera capturée. Dans le cas où aucune action n’est détectée au bout de 10 secondes, la carte sera rejetée. En cas de succès d’authentification, le porteur choisit d’effectuer un retrait, imprimer un extrait, consulter son solde ou annuler l'opération en cours. Vers tDefault Capteur de présence de carte (TOR) ISR tAuthentification Carte Non Valide Timer 10 sec 10 sec 10 sec Timer On tPinVerif Qcode PIN Incorrect tDefault ISR Timer 10 sec ISR Qcompte END tService Timer On La synchronisation entre tâches se fait par 2 Queues (Qcode et Qcompte) et 2 interruptions EXTI(capteur TOR) et TIMER. I. Tache tDefault(2 pts) La tâche tDefault doit s’exécuter lorsqu’aucune tâche n’est active. Elle affiche le message « Veuillez insérer votre carte ». Elle a la plus basse priorité. Elle est réactivée par les autres tâches par appel à l’API vtaskResume. Cette API prend en paramètre le handle de la tâche tDefault. On l'appelera Handle_tDefault dans le BSP suivant. void vTaskSuspendAll(void); xTaskHandle Handle_tDefault; // suspend toutes les tâches. A appeler ailleurs de cette tâche. //doit être appelé dans la création de la tâche tDefault. //C’est le dernier paramètre de l’API xTaskCreate*/ void vtaskResume(xTaskHandle HandleDeLaTache) ; const char * msg = " Veuillez insérer votre carte SVP " ; void affichtMsg(const char* chaine) ; I.1(0,5 pts)) Donner le bout de code de création de la tâche tDefault I.2(1,5 pts)) Donner le code de cette tâche. II. Tâche tAuthentification(6 pts) A la détection de la carte, la fonction de l’ISR (void isrHandlerCardDetection()) active la tâche tAuthentification qui est initialement en état de suspension. La synchronisation entre l’ISR et la tâche se fait par sémaphore. On appellera semIsrCapt ce sémaphore. II.1( 0,5pts)) Quelle est la nature du sémaphore utilisé : mutex, binaire ou compteur ? Justifier. II.2( 0,5pts)) Donner les bouts de codes de déclaration et de création du sémaphore. 1 II.3( 1,5pts)) Donner le code de la fonction de l’ISR (void isrHandlerCardDetection()). On suppose définie la fonction (void isrClearFlagsPending()) qui reconfigure l’environnement pour une nouvelle ISR. La tâche tAuthentification est déclenchée par l’ISR. Elle récupère de la puce de la carte son numéro, sa clef privée et sa date d’expiration. Ces données sont stockées dans une variable de type tCardInfo. L’appel de la fonction Decrypt() permettra de générer le code à envoyer à la tâche tPinVerif dans le cas où il est valide via la queue QCode. Si le code n’est pas valide, la carte est rejetée, toutes les tâches sont suspendues sauf la tâche tDefault qui est activée (resumed, voir question I). On suppose définit le BSP suivant : typedef uint8_t tcode ; typedef struct{ uint8_t jour ; uint8_t mois ; uint8_t an ; } tdate ; // type structuré pour acquérir la date d’expiration de la carte typedef struct{ uint8_t NumCard ; tcode ClefPrivee; tdate expirationDate; } tCardInfo ; // type structuré pour acquérir les informations enregistrées dans la puce de la carte uint8_t tcode uint8_t uint8_t uint8_t tcode getNumCard(); // fonction qui retourne le numéro de la carte getClefPrivee(); // fonction qui retourne la clef privée de la carte getJour() ; // fonction qui retourne la date du jour d’expiration de la carte getMois() ; // fonction qui retourne la date du mois d’expiration de la carte getAn() ; // fonction qui retourne la date de l’an d’expiration de la carte Decrypt(tCardInfo * structInfo) ; // fonction de décryptage qui retourne le code //à envoyer à la tâche tPinVerif typedef enum { notValid = 0, isValid} tvalid ; // type énuméré à retourner par la fonction // isValidFunc tvalid isValidFunc(tcode code); // fonction teste si la carte est valide void rejectCard(); // fonction qui rejette la carte du lecteur II.4( 0,5pts)) Donner les codes de déclaration et de création de la queue Qcode de taille 6. II.5( 0,5pts)) Donner le bout de code de création de la tâche tAuthentification. II.6( 2,5pts)) Donner le code de la tâche tAuthentification III. Tâche tPinVerif (6 pts) La vérification du code PIN entré par l’operateur, à partir du clavier, se fait en le comparant au code reçu de la tâche tAuthentification. L’opérateur aura 3 essais pour saisir un code PIN correct sur le clavier du DAB, sinon la carte sera capturée. Elle le sera de même si aucune saisie n’est effectuée pendant 10 secondes comptabilisées par un timer. Ce Timer est géré en mode interruption par la tache timerTask. L’accès au clavier est en concurrence avec la tâche tService, donc un traitement d’exclusivité est obligatoire avant l’appel aux fonctions de lecture du clavier. III.1(0,5 pts)) Par quel moyen se fait ce traitement d’exclusivité ? III.2(0,5 pts)) Déclarer et créer ce moyen d’exclusivité. On donne le BSP suivant : tcode* lireCodePin(); // lecture du code PIN saisie du clavier, retourne NULL si aucun code n’est saisi. tvalid testConfident(tcode c1, tcode c2) ; // test de confidentialité retourne isValid si // les deux codes sont compatibles void TimerOn() ; // lance le timer void TimerReset() ; // arrête et réinitialise le timer typedef struct{ 2 uint8_t uint16_t }tCompte ; solde ; RIB ; //identification bancaire tCompte* getCompteInfo() ; // retourne NULL si l’accès au serveur de la banque n’est pas réussi. // Sinon elle retourne l’adresse de la zone mémoire contenant les infos sur la compte. Le déroulement de la tâche est comme suit : - Recevoir le code secret de la tâche tAuthentification et lancer le timer. - Pour 3 tentatives : tenter de lire le code PIN saisi (différent de NULL) et tester la confidentialité des codes. • Si aucune tentative n’est valide, suspendre toutes les tâches, arrêter le timer et réactiver tDefault. • Si au moins une tentative est valide, arrêter le timer et récupérer les infos sur le compte. Envoyer ensuite ces infos via la queue Qcompte vers la tâche tService. III.3(0,5 pts)) Donner les codes de déclaration et de création de la queue Qcompte de taille 3. III.4( 0,5pts)) Donner le bout de code création de cette tâche. III.5(4 pts)) Coder cette tâche en se basant sur les BSP précédents. IV. Tâche tService Les services possibles pour le client du DAB sont : impression de l’extrait, lecture du solde, retrait d’un montant et annulation. Cette tâche permet l’exécution de l’un de ces services. Si l’opération à exécuter est annulation, on revient à la tâche tDefault après suspension de toutes les autres tâches et reset du timer. On suppose défini le BSP suivant : typedef enum {extrait, solde, retrait, annuler} tOper ; uint8_t getSolde(tCompte C) ; // retourne le solde du compte C en paramètre uint16_t getRIB(tCompte C) ; // retourne le RIB du compte C en paramètre void updateMontant(tCompte* C, uint8_t montant) ; // met a jour le solde du compte C suite a un retrait du montant tOper saisirService() ; //retourne le service choisi par le client uint8_t saisirMontant() ; // si l’opération est retrait, le client doit saisir son montant, // cette fonction retourne le montant choisi par le client void imprimExtrait(uint16_t RIB) ; // permet d’imprimer un extrait de compte en passant //en paramètre le champ RIB d’une structure de type tCompte Le déroulement de la tâche est comme suit. Recevoir les données envoyées par la tâche tPINVerif, activer le timer, lire le service saisi par le client et éventuellement le montant si c’est un retrait. Ensuite, Rejeter la carte et arrêter le timer. A la fin Suspendre toutes les tâches et activer tDefault à la fin. IV.1( 0,5pts)) Donner le bout de code de création de cette tâche. IV.2(3,5 pts)) Donner le code de cette tâche. V. Tâche timerTask(4 pts) Le timer expire lorsque l’accès au réseau eBank échoue pendant 10 secondes, ou l’attente de saisie a expiré au-delà de 10 secondes. La fonction de l’ISR (void isrHandlerTmr()) active la tâche timerTask par le moyen du sémaphore semIsrTMR qui est de même nature que celui de la question 1. Cette tâche se déclenche par la réception du sémaphore. Elle affiche le message « problème de réseau », rejette la carte, désactive toutes les autres tâches et réactive la tâche tDefault. V.1(0,5 pts)) Donner les bout de codes de déclaration et de création du sémaphore. V.2) (1,5 pts)Donner le code de la fonction de l’ISR (void isrHandlerTmr()). On suppose définie la fonction (void isrClearFlagsPending()) qui réactive l’ISR. V.3( 0,5pts)) donner le bout de code de création de cette tâche. V.4( 1,5pts)) donner le code de cette tâche. 3