Outils pour utilisateurs

Outils du site


tppic

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
tppic [2019/02/22 10:35]
bvandepo
tppic [2019/04/06 14:08] (Version actuelle)
bvandepo [Exercice 3: Réception de commandes des LED]
Ligne 3: Ligne 3:
  
 Se logger sur le pc superviseur en tant que: ge2i pass:ge2i Se logger sur le pc superviseur en tant que: ge2i pass:ge2i
 +
 +Utiliser le genre masculin pour socket car c'est un anglicisme: https://​fr.wiktionary.org/​wiki/​socket
  
 Les binaires pour les pc superviseur sont stockés en local sur les machines dans /​usr/​local/​binaries/​lanceEN.py pour ER2EN   et lance.py ​ pour ER2AU Les binaires pour les pc superviseur sont stockés en local sur les machines dans /​usr/​local/​binaries/​lanceEN.py pour ER2EN   et lance.py ​ pour ER2AU
Ligne 18: Ligne 20:
   sudo ip neigh flush dev eth0   sudo ip neigh flush dev eth0
  
 +
 +pour filtrer les requetes et réponses ARP avec Wireshark à partir de l'​adresse MAC:
 +  ((eth.dst == 00:​04:​a3:​10:​dc:​84) || (eth.src == 00:​04:​a3:​10:​dc:​84) ) && arp
 </​ifauth>​ </​ifauth>​
  
Ligne 41: Ligne 46:
 copier coller dans une console: copier coller dans une console:
 </​color>​ </​color>​
-  rsync -av --delete ~/​TCPIP_Demo_App_etudiant /mnt/etu/s4+  rsync -av --delete ~/​TCPIP_Demo_App_etudiant /mnt/etu/
  
 <color red> <color red>
Ligne 48: Ligne 53:
  
 </​color>​ </​color>​
 +
 +------------------------------------------------------------
 +
 ===== TP Bus de communication : Initiation au micro-contrôleur PIC32 et utilisation d'un réseau local pour l'​échange de données via  sockets UDP ===== ===== TP Bus de communication : Initiation au micro-contrôleur PIC32 et utilisation d'un réseau local pour l'​échange de données via  sockets UDP =====
    
Ligne 76: Ligne 84:
   passerelle par défaut : 172.16.0.1   passerelle par défaut : 172.16.0.1
   plage @IP statiques (pour les cartes PIC) : 172.16.0.2 - 33   plage @IP statiques (pour les cartes PIC) : 172.16.0.2 - 33
-  plage @IP DHCP avec baux statiques : 172.16.0.34 - 62+  plage @IP DHCP avec baux statiques ​(pour les PC) : 172.16.0.34 - 62
   IP du PC superviseur : 172.16.0.34   IP du PC superviseur : 172.16.0.34
 </​ifauth>​ </​ifauth>​
Ligne 87: Ligne 95:
   passerelle par défaut : 172.16.6.1   passerelle par défaut : 172.16.6.1
   plage @IP statiques (pour les cartes PIC) : 172.16.6.2 - 33   plage @IP statiques (pour les cartes PIC) : 172.16.6.2 - 33
-  plage @IP DHCP avec baux statiques : 172.16.6.34 - 62+  plage @IP DHCP avec baux statiques ​(pour les PC) : 172.16.6.34 - 62
   IP du PC superviseur : 172.16.6.34  ​   IP du PC superviseur : 172.16.6.34  ​
 </​ifauth>​ </​ifauth>​
  
-Dans la salle, un PC va faire office de superviseur,​ dans le sens où il va permettre de centraliser les communications ​issues des différentes cartes PIC.+Dans la salle, un PC va faire office de superviseur,​ dans le sens où il va permettre de centraliser les informations ​issues des différentes cartes PIC et de les piloter à distance.
  
  
Ligne 108: Ligne 116:
  
 Le schéma suivant récapitule l'​ensemble des matériels et logiciels que nous allons utiliser dans cette série de TP. Les différents éléments seront expliqués au fur et à mesure. <color red>A chaque étape, vous devez être capable d'​identifier les portions utilisées et leur rôle. Vous devrez remplir les cases jaunes sur la feuille distribuée lors du TP.</​color>​ Le schéma suivant récapitule l'​ensemble des matériels et logiciels que nous allons utiliser dans cette série de TP. Les différents éléments seront expliqués au fur et à mesure. <color red>A chaque étape, vous devez être capable d'​identifier les portions utilisées et leur rôle. Vous devrez remplir les cases jaunes sur la feuille distribuée lors du TP.</​color>​
