Outils pour utilisateurs

Outils du site


Action disabled: media
tppic

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

Objectifs

L'objectif de cette série de TP est d'illustrer la communication entre des dispositifs « industriels » de type micro-contrôleurs et des ordinateurs via un réseau Ethernet. Dans un premier temps, vous utiliserez un micro-contrôleur PIC 32 bits de la marque Microchip, programmé à l'aide de l'environnement de développement MPLABX. Ce micro-contrôleur dispose d'un grand nombre d'interfaces de communication dont l'interface ethernet intégrée que nous allons exploiter pour échanger des informations avec un serveur et d'autres cartes PIC. Pour réaliser cela, nous utiliserons des fonctions de la pile (Librairie) TCP/IP Microchip.

Lors des quatre premières heures de TP, vous devrez développer une application sur ce PIC pour qu'il dialogue avec une application déjà écrite sur un PC distant appelé « superviseur ».

Ensuite, vous développerez une application sur PC pour dialoguer avec la carte PIC, sujet présenté dans: tpqt

Présentation des réseaux

Le réseau utilisé pour faire communiquer les cartes PIC et les PC utilise un VLAN sur le réseau de l'IUT:

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.

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.

Le VLAN contient le PC superviseur, les différentes cartes PIC ainsi que les PC utilisés par les étudiants.

Sur le PC superviseur, une application nommée BroadcastReceiver est exécutée en 14 exemplaires, chacune dialoguant avec une unique carte PIC grâce à des numéros de port différents.

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. 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.

Détermination des adresses

Pour connaître les adresses IP et MAC des interfaces d'un appareil sous linux, saisir dans une console (ouverte en tapant ALT+F2 puis lxterm) la commande suivante (qui remplace avantageusement: ifconfig -a)

ip addr ls 

La commande affiche les différentes interfaces présentes sur la machine. Dans les salles de TP, il y a 2 interfaces filaires par machine, et il vous incombe de déterminer laquelle est connectée à chaque réseau ou VLAN (en fonction de l'IP associée).

L'adresse MAC de chaque interface est affichée sur la ligne “Adresse physique”

Pour connaître l'adresse MAC d'une machine distante, nous pouvons utiliser le mécanisme d'ARP (Adress Resolution Protocol). Pour cela, nous envoyons une requête de ping à la machine distante en tapant dans une console (Pour terminer l'exécution de la commande ping, taper CTRL+C):

ping adresse_IP  

Si la machine depuis laquelle cette commande est lancée ne connaît pas encore l'adresse MAC correspondant à cette IP, elle va envoyer une requête ARP sur le réseau pour demander quel dispositif possède cette IP. Le dispositif en question, s'il est présent et qu'il est capable de répondre à la requête, va alors répondre à la requête ARP. (puis plus tard au ping…). La machine qui a lancé la requête ARP va ensuite stocker dans une table la correspondance entre les adresses IP et MAC et cette table sera visible en saisissant dans une console la commande suivante (qui remplace avantageusement: arp -a):

 ip neigh ls 

Pour consulter la table de routage en IPv4:

ip route ls 

Pour consulter la table de routage en IPv6 (non utilisée dans le TP):

ip -6 route ls   

Présentation du format d'échange des données

Chaque application BroadcastReceiver réalise la tâche suivante: Tout d'abord, elle ouvre des sockets UDP (canal de communication, se reporter au cours de réseau) pour communiquer:

Ensuite l'application BroadcastReceiver affiche les datagrammes UDP reçus sous forme d'une chaîne de caractères, et si la chaîne est conforme au format attendu, elle visualise l'état des trois boutons dont la valeur a été passée via des variables que nous nommerons b1state, b2state et b3state (actif à 1). Une variable compteur est également transmise pour comptabiliser le nombre de trames émises par le PIC. Le format à respecter a été choisi arbitrairement comme une chaîne ASCII générée par :

sprintf(chaine,"compteur= %6d b1:%d  b2:%d  b3:%d\n",compteuretudiant,b1state,b2state,b3state);

La fonction sprintf fonctionne de la même façon que le printf sauf que la chaine, au lieu d'être affichée sur une console, est écrite dans une variable de type tableau de caractères dont l'adresse de début est passée en premier paramètres de la fonction sprintf. Dans cet exemple, la variable char chaine[100] est donc remplie avec les caractères qui auraient normalement été affichés si l'on avait exécuté la fonction printf.

