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:37]
bvandepo
tppic [2020/03/03 16:28] (Version actuelle)
bvandepo
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.51
 </ifauth> </ifauth>
 <ifauth @au> <ifauth @au>
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.48  
 </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.
  
  
 Ce VLAN utilise des adresses en /26 et possède donc un masque 255.255.255.192.  Ce VLAN utilise des adresses en /26 et possède donc un masque 255.255.255.192. 
-<ifauth @en>L'adresse IP 172.16.0.34 est attribuée dynamiquement au PC superviseur grâce à un bail DHCP.</ifauth>  +<ifauth @en>L'adresse IP 172.16.0.51 est attribuée dynamiquement au PC superviseur grâce à un bail DHCP.</ifauth>  
-<ifauth @au>L'adresse IP 172.16.6.34 est attribuée dynamiquement au PC superviseur grâce à un bail DHCP.</ifauth> +<ifauth @au>L'adresse IP 172.16.6.48 est attribuée dynamiquement au PC superviseur grâce à un bail DHCP.</ifauth> 
 Chaque carte PIC numérotée x doit être configurée pour avoir une adresse statique différente en fonction du numéro de la carte. Chaque carte PIC numérotée x doit être configurée pour avoir une adresse statique différente en fonction du numéro de la carte.
 <ifauth @en>La carte PIC numérotée x est adressée par l'IP 172.16.0.x.</ifauth> <ifauth @en>La carte PIC numérotée x est adressée par l'IP 172.16.0.x.</ifauth>
Ligne 135: Ligne 143:
  
 <ifauth @en> <ifauth @en>
-  - En émission: Superviseur avec l'IP 172.16.0.34  et le port UDP 30002+10*x vers carte PIC avec l'IP   172.16.0.x  et le port 30002+10*x +  - En émission: Superviseur avec l'IP 172.16.0.51  et le port UDP 30002+10*x vers carte PIC avec l'IP   172.16.0.x  et le port 30002+10*x 
-  - En réception: Carte PIC avec l'IP 172.16.0.x  et le port UDP 30001+10*x vers Superviseur avec l'IP 172.16.0.34 et le port  30001+10*x+  - En réception: Carte PIC avec l'IP 172.16.0.x  et le port UDP 30001+10*x vers Superviseur avec l'IP 172.16.0.51 et le port  30001+10*x
 Par exemple, l'application 3 communiquant avec la carte PIC 3 émet ses informations vers l'IP PIC 172.16.0.3 port 30032 et les reçoit sur le port 30031. La figure suivante montre la fenêtre de cette application: Par exemple, l'application 3 communiquant avec la carte PIC 3 émet ses informations vers l'IP PIC 172.16.0.3 port 30032 et les reçoit sur le port 30031. La figure suivante montre la fenêtre de cette application:
  
Ligne 143: Ligne 151:
  
 <ifauth @au> <ifauth @au>
-  - En émission: Superviseur avec l'IP 172.16.6.34  et le port UDP 30002+10*x vers carte PIC avec l'IP   172.16.6.x  et le port 30002+10*x +  - En émission: Superviseur avec l'IP 172.16.6.48  et le port UDP 30002+10*x vers carte PIC avec l'IP   172.16.6.x  et le port 30002+10*x 
-  - En réception: Carte PIC avec l'IP 172.16.6.x  et le port UDP 30001+10*x vers Superviseur avec l'IP 172.16.6.34 et le port  30001+10*x+  - En réception: Carte PIC avec l'IP 172.16.6.x  et le port UDP 30001+10*x vers Superviseur avec l'IP 172.16.6.48 et le port  30001+10*x
    
 Par exemple, l'application 3 communiquant avec la carte PIC 3 émet ses informations vers l'IP PIC 172.16.6.3 port 30032 et les reçoit sur le port 30031. La figure suivante montre la fenêtre de cette application: Par exemple, l'application 3 communiquant avec la carte PIC 3 émet ses informations vers l'IP PIC 172.16.6.3 port 30032 et les reçoit sur le port 30031. La figure suivante montre la fenêtre de cette application:
Ligne 235: 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 243: 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 249: 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 277: 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 292: 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' (sans compter 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 308: 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 355: Ligne 367:
 ==Lancement de l'outils de développement== ==Lancement de l'outils de développement==
   - Brancher la carte de développement sur le port USB du PC.   - Brancher la carte de développement sur le port USB du PC.
-  - Lancer mplabX, Menu Applications->Programmation->Mplab IDE+  - Lancer mplabX, en ouvrant un terminal et en saisissant mplab_ide
   - Dans mplabX, cliquer sur  File->Open project et choisir le projet Projet.X dans le dossier ~/TCPIP_Demo_App_etudiant      - Dans mplabX, cliquer sur  File->Open project et choisir le projet Projet.X dans le dossier ~/TCPIP_Demo_App_etudiant   
   - Par la suite, en cas de message d'erreur indiquant que la carte ne peut pas être réinitialisée, il faudra fermer MPLABX et le relancer.   - Par la suite, en cas de message d'erreur indiquant que la carte ne peut pas être réinitialisée, il faudra fermer MPLABX et le relancer.
Ligne 366: 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 dizaines de secondes) mais les suivantes seront plus rapides car seuls les fichiers modifiés seront recompilés (sauf si vous modifiez « TCPIPConfig PIC32 Internal Ethernet.h ») . Quand "User Program Running" s'affiche dans la fenêtre sous le code, la compilation et le chargment de l'application sont terminées.
   - Placer des points d'arrêt dans votre programme, en cliquant sur le numéro de la ligne (petit carré rouge apparaît), pour le désactiver, cliquer à nouveau sur le carré.   - Placer des points d'arrêt dans votre programme, en cliquant sur le numéro de la ligne (petit carré rouge apparaît), pour le désactiver, cliquer à nouveau sur le carré.
   - Presser Debug->debug project pour charger le programme dans le micro contrôleur et lancer le mode debug (Debug->Finish debugger session)   - Presser Debug->debug project pour charger le programme dans le micro contrôleur et lancer le mode debug (Debug->Finish debugger session)
  
 ====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 398: 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 416: 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 430: 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 de la chaîne de caractères codant l'état des boutons poussoirs vers le PC superviseur. <color red> La chaîne envoyée sur le socket devra contenir le caractère '\0'. </color>
  
-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 445: 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 460: 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 466: 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 480: Ligne 494:
     nodesep=0.1;     nodesep=0.1;
 /////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Finite State Machine Name: arp+// Finite State Machine Name: arp2
 /////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////display  states////////////////// //////////////////display  states//////////////////
Ligne 498: 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:      ----------------- 
- { 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.
  
      
Ligne 649: Ligne 657:
  
 {{http://homepages.laas.fr/bvandepo/files/iut/tp_pic/validation.png}} {{http://homepages.laas.fr/bvandepo/files/iut/tp_pic/validation.png}}
 +
 +
 +
 + 
 +Mettre à jour le suivi de version en saisissant dans une console:
 +  echo commence
 +  cd ~/TCPIP_Demo_App_etudiant
 +  git commit -a -m'reglage de l'adresse IP  du pc etudiant'
 +  gitk &
 +  echo fini
  
  
tppic.1550828224.txt.gz · Dernière modification: 2019/02/22 10:37 de bvandepo