-<ifauth @prof> 
-{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​schemareseauPIC-2018-au-en.png}} 
-</​ifauth>​ 
  
 {{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​schemareseauPIC-2018-au-en-horizontal.png}} {{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_pic/​schemareseauPIC-2018-au-en-horizontal.png}}
Ligne 238: Ligne 243:
  
  
-Cliquer sur Index puis sur UDP pour accéder à la partie qui nous sera utile. Le schéma suivant montre les différentes fonctions correspondant à l'​utilisation d'un socket UDP:+Cliquer sur Index puis sur UDP pour accéder à la partie qui nous sera utile. Le schéma suivant montre les différentes fonctions correspondant à l'​utilisation d'une socket UDP:
  
  
Ligne 246: Ligne 251:
  
  
-Nous nous restreindrons à utiliser les sockets dans un seul sens de communication à la fois et nous utiliserons donc deux sockets ​définis comme variables globales pour établir et maintenir la communication bidirectionnelle: ​+Nous nous restreindrons à utiliser les sockets dans un seul sens de communication à la fois et nous utiliserons donc deux sockets ​manipulés via deux variables globales pour établir et maintenir la communication bidirectionnelle: ​
   UDP_SOCKET udpsock; ​ //utilisé pour l'​émission depuis le PIC   UDP_SOCKET udpsock; ​ //utilisé pour l'​émission depuis le PIC
   UDP_SOCKET udpsock2; //utilisé pour la réception depuis le PIC   UDP_SOCKET udpsock2; //utilisé pour la réception depuis le PIC
Ligne 252: Ligne 257:
 Chaque socket doit ensuite être ouvert dans la fonction etudiantSocketAppInit() par un appel à la fonction: ​  Chaque socket doit ensuite être ouvert dans la fonction etudiantSocketAppInit() par un appel à la fonction: ​
   UDP_SOCKET UDPOpen( UDP_PORT localPort, ​ NODE_INFO * ptr_remoteNode, ​ UDP_PORT remotePort);​   UDP_SOCKET UDPOpen( UDP_PORT localPort, ​ NODE_INFO * ptr_remoteNode, ​ UDP_PORT remotePort);​
-localPort et remotePort ​sont ici égaux et valent ​le numéro du port associé au socket.  ptr_remoteNode est un pointeur sur une structure qui permet d'indiquer ​l'adresse IP de la machine connectée ​avec le socket. Cette structure est constituée de deux tableaux d'​octets IPAddr.v[] et  MACAddr.v[] codant respectivement l'​adresse IP et l'​adresse MAC du destinataire. Pour une socket ​écoutant sur n'​importe ​quelle adresse IP, il faut passer la valeur NULL comme paramètre effectif ptr_remoteNode.+Dans notre projet, les paramètres **localPort** et **remotePort** auront des valeurs effectives identiques pour un même socket: ​le numéro du port.  ​**ptr_remoteNode** est un pointeur sur une structure qui permet d'identifier ​l'hôte distant connecté ​avec le socket. Cette structure est constituée de deux tableaux d'​octets IPAddr.v[] et  MACAddr.v[] codant respectivement l'​adresse IP et l'​adresse MAC de l'​hôte distant. Pour ouvrir un socket ​en réception depuis ​n'​importe ​quel hôte, il faut passer la valeur ​**NULL** comme paramètre effectif ptr_remoteNode.
  
 +La fonction **UDPClose()** ne sera pas utilisée dans notre application,​ car les 2 sockets sont ouverts à l'​initialisation et utilisés tout au long de l'​exécution du programme.
  
 ===Socket en émission=== ===Socket en émission===
  
-Le socket en émission ​ peut alors émettre ses données à condition ​qu'il y ait de la place dans les buffers ​d'​émission ​de l'​interface Ethernet. Pour déterminer la place disponible, nous utiliserons la fonction suivante qui retourne le nombre de caractères que l'on peut émettre sur un socket:+Pour émettre des données sur un socket en émission, il faut s'​assurer ​qu'il y ait de la place dans son buffer ​d'​émission ​(FIFO). Pour déterminer la place disponible, nous utiliserons la fonction suivante qui retourne le nombre de caractères que l'on peut émettre sur un socket:
   WORD UDPIsPutReady( UDP_SOCKET s);   WORD UDPIsPutReady( UDP_SOCKET s);
  