L'application permet également de commander les LED de la carte PIC. Elle dispose pour cela de 4 Boutons. Les boutons « Led0 », « Led1 » et « Led2 » doivent faire commuter l'état des leds correspondantes sur la carte PIC lors d'un appui, alors que le bouton « start clignote LED0 » permet de commuter automatiquement la led0 toutes les 2 secondes. Chaque commutation d'une Led numérotée i est pilotée en envoyant une chaine ASCII générée par:

sprintf(chaine,"%d",i) ;

Pour rappel, l'objectif de ce premier TP est de développer l'application tournant sur le PIC qui va émettre l'état des boutons et commander les LED.

Présentation de la carte de développement

La carte utilisée est une PIC32 Ethernet Starter Kit.

La documentation de cette carte est disponible dans le fichier: https://bvdp.inetdoc.net/files/iut/tp_pic/doc/PIC32_Starter_Kits_Users_Guide_DS61159A.pdf

La documentation du micro-contrôleur PIC32MX est dans le fichier: https://bvdp.inetdoc.net/files/iut/tp_pic/doc/PIC32MX-61156D.pdf

Pour les plus curieux, le schéma de la carte est visible sur: https://bvdp.inetdoc.net/files/iut/tp_pic/doc/PIC32ESKSchematics.pdf

La structure interne du PIC32 est visible sur l'image suivante:

La carte possède des E/S simples à utiliser, 3 LED et 3 boutons:

  1. bouton SW1: Actif à l'état bas et connecté au bit 6 du port D (RD6)
  2. bouton SW2: Actif à l'état bas et connecté au bit 7 du port D (RD7)
  3. bouton SW3: Actif à l'état bas et connecté au bit 13 du port D (RD13)
  4. LED 0: actif à l'état haut et connectée au bit 0 du port D (RD0)
  5. LED 1: actif à l'état haut et connectée au bit 1 du port D (RD1)
  6. LED 2: actif à l'état haut et connectée au bit 2 du port D (RD2)

Cette carte est dotée d'une connectivité variée:

  1. Interface USB Host: La carte peut être raccordée à des périphériques (clef usb, souris,clavier…)
  2. Interface USB OnTheGo: La carte peut être raccordée comme un périphérique (Device) à un hôte (PC ou autre carte micro-contrôleur) ou comme un hôte au choix.
  3. Interface USB Debug: Cette interface USB est connectée à un second micro-contrôleur PIC de la carte de développement servant au chargement et au test des programmes. Cette interface est également utilisée pour alimenter la carte en 5V via le bus USB.
  4. Interface Ethernet 10/100: Cette interface permet de raccorder la carte à un réseau ethernet.
  5. Connecteur d'extension: ce connecteur de 120 broches permet d'utiliser diverses broches et interfaces du micro-contrôleur.

Structure interne du micro-contrôleur

Le micro contrôleur est de type 32 bits, il est donc capable d'effectuer des opérations directement sur des registres de 32 bits. Comme nous allons le programmer en langage C, cela se traduira principalement par une plus grande vitesse d'exécution des calculs sur les grands nombres.

Le micro-contrôleur intègre la partie MAC (Média Access Control), la couche PHY (PHYsique) étant quand à elle réalisée par le composant DP83848C de chez Texas Instrument, voir le fichier: https://bvdp.inetdoc.net/files/iut/tp_pic/doc/1668041.pdf

Développement sur PIC

Le développement de l'application se fait en langage C. Nous utiliserons une version un peu allégée du projet de démo “TCP/IP Demo App” dans lequel nous ajouterons une tâche de communication utilisant 2 sockets UDP.

Structure de l'application à construire

Le code que vous devez développer doit être écrit uniquement dans deux fichiers etudiantSocketApp.c et etudiantSocketApp.h. Ces fichiers définissent 2 fonctions appelées par le programme principal:

  1. une fonction void etudiantSocketAppInit(); appelée une fois en début de programme.
  2. une fonction void etudiantSocketAppTask(); appelée en boucle dans le programme à une cadence dépendant des autres tâches à exécuter. Par exemple, le micro contrôleur exécute une tâche de réponse au PING comme nous le verrons plus loin. Il ne faut donc pas que la fonction etudiantSocketAppTask soit bloquante, au risque de bloquer l'exécution d'autres services.

Durant le développement de votre application, vous pourrez utiliser la fonction DBPRINTF(char texte[]); pour afficher dans la console debug des messages courts indiquant l'état du programme. Veillez à utiliser cette fonctionnalité avec parcimonie car elle est très lente. Veillez également à ce que la chaine passée en paramètre soit bien terminée par \n pour déclencher l'envoi effectif de la chaine sur l'interface debug. Dans le cas contraire, vous pourrez faire un appel à:

DBPRINTF("\n");