-Si il y a suffisamment de place pour émettre les données, une chaîne de caractères cData contenant wDataLen caractères peut être émise ​par un appel à la fonction:+S'il y a suffisamment de place pour émettre les données, une chaîne de caractères ​**cData** contenant ​**wDataLen** caractères peut être copiée dans le buffer d'​émission ​par un appel à la fonction:
   WORD UDPPutArray( BYTE * cData, WORD wDataLen); //retourne le nombre de caractères effectivement émis.   WORD UDPPutArray( BYTE * cData, WORD wDataLen); //retourne le nombre de caractères effectivement émis.
-Finalement, pour demander l'​émission effective des données sur l'​interface, ​on fait appel à la fonction :+Finalement, pour demander l'​émission effective des données ​du buffer d'​émission ​sur l'​interface, ​il faut faire appel à la fonction :
   void UDPFlush();   void UDPFlush();
   ​   ​
 ===Socket en réception=== ===Socket en réception===
-Le socket en réception utilise d'​autres fonctions. La fonction UDPIsGetReady retourne le nombre de caractères pouvant être lus sur un socket,:+Le socket en réception utilise d'​autres fonctions. La fonction ​**UDPIsGetReady()** retourne le nombre de caractères pouvant être lus sur un socket, ​car disponible dans le buffer de réception:
   WORD UDPIsGetReady( UDP_SOCKET s);    WORD UDPIsGetReady( UDP_SOCKET s); 
-Les caractères (au nombre de wDataLen) sont ensuite lus vers une chaîne cData par la fonction:+Les caractères (au nombre de **wDataLen**) sont ensuite lus vers une chaîne ​**cData** par la fonction:
   WORD UDPGetArray( BYTE * cData, ​ WORD wDataLen);   WORD UDPGetArray( BYTE * cData, ​ WORD wDataLen);
-La fonction UDPClose() ne sera pas utilisée dans notre application,​ car les 2 sockets sont ouverts à l'​initialisation et utilisés tout au long de l'​exécution du programme.+
  
  
 ===Gestion du temps=== ===Gestion du temps===
-La fonction etudiantSocketAppTask() n'est pas appelée à intervalle de temps constant. Pour définir le nombre de fois que la tâche doit être exécutée par seconde, on utilise un timer que l'on vient scruter (mécanisme de scrutation plutôt que d'​interruption) à chaque appel de la fonction etudiantSocketAppTask() pour savoir s'il est temps d'​exécuter la tâche.+La fonction ​**etudiantSocketAppTask()** n'est pas appelée à intervalle de temps constant. Pour définir ​la périodicité (le nombre de fois que la tâche doit être exécutée par seconde), on utilise un timer que l'on vient scruter (mécanisme de scrutation plutôt que d'​interruption) à chaque appel de la fonction ​**etudiantSocketAppTask()** pour savoir s'il est temps d'​exécuter la tâche.
  
  
Ligne 280: Ligne 286:
   #define ETUDIANTSOCKETAPP_OCCURENCE_PAR_SEC 5ul //pour 5 fois par secondes,   #define ETUDIANTSOCKETAPP_OCCURENCE_PAR_SEC 5ul //pour 5 fois par secondes,
   ​   ​
-la fonction etudiantSocketAppTask() possède cette structure: +la fonction ​**etudiantSocketAppTask()** possède cette structure:
  
  
Ligne 295: Ligne 300:
  
 ===Génération et décodage de chaînes de caractères ASCII=== ===Génération et décodage de chaînes de caractères ASCII===
-Nous allons utiliser des tableaux de caractères pour l'​émission et la réception des données via les sockets car ce sont les paramètres d'​entrées/​sorties utilisés par les fonctions disponibles pour l'​envoi et la réception de datagrammes. Pour rappel, les fonctions permettant d'​écrire et de lire dans une chaîne de caractères chainecarac la chaîne de caractères formatée format(par exemple ''​Bonjour %d''​) sont:+Nous allons utiliser des tableaux de caractères pour l'​émission et la réception des données via les sockets car ce sont les paramètres d'​entrées/​sorties utilisés par les fonctions disponibles pour l'​envoi et la réception de datagrammes. Pour rappel, les fonctions permettant d'​écrire et de lire dans une chaîne de caractères ​**chainecarac** la chaîne de caractères formatée ​**format** (par exemple ''​Bonjour %d''​) sont:
  
   int sprintf(char* chainecarac,​ const char * format, ... );   int sprintf(char* chainecarac,​ const char * format, ... );
   int sscanf(char* chainecarac,​ const char * format, ... );    int sscanf(char* chainecarac,​ const char * format, ... ); 
-La fonction strlen retourne le nombre de caractères d'une chaîne chainecarac:​+La fonction strlen retourne le nombre de caractères d'une chaîne ​**chainecarac** terminée par le caractère '​\0'​:
    int strlen(char* chainecarac);​    int strlen(char* chainecarac);​
 ===Lecture de l'​état des boutons=== ===Lecture de l'​état des boutons===
-L'​état des 3 boutons est lu dans des variables ​par +L'​état des 3 boutons est lu et affecté à des variables ​grâce à:
   b1state=(int)!PORTReadBits(IOPORT_D,​ BIT_6);   b1state=(int)!PORTReadBits(IOPORT_D,​ BIT_6);
   b2state=(int)!PORTReadBits(IOPORT_D,​ BIT_7);   b2state=(int)!PORTReadBits(IOPORT_D,​ BIT_7);
Ligne 311: Ligne 316:
   LED1_IO ^= 1;    LED1_IO ^= 1; 
   LED2_IO ^= 1;   LED2_IO ^= 1;
 +
 Il est bien sûr possible de commander les leds par valeur par exemple avec: Il est bien sûr possible de commander les leds par valeur par exemple avec:
-  LED1_IO = 0; ou LED1_IO = 1;  ​+  LED1_IO = 0;  
 +  ​LED1_IO = 1;  ​ 
 +  LED1_IO = b2state;
  
 ====Remarques importantes:​==== ====Remarques importantes:​====
-   - Ne brancher le câble réseau sur l'​interface du PIC que lorsque vous voulez tester votre programme sur la carte et que vous l'avez déjà testé en pas à pas.+   - Dans tout le TP, vous veillerez à ne pas commenter ou casser du code précédemment validé. Chaque exercice doit ajouter des fonctionnalités,​ en maintenant le bon fonctionnement des fonctionnalités précédentes! 
 +   - Ne brancher le câble réseau sur l'​interface du PIC que lorsque vous voulez tester votre programme sur la carte.
    - Les cartes PIC ainsi que les câbles réseaux sont numérotés,​ il est IMPERATIF de n'​utiliser que votre câble et votre carte et de régler correctement l'​adresse IP de votre carte via le fichier "​TCPIPConfig PIC32 Internal Ethernet.h"​.    - Les cartes PIC ainsi que les câbles réseaux sont numérotés,​ il est IMPERATIF de n'​utiliser que votre câble et votre carte et de régler correctement l'​adresse IP de votre carte via le fichier "​TCPIPConfig PIC32 Internal Ethernet.h"​.
   - Votre application est contenue uniquement dans les fichiers etudiantSocketApp.c et etudiantSocketApp.h. Vous n'avez pas à modifier d'​autres fichiers hormis "​TCPIPConfig PIC32 Internal Ethernet.h"​ pour les réglages d'​adresses IP.   - Votre application est contenue uniquement dans les fichiers etudiantSocketApp.c et etudiantSocketApp.h. Vous n'avez pas à modifier d'​autres fichiers hormis "​TCPIPConfig PIC32 Internal Ethernet.h"​ pour les réglages d'​adresses IP.
Ligne 369: Ligne 378:
   #define MY_DEFAULT_IP_ADDR_BYTE4 {100ul}   #define MY_DEFAULT_IP_ADDR_BYTE4 {100ul}
   ​   ​
-Le masque est réglé à l'aide des macros MY_DEFAULT_MASK_BYTE1 à 4, de la même manière.+Le masque est réglé à l'aide des macros ​**MY_DEFAULT_MASK_BYTE1** à **4**, de la même manière.
  