L'affichage des infos de debug dans le champ Output→DBPRINTF (droite de Starter Kits dans la partie inférieure de MPLABX).

Note sur les types

Afin de différencier les entiers sur 8,16 et 32 bits, 3 types sont définis:

  1. DWORD pour des entiers sur 32 bits.
  2. WORD pour des entiers sur 16 bits.
  3. BYTE pour des entiers sur 8 bits.

D'autres types sont également définis: UDP_SOCKET, UDP_PORT, NODE_INFO…

Sockets MICROCHIP

L'application à développer utilise une interface propre à MICROCHIP pour l'utilisation des sockets. Son usage reste très proche de celui des Sockets BSD vus en TP de réseau. La documentation complète de la pile TCP/IP est disponible dans le fichier: https://bvdp.inetdoc.net/files/iut/tp_pic/doc/TCPIPStackHelp.chm

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:

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 udpsock2; //utilisé pour la réception depuis le PIC

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);

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

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);

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.

Finalement, pour demander l'émission effective des données du buffer d'émission sur l'interface, il faut faire appel à la fonction :

void UDPFlush();

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, car disponible dans le buffer de réception:

WORD UDPIsGetReady( UDP_SOCKET s); 

Les caractères (au nombre de wDataLen) sont ensuite lus vers une chaîne cData par la fonction:

WORD UDPGetArray( BYTE * cData,  WORD wDataLen);

Gestion du temps

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.

Après avoir défini la variable globale DWORD tim = 0; et la constante

#define ETUDIANTSOCKETAPP_OCCURENCE_PAR_SEC 5ul //pour 5 fois par secondes,

la fonction etudiantSocketAppTask() possède cette structure:

void etudiantSocketAppTask()
{
if(TickGet() -tim >= TICK_SECOND/ ETUDIANTSOCKETAPP_OCCURENCE_PAR_SEC)
  {
  tim = TickGet();
  compteur++; //Tâche à exécuter, incrémentation d'un compteur par exemple....
  } 
}

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:

int sprintf(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 terminée par le caractère '\0' (sans compter le caractère '\0'):

 int strlen(char* chainecarac);

Lecture de l'état des boutons

L'état des 3 boutons est lu et affecté à des variables grâce à:

b1state=(int)!PORTReadBits(IOPORT_D, BIT_6);
b2state=(int)!PORTReadBits(IOPORT_D, BIT_7);
b3state=(int)!PORTReadBits(IOPORT_D, BIT_13);

Commande des LED

Les Leds sont changées d'état en exécutant:

LED0_IO ^= 1;  //opérateur Ou exclusif avec opérande 1 = complémentation
LED1_IO ^= 1; 
LED2_IO ^= 1;

Il est bien sûr possible de commander les leds par valeur par exemple avec:

LED1_IO = 0; 
LED1_IO = 1;  
LED1_IO = b2state;

Remarques importantes:

  1. 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!
  2. Ne brancher le câble réseau sur l'interface du PIC que lorsque vous voulez tester votre programme sur la carte.
  3. 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”.
  4. 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.
  5. Ne jamais brancher une carte PIC sur le réseau sans avoir préalablement chargé votre programme… Elle contient peut être un mauvais programme qui va polluer tout le réseau et empêcher vos collègues de travailler!
  6. La carte de développement PIC32 est alimentée par le port USB, ne pas chercher à l'alimenter par une alimentation externe.
  7. Ne pas changer la position des cavaliers sur les cartes.

Travail demandé

Avant de coder...

Identification des binômes
  1. Remplir la feuille de présence pour déterminer qui utilise quelle carte et quelle adresse IP.
Identification des éléments utiles sur le schéma et analyse des couches réseau
  1. Repérer sur le schéma à remplir les éléments utilisés pour faire dialoguer la carte PIC avec le PC superviseur..
  2. Établir un schéma faisant apparaître les différentes couches réseau impliquées.
Récupération du projet

POUR LA PREMIERE SEANCE UNIQUEMENT!, Copier/coller dans une console:

echo commence
cd ~
wget https://bvdp.inetdoc.net/files/iut/tp_pic/install_linux/TCPIP_Demo_App_etudiant.zip
unzip TCPIP_Demo_App_etudiant.zip
rm  TCPIP_Demo_App_etudiant.zip
echo fini
Initialisation du système de gestion de version en local

POUR LA PREMIERE SEANCE UNIQUEMENT!, Copier/coller dans une console:

echo commence
cd ~/TCPIP_Demo_App_etudiant
git init
git add etudiantSocketApp.c  ./Alternative_Configurations/TCPIPConfig_PIC32_Internal_Ethernet.h etudiantSocketApp.h MainDemo.c 
git commit -m'initial version'
gitk &
echo fini

Vous pouvez ensuite fermer l'outils gitk qui permet de voir les changements entre les différentes versions.

Lancement de l'outils de développement
  1. Brancher la carte de développement sur le port USB du PC.
  2. Lancer mplabX, en ouvrant un terminal et en saisissant mplab_ide
  3. Dans mplabX, cliquer sur File→Open project et choisir le projet Projet.X dans le dossier ~/TCPIP_Demo_App_etudiant
  4. 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.
Configuration de l'adresse IP de chaque carte

L'adresse IP associée à chaque carte est dite 'statique', c'est à dire qu'elle est attribuée à chaque carte par le programme de chacune d'elle, au lieu d'être attribuée par un serveur (on parle alors d'adresse 'dynamique' fournie par un serveur DHCP)

  1. Ouvrir « TCPIPConfig PIC32 Internal Ethernet.h » dans le projet (en déroulant à gauche Header files)
  2. Localiser le réglage de l'adresse IP et du masque dans ce fichier et remplacer les valeurs par celles qui conviennent. Par exemple, pour régler le quatrième octet de l'IP à la valeur 100:

#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 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
  1. 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.
  2. 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é.
  3. 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

Il y a plusieurs tâches fonctionnant en (pseudo)parallèle sur le PIC, notamment un service de réponse au PING.

  1. 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 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:

Une fois la réponse au ping validée, mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/TCPIP_Demo_App_etudiant
git commit -a -m'ping working'
gitk &
echo fini

Exercice 2: Prise en main des E/S

  1. Débrancher le cable réseau pour cet exercice.
  2. Dans la fonction etudiantSocketAppTask(), recopier l'état des boutons sur les LEDs correspondantes à une cadence d'une fois par seconde.
  3. 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:
sprintf(chaine,"compteur= %6d b1:%d  b2:%d  b3:%d\n",compteuretudiant,b1state,b2state,b3state);

Mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/TCPIP_Demo_App_etudiant
git commit -a -m'E/S working'
gitk &
echo fini

Exercice 3: Réception de commandes des LED

  1. 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)
  2. 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.
  3. Tester votre programme en demandant sur le PC superviseur, via l'application BroadcastReceiver qui communique avec votre carte PIC, de commuter chacune des LEDs.

Mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/TCPIP_Demo_App_etudiant
git commit -a -m'led working'
gitk &
echo fini

Exercice 4: Émission de l'état des boutons

  1. 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. La chaîne envoyée sur le socket devra contenir le caractère '\0'.

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[1] = XXX;
myRemoteNode.IPAddr.v[2] = XXX;
myRemoteNode.IPAddr.v[3] = XXX;
myRemoteNode.MACAddr.v[0]= XXX; //Adresse MAC du PC superviseur, premier octet (de poids fort)
myRemoteNode.MACAddr.v[1]= XXX;
myRemoteNode.MACAddr.v[2]= XXX;
myRemoteNode.MACAddr.v[3]= XXX;
myRemoteNode.MACAddr.v[4]= XXX;
myRemoteNode.MACAddr.v[5]= XXX; 

Ensuite, passer un pointeur sur myRemoteNode en paramètre à la fonction UDPOpen() lors de l'ouverture du socket en émission.

Mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/TCPIP_Demo_App_etudiant
git commit -a -m'buttons working'
gitk &
echo fini

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 ce tableau:

ARPResolve(type pointeur sur adresse IP  );

et

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 (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.

Il est important que la fonction etudiantSocketAppTask() soit NON BLOQUANTE!

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 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.

Mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/TCPIP_Demo_App_etudiant
git commit -a -m'ARP working'
gitk &
echo fini

Communication avec votre PC

Récupérer l'éxecutable de l'application broadcastreceiver sur votre machine:

echo commence
cd ~/TCPIP_Demo_App_etudiant
wget bvdp.inetdoc.net/files/iut/tp_pic/binaries/broadcastreceiver
chmod a+x broadcastreceiver
echo fini

Ensuite saisir dans la console en substituant les paramètres par leur valeurs correctes:

./broadcastreceiver AdresseIPCartePIC PortUDPReceptionSurPC PortUDPEmissionSurPC

par exemple pour la carte PIC numéro 17:

./broadcastreceiver 172.16.0.17 30171 30172

Modifier le code du PIC en conséquence (adresses IP (et MAC si ARP non fonctionnel) destinataire et numéros de ports).

Vérifier la communication entre le PC et le PIC

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.txt · Dernière modification : 2022/02/21 09:45 de bvandepo