-Le suffixe ul apres la valeur 100 signifie que la valeur est une constante à interpréter en tant que Unsigned Long. +Le suffixe ul apres la valeur 100 signifie que la valeur est une constante à interpréter en tant que **Unsigned Long**
 ==Chargement de votre programme et utilisation du mode debug== ==Chargement de votre programme et utilisation du mode debug==
   - Cliquer sur Debug->​Debug project. NB: la première compilation est lente (qq minutes) mais les suivantes seront plus rapides car seuls les fichiers modifiés seront recompilés (sauf si vous modifiez « TCPIPConfig PIC32 Internal Ethernet.h ») .   - Cliquer sur Debug->​Debug project. NB: la première compilation est lente (qq minutes) mais les suivantes seront plus rapides car seuls les fichiers modifiés seront recompilés (sauf si vous modifiez « TCPIPConfig PIC32 Internal Ethernet.h ») .
Ligne 378: Ligne 387:
  
 ====Exercice 1: Test de communication avec la carte ==== ====Exercice 1: Test de communication avec la carte ====
-Il y a plusieurs ​applications ​fonctionnant sur le PIC, notamment un service de réponse au PING.  +Il y a plusieurs ​tâches ​fonctionnant ​en (pseudo)parallèle ​sur le PIC, notamment un service de réponse au PING.  
-  - Votre carte étant en fonctionnement (RUN) et raccordée au réseau, lancer une demande de ping depuis ​le PC superviseur avec l'​adresse de votre carte. Votre PC envoie alors des demandes de PING à l'​adresse de la carte PIC. Si celle-ci est connectée au réseau et en fonction, elle doit répondre et l'​outil ping doit afficher le temps mis par la carte pour répondre (généralement moins d'une milliseconde sur ce réseau local). Cette opération peut être réalisée ​soit depuis le PC superviseur soit depuis votre machine de développement ​en saisissant ​ par exemple dans une console:+  - Votre carte étant en fonctionnement (programme en cours d’exécution) et raccordée au réseau, lancer une demande de PING depuis ​votre PC superviseur avec l'​adresse de votre carte. Si celle-ci est connectée au réseau et en fonction, elle doit répondre et l'​outil ping doit afficher le temps mis par la carte pour répondre (généralement moins d'une milliseconde sur ce réseau local). Cette opération peut être réalisée ​ en saisissant ​ par exemple dans une console:
 <ifauth @en> <ifauth @en>
   ping 172.16.0.2   ping 172.16.0.2
Ligne 401: Ligne 410:
 ====Exercice 2: Prise en main des E/S ==== ====Exercice 2: Prise en main des E/S ====
   - Débrancher le cable réseau pour cet exercice.   - Débrancher le cable réseau pour cet exercice.
-  - Dans la fonction etudiantSocketAppTask(),​ recopier l'​état des boutons sur les LEDs correspondantes **à une cadence d'une fois par seconde**. +  - Dans la fonction ​**etudiantSocketAppTask()**, recopier l'​état des boutons sur les LEDs correspondantes **à une cadence d'une fois par seconde**. 
-  - Afficher sur l'​interface debug la chaine ​qui devrait être envoyé au superviseur pour donner l'​état des boutons à l'aide de la fonction DBPRINTF présentée plus haut. La chaine ​affichée devra être générée dans le tableau chaine que vous aurez déclaré avec une taille suffisante. Le remplissage du tableau se fera  à l'aide de la fonction **sprintf**:​+  - Afficher sur l'​interface debug la chaîne ​qui devrait être envoyé au superviseur pour donner l'​état des boutons à l'aide de la fonction ​**DBPRINTF** présentée plus haut. La chaîne ​affichée devra être générée dans le tableau ​**chaine** que vous aurez déclaré ​préalablement ​avec une taille suffisante. Le remplissage du tableau se fera à l'aide de la fonction **sprintf**:​
  
  
Ligne 419: Ligne 428:
  
 ====Exercice 3: Réception de commandes des LED ==== ====Exercice 3: Réception de commandes des LED ====
-  - Compléter les fonctions etudiantSocketAppInit() et etudiantSocketAppTask() pour gérer la réception périodique des chaînes de caractères commandant les LED depuis le PC superviseur. Pour cela, vous devrez ouvrir ​une socket écoutant sur le bon numéro de port et depuis n'​importe quelle IP.  Veillez à définir un tableau de caractères en mémoire et à ne pas tenter de lire plus de caractères qu'il n'y a de place dans ce tableau. Vous penserez à commenter les lignes de votre programme qui pilotent les leds à partir de l'​état des boutons pour ne pas interférer avec la commande des leds depuis le réseau. +  - Compléter les fonctions ​**etudiantSocketAppInit()** et **etudiantSocketAppTask()** pour gérer la réception périodique des chaînes de caractères commandant les LED depuis le PC superviseur. Pour cela, vous devrez ouvrir ​un socket écoutant sur le bon numéro de port et depuis n'​importe quelle IP.  Veillez à définir un tableau de caractères en mémoire et à ne pas tenter de lire plus de caractères qu'il n'y a de place dans ce tableau. ​Vous pourrez au choix traiter un ordre de commutation des LEDS par appel de la fonction **etudiantSocketAppTask()** ou bien traiter autant d'​ordres que possible (en fonction de la taille de votre tableau) 
-  - Tester votre programme en demandant sur le PC superviseur,​ via l'​application BroadcastReceiver qui communique avec votre carte PIC, de commuter chacune des LED.+  - Vous penserez à commenter ​**UNIQUEMENT** ​les lignes de votre programme qui pilotent les leds à partir de l'​état des boutons pour ne pas interférer avec la commande des LEDs depuis le réseau. Conserver tout le reste du code en place, notamment la lecture de l'​état des boutons et l'​affichage de la chaine dans **DBPRINTF**
 +  - Tester votre programme en demandant sur le PC superviseur,​ via l'​application BroadcastReceiver qui communique avec votre carte PIC, de commuter chacune des LEDs.
  
  
Ligne 433: Ligne 443:
   echo fini   echo fini
 ====Exercice 4: Émission de l'​état des boutons ==== ====Exercice 4: Émission de l'​état des boutons ====
-  - Compléter les fonctions etudiantSocketAppInit() et etudiantSocketAppTask() pour gérer l'​envoi périodique à une fréquence d'un Hertz d'une chaîne de caractères codant l'​état des boutons poussoirs vers le PC superviseur. ​+  - Compléter les fonctions ​**etudiantSocketAppInit()** et **etudiantSocketAppTask()** pour gérer l'​envoi périodique à une fréquence d'un Hertz d'une chaîne de caractères codant l'​état des boutons poussoirs vers le PC superviseur. ​
  
-Pour cette tâche, il faut configurer l'​ouverture ​de la socket ​pour qu'​elle s'​établisse ​avec une seule machine sur le réseau. Dans un premier temps, nous n'​utiliserons pas le mécanisme ARP et nous devrons donc régler l'​adresse IP et l'​adresse MAC de la machine ​destination ​(le PC superviseur) avant d'​ouvrir ​la socket en définissant une variable globale NODE_INFO myRemoteNode;​ puis en l'​initialisant dans la fonction etudiantSocketAppInit() avec les valeurs que vous aurez déterminée ​grâce aux commandes ping et arp:+Pour cette tâche, il faut configurer l'​ouverture ​du socket avec une seule machine sur le réseau. Dans un premier temps, nous n'​utiliserons pas le mécanisme ARP et nous devrons donc régler l'​adresse IP et l'​adresse MAC de la machine ​distante ​(le PC superviseur) avant d'​ouvrir ​le socket en définissant une variable globale ​**NODE_INFO myRemoteNode;​** puis en l'​initialisant dans la fonction ​**etudiantSocketAppInit()** avec les valeurs que vous aurez déterminées ​grâce aux commandes ping et arp:
  
   myRemoteNode.IPAddr.v[0] = XXX;  //Adresse IP du PC superviseur,​ premier octet  (de poids fort)   myRemoteNode.IPAddr.v[0] = XXX;  //Adresse IP du PC superviseur,​ premier octet  (de poids fort)
Ligne 448: Ligne 458:
   myRemoteNode.MACAddr.v[5]= XXX;    myRemoteNode.MACAddr.v[5]= XXX; 
  
-Ensuite, passer ​ myRemoteNode en paramètre à la fonction UDPOpen lors de l'​ouverture ​de la socket en émission.+Ensuite, passer ​un pointeur sur **myRemoteNode** en paramètre à la fonction ​**UDPOpen()** lors de l'​ouverture ​du socket en émission.
  
  
Ligne 463: Ligne 473:
  
 ====Exercice 5: Gestion de l'ARP pour la communication avec le PC superviseur==== ====Exercice 5: Gestion de l'ARP pour la communication avec le PC superviseur====
-On souhaite maintenant mettre en place le mécanisme d'ARP dans l'​application sur le PIC. Vous allez dans un premier temps "​casser"​ l'​initialisation de **myRemoteNode.MACAddr.v[i]** en mettant des 0 dans toutes les cases et nous allons utiliser les fonctions suivantes pour remplir automatiquement ​le tableau:+On souhaite maintenant mettre en place le mécanisme d'ARP dans l'​application sur le PIC. Vous allez dans un premier temps "​casser"​ l'​initialisation de **myRemoteNode.MACAddr.v[i]** en mettant des 0 dans toutes les cases et nous allons utiliser les fonctions suivantes pour remplir automatiquement ​ce tableau:
  
   ARPResolve(type pointeur sur adresse IP  );   ARPResolve(type pointeur sur adresse IP  );
Ligne 469: Ligne 479:
   bool ARPIsResolved(type pointeur sur adresse IP, type pointeur sur adresse MAC)   bool ARPIsResolved(type pointeur sur adresse IP, type pointeur sur adresse MAC)
  
-Dans la fonction etudiantSocketAppTask(),​ à l'​intérieur de la tâche périodique à 1Hz, ajouter une machine à état **simple** permettant de faire des requêtes ARP avec la fonction **ARPResolve**. Ceci permet d'​envoyer une requette ARP avec l'​adresse IP passée en argument. Dans les appels suivants de la fonction etudiantSocketAppTask(),​ il vous faudra tester si **ARPIsResolved** a renvoyé ​true, ce qui signifie que la réponse ARP est arrivée et donc que le champ adresse MAC est mis à jour. Dans ce cas il faudra ouvrir ​la socket (une seule fois) puis effectuer l'​envoi des données comme dans l'​exercice ​précedent. Dans le cas contraire, il faudra appeler à nouveau **ARPResolve** pour envoyer une nouvelle requête.+Dans la fonction ​**etudiantSocketAppTask()**, à l'​intérieur de la tâche périodique à 1Hz, ajouter une machine à état **simple** ​(l'​état étant codé par une variable **static int**) ​permettant de faire des requêtes ARP avec la fonction **ARPResolve**. Ceci permet d'​envoyer une requette ARP avec l'​adresse IP passée en argument. Dans les appels suivants de la fonction** etudiantSocketAppTask()**, il vous faudra tester si **ARPIsResolved** a renvoyé ​**TRUE**, ce qui signifie que la réponse ARP est arrivée et donc que le champ adresse MAC est mis à jour. Dans ce cas il faudra ouvrir ​le socket (une seule fois) puis effectuer l'​envoi des données comme dans l'​exercice ​précédent. Dans le cas contraire, il faudra appeler à nouveau **ARPResolve** pour envoyer une nouvelle requête. 
  
 <color red> <color red>
-Il est important que la fonction ​ etudiantSocketAppTask() soit NON BLOQUANTE!</​color>​+Il est important que la fonction ​**etudiantSocketAppTask()** soit NON BLOQUANTE!</​color>​
  
-<​graphviz dot 500x90>+<​graphviz dot 350x90>
 ////////////////////////////////////////////////////////////////////////////////​ ////////////////////////////////////////////////////////////////////////////////​
 // Finite State Machine .dot diagram autogenerated by FsmProcess V 1.0 B. VANDEPORTAELE LAAS-CNRS 2016 // Finite State Machine .dot diagram autogenerated by FsmProcess V 1.0 B. VANDEPORTAELE LAAS-CNRS 2016
Ligne 483: Ligne 494:
     nodesep=0.1;​     nodesep=0.1;​
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////​ ///////////////////////////////////////////////////////////////////////////////////////////////////////////​
-// Finite State Machine Name: arp+// Finite State Machine Name: arp2
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////​ ///////////////////////////////////////////////////////////////////////////////////////////////////////////​
 //////////////////​display ​ states//////////////////​ //////////////////​display ​ states//////////////////​
Ligne 501: Ligne 512:
     //Action on state:     //Action on state:
     stateaction_1 ​ [shape=box,​label= ​  <<​TABLE BORDER="​0"​ CELLBORDER="​1"​ CELLSPACING="​0"​ CELLPADDING="​4">​     stateaction_1 ​ [shape=box,​label= ​  <<​TABLE BORDER="​0"​ CELLBORDER="​1"​ CELLSPACING="​0"​ CELLPADDING="​4">​
-        <​TR><​TD>​F</​TD><​TD COLSPAN="​2">​UDPOPEN</TD> </TR>+        <​TR><​TD>​F</​TD><​TD COLSPAN="​2">​UDPPUTARRAY</TD> </TR>
         </​TABLE>> ​ ];         </​TABLE>> ​ ];
     //attach the action on the state     //attach the action on the state
     state_1 ->​stateaction_1 ​ [arrowhead=none ]     ;     state_1 ->​stateaction_1 ​ [arrowhead=none ]     ;
- ​}; ​ 
-    //​---------State: ​  ​2 ​   ----------------- 
- { rank = same; 
-    state_2 [shape=circle,​fixedsize=true,​width=0.63,​ label= "​2"​ ]; 
-    //Action on state: 
-    stateaction_2 ​ [shape=box,​label= ​  <<​TABLE BORDER="​0"​ CELLBORDER="​1"​ CELLSPACING="​0"​ CELLPADDING="​4">​ 
-        <​TR><​TD>​F</​TD><​TD COLSPAN="​2">​UDPPUTARRAY</​TD>​ </TR> 
-        </​TABLE>> ​ ]; 
-    //attach the action on the state 
-    state_2 ->​stateaction_2 ​ [arrowhead=none ]     ; 
  ​}; ​  ​}; ​
 //////////////////​display ​ transitions//////////////////​ //////////////////​display ​ transitions//////////////////​
     state_0 -> state_1[ shape=box, ​ label= ​ <<​TABLE BORDER="​0"​ CELLBORDER="​1"​ CELLSPACING="​0"​ CELLPADDING="​4">​     state_0 -> state_1[ shape=box, ​ label= ​ <<​TABLE BORDER="​0"​ CELLBORDER="​1"​ CELLSPACING="​0"​ CELLPADDING="​4">​
-        <​TR><​TD COLSPAN="​2">​ARPISRESOLVED</​TD>​ </​TR>​ +        <​TR><​TD COLSPAN="​3">​ARPISRESOLVED</​TD>​ </​TR>​ 
-        </TABLE>>  ]; +        <TR><TD>F</TD><TD COLSPAN="​2">​UDPOPEN</TD> </TR>
-    state_1 -> state_2[ shape=box, ​ label=  ​<<TABLE BORDER="​0"​ CELLBORDER="​1"​ CELLSPACING="​0"​ CELLPADDING="​4"​> +
-        <TR><TD COLSPAN="​2">​1</TD> </TR>+
         </​TABLE>> ​ ];         </​TABLE>> ​ ];
 } }
- 
 </​graphviz>​ </​graphviz>​
  
  
 +Pour débugger, vous pourrez afficher l'​adresse IP demandée dans la requête ARP à l'aide de: 
 +  sprintf(chaine,​ "​ARPResolve adresse IP= %d.%d.%d.%d\n",​ myRemoteNode.IPAddr.v[0],​ myRemoteNode.IPAddr.v[1],​ myRemoteNode.IPAddr.v[2],​ myRemoteNode.IPAddr.v[3]);​
 +  DBPRINTF(chaine);​
 +Puis afficher l'​adresse MAC obtenue à l'aide de 
 +  sprintf(chaine,​ "ARP OK: adresse mac= %02x:​%02x:​%02x:​%02x:​%02x:​%02x\n",​ myRemoteNode.MACAddr.v[0],​ myRemoteNode.MACAddr.v[1],​ myRemoteNode.MACAddr.v[2],​ myRemoteNode.MACAddr.v[3],​ myRemoteNode.MACAddr.v[4],​ myRemoteNode.MACAddr.v[5]);​
 +  DBPRINTF(chaine);​
 +        ​
  
  
-Tester l'​émission avec le mécanisme d'ARP avec le PC superviseur. Utiliser Wireshark sur le PC superviseur pour observer la requête et la réponse ARP suivies des datagrammes UDP.+Tester l'​émission avec le mécanisme d'ARP avec le PC superviseur. Utiliser ​le logiciel ​Wireshark sur le PC superviseur pour observer la requête et la réponse ARP suivies des datagrammes UDP échangés entre votre carte PIC et l'​application correspondante sur le PC superviseur.
  
   ​   ​
tppic.1550828106.txt.gz · Dernière modification: 2019/02/22 10:35 par bvandepo