IMA5 2018/2019 P13 : Différence entre versions
(→Documents Rendus) |
(→Documents Rendus) |
||
Ligne 657 : | Ligne 657 : | ||
=Documents Rendus= | =Documents Rendus= | ||
Rapport intermédiaire : [[Fichier:RapportIntermédiaire.pdf]] | Rapport intermédiaire : [[Fichier:RapportIntermédiaire.pdf]] | ||
+ | |||
+ | Présentation intermédiaire : [[Fichier:SoutenanceIntermédiareDiapoP13.pdf ]] |
Version du 19 décembre 2018 à 06:21
Sommaire
Présentation générale
Description
La recherche de places de parking est une tâche fastidieuse, consommatrice de temps et polluante.
Objectifs
Pour remédier à ce problème, nous proposons de réaliser un ensemble composé :
- D'un capteur de détection de voiture :
- D'un système de transmission basé sur une carte "maison" (µC : CC430) déjà existante ;
- D'un système de stockage et de visualisation des places libres.
Préparation du projet
Cahier des charges
Choix techniques : matériel et logiciel
Liste des tâches à effectuer
Calendrier prévisionnel
Réalisation du Projet
Semaine du 17/09
En attendant un entretien avec les encadrants de projet pour mettre au point un cahier des charges précis, plusieurs recherches bibliographiques ont été effectuées.
Plusieurs solutions existent déjà pour effectuer la détection de voitures dans un parking, axées autours de trois méthodes :
- Détection avec un capteur par place
- Détection avec des capteurs en entrée et en sortie de parking
- Détection par caméra
Chaque solution présente des avantages et des inconvénients, qu'il faudra analyser afin de choisir la solution adaptée.
Le solution avec un capteur par place est précise et indique facilement et précisément l'occupation des places. Elle est de plus peu coûteuse en énergie par capteur, la détection ne devant pas être effectuée en permanence. En revanche cette méthode est coûteuse car nécessite un capteur par place, et implique une remontée d'informations complexe à mettre en place (sans fil ou filaire).
La solution avec des capteurs en entrée et en sortie est peu coûteuse et permet une remontée d'informations assez simple (peu de données à transmettre). En revanche elle n'est pas précise et indique seulement le nombre de voitures/places restantes dans le parking et non les places précises restantes. Elle est de plus coûteuse en énergie pour les capteurs, devant être actifs très souvent afin de ne pas manquer une voiture.
La solution par caméra est économe en matériel, une caméra pouvant être suffisante pour un parking entier, et permet de détecter précisément les places restantes. Elle n'est cependant pas pratique pour un parking souterrain, consomme beaucoup d'énergie par capteur et nécessite des capacités de traitement d'images hors de la portée d'un cc430. Elle peut cependant utiliser un serveur pour effectuer les calculs.
Des liens vers les études sont disponibles dans la partie Documentation
L'entretien avec les encadrant à de plus été préparer afin de pouvoir déterminer u cahier des charges précis. Les questions suivantes doivent être abordées :
- Objectifs précis du projet
- Localisation du parking, type de parking
- Durée de vie minimale des capteurs
- Type de détection voulu
- Budget
- Design du boiter du capteur
- Utilisation de RIOT imposée
- Quel type d'affichage
- Alimentation des capteurs
- Utilisation d'un serveur
- Utilisation du protocole RPL
Semaine du 24/09
Suite au rendez-vous du 21/09, les questions suivantes ont été écartées :
- Durée de vie minimale des capteurs
- Type de détection voulu
- Budget
- Design du boitier du capteur
- Quel type d'affichage
- Alimentation des capteurs
- Utilisation d'un serveur
En effets ces questions ne sont pas prioritaires et n'entreront dans l'équations que si le projet avance très vite.
- Objectifs précis du projet
L'objectif principal du projet est de déployer un réseau d'objets sans fils possédant des capacités de routage dynamique.
- Localisation du parking, type de parking
Le parking d'étude sera le parking de l'IRCICA, mais des essais en condition réel seront intéressant mais ne sont pas une priorité
- Utilisation du protocole RPL
Le routage dynamique devra préférentiellement être mis en place en respectant le protocole RPL
- Utilisation de RIOT imposée
RIOT OS n'est en aucun cas imposé, et l'utilisation d'un autre OS (Contiki a été évoqué) est parfaitement envisageable, voir même tenter une appproche sans OS.
Ayant déjà travaillé avec RIOTOS et le CC430, je sais qu'il peut y avoir des problème concernant la taille et l'occupation en RAM des OS. Ma première mission est donc de déterminer si le CC430 et ses 32ko de ROM et 4ko de RAM permettent l'utilisation des implémentations du protocoles RPL des différents OS de l'embarqués, ou si d'autres options plus simple (routage statique voir simple broadcast) sont à privilégier.
Semaine du 01/10
Durant cette semaine j'ai étudié l'impact en mémoire (ROM et RAM) des deux OS les plus adaptés aux premiers abord pour le projet : Contiki et RIOT. Les deux OS vantent une utilisation en ROM et RAM faible (environ 10ko de ROM et 2 ko de RAM), ce qui conviendrait parfaitement au besoin du projet. Malheureusement, ces tailles annoncées ne sont vrai que pour l'OS seul dans la plus grande majorité des cas, que ce soit pour RIOT ou Contiki. Le cc430 n'est pas supporté par Contiki, mais le Tmote Sky l'est, et est basé sur un msp430 de chez TI, comme le cc430. Utiliser le Tmote Sky afin d'établir la taille en ROM et RAM prise par les sources semble une option valide. Lors de la compilation des sources d'exemples RPL pour Contiki avec le Tmote Sky, sans modification au préalable de l'exemple, on option (grâce à la commande size sur linux) :
text | data | bss |
---|---|---|
43380 | 310 | 6958 |
soit 43380 octets de ROM utilisé et 310+6958=7268 octets de RAM utilisés, ce qui est bien supérieur à ce qui est disponible.
Du coté de RIOT, je savais que le programme d'exemple ne tenait pas dans le cc430, en effet il y a une surcharge de RAM de 2426 octets et de ROM de 32956 octets.
Dans les deux cas il est possible de réduire la taille de ce programme en retirant ce qui ne nous concerne pas.
De plus, afin d'être sur que le compilateur optimise la taille de l'exécutable, j'ai regardé la commande final des makefile de RIOT et Contiki en ajoutant
SHELL="sh -x"
à la fin de la commande make.
L'une des option de gcc pour optimisé en taille est l'option -0s, et cette option est bien présente pour les deux OS. Les gains en places ne peuvent donc pas être effectués grâce aux options du compilateur, mais doivent être effectués auprès du code source.
Les optimisations possibles chez Contiki se font en ajoutant un fichier project-conf.h dans le répertoire de l'exemple et d'y ajouter des #define pour restreindre certaines fonctionnalités.
Du coté de RIOT, il faut modifier le makefile et le code d'exemple.
Semaine du 08/10
Cette semaine a été consacrée à l'exploration des possibilités de réductions de taille des sources.
Contiki
Le programme d'exemple étant assez simple, il n'y à pas beaucoup de chose à modifier pour en réduire la taille. Il faut donc jouer sur les paramètres du fichier project-conf.h. Les paramètrs impactant la taille que nous pouvons modifier sont les suivants :
#define QUEUEBUF_CONF_NUM 4 #define NBR_TABLE_CONF_MAX_NEIGHBORS 8 #define NETSTACK_MAX_ROUTE_ENTRIES 0 #define UIP_CONF_BUFFER_SIZE 100 #define SICSLOWPAN_CONF_FRAG 0 #define PROCESS_CONF_NO_PROCESS_NAMES 1 #define UIP_CONF_TCP 0
avec QUEUEBUF_CONF_NUM le nombre de message que doit pouvoir contenir le buffer de message. Plus cette varaible est faible, moins le programme prend de place en RAM mais plus il y a un risque d'engorgement. NBR_TABLE_CONF_MAX_NEIGHBORS correspond aux nombres de voisins que le nodes peut gérer. Plus cette valeur est importante, plus le réseau est flexible, mais plus cela prend de la place en RAM. NETSTACK_MAX_ROUTE_ENTRIES correspond au nombre de route sauvegarder dans la table rde routage. Plus cette valeur est importante, plus le réseau est réactif, mais comme nous sommes en mode "non storing mode", cette valeur doit être mise à zéro. UIP_CONF_BUFFER_SIZE correspond à la taille en octet du buffer de message IPv6. La taille minimal pour l'intéropérabilité est de 1280 octets, mais si le réseau n'a pas vocation à être mis en relation avec d'autre réseau IPv6, comme dans notre cas, la taille de ce buffer peut être réduit. Comme un paquet RPL à une taille maximale d'environ 32 octets et l'entête IPv6 d'envoron 40 octets, une taille de buffer de 100 est suffisante. SICSLOWPAN_CONF_FRAG correspond à l'utiliksation ou non du méchanisme de fragmentation des messages. Comme nos message seront normalement très court (moins de 10 octets), ce mechanisme ne devrait pas être utile et donc peut être retirer. Cela gagne de la place en RAM et en ROM. PROCESS_CONF_NO_PROCESS_NAMES correspond au mechanisme de nommage des processus créés dans Contiki. Comme il n'y aura pas beaucoup de processus et qu'ils ne seront pas lu par un humain lors du fonctionnement, désactiver ce mechanisme permet de gagner de l'espace en ROM principalement. UIP_CONF_TCP correspond à l'utilisation du mechanisme TCP. Comme le protocole UDP correspond à nos besoin, il n'est pas nécessaire d'intégrer les mechanismes de TCP.
De plus, dans le programme d'exemple, il y a de plus un mechanisme qu'il est possible de désactiver : les logs. En effet, Contiki propose un système avancé de log avec plusieurs niveaux permettant d'observer finement ce qu'il se passe durant le fonctionnement de l'OS. Passer de
#define LOG_LEVEL LOG_LEVEL_INFO
à
#define LOG_LEVEL LOG_LEVEL_NONE
permet aussi d'économiser un peu d'espace.
Avec ces modification, on arrive à
text | data | bss |
---|---|---|
41174 | 296 | 3492 |
On arrive donc en dessous des 4ko de RAM utilisée, mais il reste encore environ 10ko de ROM en trop.
RIOT
Comme je savais depuis mon projet IMA4 que RIOT occupait trop de place sur le cc430, j'ai pu rapidement tester des modifications afin de déterminer la taille prise en nmémoire. J'ai donc compilé le projet d'exemple gnrc_networking avec une carte proche du cc430 mais ayant plus de ROM et de RAM, le Tmote sky, ou telosB. Le resultat, sans modification préalable n'est pas encourageant : la compilation échoue car il y a un overflow de ROM de 14ko, sur les 48k disponible. La compilation n'indique pas d'overflow en RAM utilisé, mais le Tmote Sky ayant 10ko de RAM, ce n'est pas une chose à retenir car le cc430 n'en a que 4ko.
En modifiant le programme principale pour qu'il ne fasse rien, et en retirant dans le makefile l'inclusion de sources non nécessaire à notre projet (comme un shell), on arrive à un overflow de 7ko de ROM.
Avec ces même modifications, une compilation avec comme cible le cc430 indique un overflow en RAM de 1.6Ko de RAM.
Semaine du 15/10
J'ai décidé d'orienter principalement mes efforts vers l'OS Contiki, car je trouve que leurs sources sont plus facilement lisible que celles de RIOT, et leur programme d'exemple pour former un réseau RPL est plus facilement réutilisable, n'utilisant pas une couche shell contrairement à RIOT.
En étudiant les sources du Tmote Sky que j'utilise comme références, j'ai trouvé que le port était assez fourni, permettant de gérer beaucoup d'aspect du microcontroleur, avec entre autre des modules pour les GPIO, l'UART, le SPI, l'I2C et les capteurs de la carte. Le Tmote Sky possède aussi un module d'indentification unique, le ds2411. Ce module permet d'obtenir de manière matériel un identifiant unique pour chaque node. Pour le début du projet, il n'y a pas besoin de ces modules, donc il est possible de les retirer du makefile et des différentes sources les utilisant.
Ce faisant, on arrive à :
text | data | bss |
---|---|---|
35762 | 210 | 3296 |
On arrive proche des 32ko de ROM du cc430. Afin d'avoir de la marge, j'estime à 2ko de ROM nécessaire pour utiliser les sources du cc430 disponible, donc je pense qu'il faut réduire l'utilisation en ROM a 30ko.
En retirant la gestion propre à Contiki des LED et le calcul du chiffrement AES de manière logiciel, on descend à 35370 octets de ROM.
Les paramètres du fichiers projet-conf.h que l'on peut encore modifier sont :
QUEUEBUF_CONF_NUM NBR_TABLE_CONF_MAX_NEIGHBORS
Malheureusement, ces variables n'ont qu'un impact fort sur la RAM, et leur impact est très faible sur la ROM.
A partir de ce point je n'ai pas d'autre pistes pour réduire de manière significative l'utilisation en ROM. En accord avec mes encadrants, il a été décidé que si l'on veut utiliser les cc430 disponibles, il va falloir se passer d'OS et extraire les parties de la couches réseau de Contiki ou de RIOT dont nous avons besoin (principalement MAC, UDP et RPL).
Contiki met en place des méchanismes très pratique afin d'analyser la mémoire utilisé par les sources graces aux commandes (expliquée ici https://github.com/contiki-ng/contiki-ng/wiki/Tutorial:-RAM-and-ROM-usage) :
make <nom-du-projet>.ramprof
pour observer la taille de chaque variable en RAM. Cette commande effectue en fait la commande
msp430-nm -S -td --size-sort <nom-du-projet>.<cible> | grep -i " [abdrw] " | cut -d' ' -f2,4
(ici
msp430-nm -S -td --size-sort udp-client.sky | grep -i " [abdrw] " | cut -d' ' -f2,4
)
et
make <nom-du-projet>.flashprof
pour observer la taille de chaque fonction en ROM. Cette commande exécute en fait la commande :
msp430-nm -S -td --size-sort <nom-du-projet>.<cible> | grep -i " [t] " | cut -d' ' -f2,4
(ici
msp430-nm -S -td --size-sort udp-client.sky | grep -i " [t] " | cut -d' ' -f2,4
)
Un extrait du resultat de la seconde commande donne
{...} 00000384 nbr_table_add_lladdr 00000384 uip_icmp6_error_output 00000396 frame802154_parse 00000432 rpl_process_dio 00000476 transmit_from_queue 00000558 rpl_icmp6_dio_output 00000612 ns_input 00000680 dio_input 00000808 rpl_ext_header_update 00001196 uip_process 00001540 input 00001810 output
On remarque que les deux plus grosses fonctions sont "input" et "output".
On peut déterminer leur origine avec les commandes suivantes :
$ nm -oStd obj_sky/*.o | grep " output$" obj_sky/sicslowpan.o:00000000 00001810 t output $ nm -oStd obj_sky/*.o | grep " input$" obj_sky/sicslowpan.o:00000000 00001540 t input
On remarque que ces fonctions proviennent du module "sicslowpan" (6LoWPAN). 6LoWPAN (IPv6 over Low-Power Wireless Personal Area Networks) définit des méchanismes d'encapsulation et de compression des headers IPv6 pour objets contraints, et donc on ne peut se séparer de ce module. 6LoWPAN sert de plus de base pour le protocole de routage RPL, et est donc indispensable.
Afin d'être sur que les sources de Contiki en rapport avec la couche MAC, avec 6LoWPAN et RPL (entre autres) pouvaient effectivement tenir dans les 32ko du cc430, j'ai décidé d'estimer la taille totale de ces sources.
Pour ce faire, j'ai d'abord conçu des scripts se basant sur les commandes précedemment citées. J'ai enregistré le résultat de la commande
make udp-client.flashprof
dans un fichier, puis ajouté à chaque ligne correspondant à une fonction la localisation de cete fonction grâce au script suivant :
#!/bin/bash obj=~/Documents/PFE/baseSource/Contiki-NG/contiki-ng/examples/rpl-udp/obj_sky/*.o file=~/Documents/PFE/Redaction/outputFlash.txt file2=~/Documents/PFE/Redaction/funcLocations.txt rm $file2 touch $file2 cptline=0 while IFS= read -r cmd; do if [ $cptline -ge 2 ]; then nom=$(echo $cmd |cut -d' ' -f2) line= taille=$(echo $cmd |cut -d' ' -f1) location=$(nm -oStd $obj | grep " $nom$") location=$(echo $location |cut -d' ' -f1) line=$taille' '$nom$'\t'$'\t'$location echo ' '$taille' '$nom$'\t'$'\t'$location >> $file2 else cptline=$(($cptline + 1)) fi done < "$file"
Cela donne une résultat du genre :
00000002 drop_route /home/nenth/Documents/PFE/baseSource/Contiki-NG/contiki-ng/examples/rpl-udp/obj_sky/rpl.o:00000000 00000002 energest_flush /home/nenth/Documents/PFE/baseSource/Contiki-NG/contiki-ng/examples/rpl-udp/obj_sky/clock.o: {...}
J'ai ensuite ajouté à chaque ligne un champs au debut de celle ci contenant 1 ou 0 en fonction de la localisation de la fonction, 1 si la fonction semble être dans un module réseau, 0 sinon.
Ensuite j'ai exécuté le script suivant qui en, fonction du premier champs à 1 ou 0 calcul la taille totale de toutes les fonctions :
#!/bin/bash file=~/Documents/PFE/Redaction/funcLocationsAppend.txt total=0 while IFS= read -r cmd; do isAddable=$(echo $cmd |cut -d' ' -f1) if [ $isAddable -eq 1 ]; then total=$(($total + $(echo $cmd |cut -d' ' -f2 | sed -e 's/^0*//'))) fi echo $total done < "$file"
Ici le sed permet de transformer le champs de type
00000384
en
384
car pour le shell un nombre commençant par 0 est considéré comme en base 8, et donc les chiffres 8 et 9 font planter l'addition.
Le résultat de ce script donne une taille totale de 28564 octets. A première vue, il reste environ 3k pour le reste du projet, ce qui est relativement peu, mais cela doit être possible.
Extraction
A partir des fichiers extraits, on trouve 9 fichier avec le mot clé PROCESS qui sert identifier tous ce qui se rapporte aux processus. Par exemple, PROCESS permet de déclarer des pocessus qui seront lancés :
#if PROCESS_CONF_NO_PROCESS_NAMES #define PROCESS(name, strname) \ PROCESS_THREAD(name, ev, data); \ struct process name = { NULL, \ process_thread_##name } #else #define PROCESS(name, strname) \ PROCESS_THREAD(name, ev, data); \ struct process name = { NULL, strname, \ process_thread_##name } #endif
Comme déterminé auparavant, un processus avec un nom est plus gourmand en mémoire qu'un processus ssans, on ne retient que
#define PROCESS(name, strname) \ PROCESS_THREAD(name, ev, data); \ struct process name = { NULL, \ process_thread_##name }
Les fichiers à modifier a première vue sont
netstack.c netstach.h resolv.c resolv.h simple-udp.c tcpip.c tcpip.h udp-client.c udp-socket.c
J'ai commencé à explorer les occurence et l'utilité de chaque macro dans chaque fichier.
Dans netstack.c, on rencontre 3 fois le mot clé PROCESS, mais ne fait partie que de nom de variables.
Dans resolv.c, on rencontre 1 fois le mot clé PROCESS, mais ne fait partie que de nom de variables.
Fichier | Nombre d'occurence de "PROCESS" | Importance de "PROCESS" |
---|---|---|
netstack.c | 3 | Aucune |
netstack.h | 1 | aucune |
resolv.c | 18 | forte |
resolv.h | 1 | aucune |
simple-udp.c | 10 | forte |
tcpip.c | 18 | forte |
tcpip.h | 1 | aucune |
udp-client.c | 6 | moyenne |
udp-socket.c | 11 | forte |
Les principales macro rencontrés sont les suivants :
PROCESS PROCESS_THREAD PROCESS_BEGIN PROCESS_WAIT_EVENT_UNTIL PROCESS_END PROCESS_CONTEXT_BEGIN PROCESS_WAIT_EVENT PROCESS_CURRENT
Il faut de comprendre ce que font ces macro avant d'entamer l'extraction des sources.
Toutes ces macro sont définis dans le fichier process.h
.
Toutes ces macros rendent le code lisible dans un contexte de processus lancés en parallèles mais rendent l'extraction plus complexe.
PROCESS
permet de simplement déclarer un thread et une structure associer à ce thread.
PROCESS_THREAD
permet de définir le thread déclaré par PROCESS_THREAD
La fonction des autres macro est pour le moment moins clair.
Pour essayer de voir plus clair, j'ai ajouté l'option de compilation de gcc -E
dans le makefile de Contiki pour que gcc s'arrête après l'étape de précompilation.
Pour exemple, l'option -E
transforme la définition du thread de tcpip (localisé dans tcpip.c)
PROCESS_THREAD(tcpip_process, ev, data) { PROCESS_BEGIN(); #if UIP_TCP memset(s.listenports, 0, UIP_LISTENPORTS*sizeof(*(s.listenports))); s.p = PROCESS_CURRENT(); #endif tcpip_event = process_alloc_event(); #if UIP_CONF_ICMP6 tcpip_icmp6_event = process_alloc_event(); #endif /* UIP_CONF_ICMP6 */ etimer_set(&periodic, CLOCK_SECOND / 2); uip_init(); #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.init(); #endif /* Initialize routing protocol */ NETSTACK_ROUTING.init(); while(1) { PROCESS_YIELD(); eventhandler(ev, data); } PROCESS_END(); }
en
static char process_thread_tcpip_process(struct pt *process_pt, process_event_t ev, process_data_t data) { { char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} switch((process_pt)->lc) { case 0:; tcpip_event = process_alloc_event(); etimer_set(&periodic, 128UL / 2); uip_init(); rpl_lite_driver.init(); while(1) { do { PT_YIELD_FLAG = 0; (process_pt)->lc = 837; case 837:; if(PT_YIELD_FLAG == 0) { return 1; } } while(0); eventhandler(ev, data); } }; PT_YIELD_FLAG = 0; (process_pt)->lc = 0;; return 3; }; }
On remarque bien la disparition des blocks #if
, mais le problème vient du block switch
En effet, on remarque une structure très étrange du code : nous avons un case 837
dans le block même du case 0
. De plus, on trouve un do {...} while(0)
dans un while(1)
Afin de continuer je dois comprendre le fonctionnement de cette structure.
Protothread
Après avoir passer un certain temps a essayer de comprendre le fonctionnement de la précedente structure, j'ai compris plus en détail son fonctionnement et surtout le fonctionnement de Contiki.
Contrairement aux OS traditionnels et à RIOT, Contiki n'utilise pas de threads classiques, mais utilise des "protothreads".
J'ai compris le fonctionnement des protothreads grâce au document publié par Adam Dunkels, Oliver Schmidt, Thiemo Voigt et Muneeb Ali : "Protothreads : Simplifying Event-Driven Programming of Memory-Constrained Embedded Systems".
Les protothreads n'utilisent pas de mechanisme de sauvegarde de contexte, mais stockent simplement l'endroit où le thread s'est arrété. En effet, tous les protothreads tournent dans une et unique pile, contrairement aux threads classiques qui utilisent une pile par thread. L'avantage des protothreads est que du coup la consommation en RAM est très faible, ne stockant que 2 octets en RAM en plus, peut importe la taille du thread.
Les protothreads sont basés sur un fonctionnement similaire à ce qui est appelé "La machine de Duff". Ils ont été développés afin de faciliter le développement d'application sur des systèmes très contraint en mémoire, comme notre cc430. L'objectif est de réduire, voir supprimer, les machines à états très courantes dans la programmation orienté évennement très courante dans les systèmes contraints, mais aussi très complexe.
Grâce à l'utilisation peu évidente du block switch
il est possible de continuer l'exécution d'un protothread à partir d'un point précis de celui ci : c'est le méchanisme appelé de "local continuation".
L'inconvéniant majeur des protothreads est l'augmentation de l'utilisation en ROM.
Selon le document de Adam Dunkels & co, l'augmentation en ROM est variable en fonction de la complexité, pouvant atteindre plus de 70% d'augmentation dans les pires cas, et environ 15% dans les cas moyens. En revanche, il y a un gain énorme en RAM, passant de 18 octets utilisés en RAM pour un thread classique à 2 octets en protothread, soit une réduction de 89%.
L'utilisation des protothread est donc un compromis entre occupation en RAM, occupation en ROM et complexité de code.
Il est a noté que les protothread empêche l'utilisation du switch
dans un thread et que l'utilisation de variable locale est très limité, ces variables étant perdu au changement de "contexte".
L'idéal est que j'arrive à retirer la couche des protothreads pour gagner de la place en ROM, mais cela risque d'être complexe de repasser sur une programmation orienté évènement avec une machine a états complexe.
uIP
En parrallèle des recherches effectuées sur le fonctionnement des protothreads, j'ai continué à chercher des informations sur la couche IP de Contiki, qui a apparemment été extraite plusieurs fois. Je n'ai pas réussi a trouver des informations à ce sujet, mais je trouvé la source de la couche IP de Contiki : une implémentation réduite de la couche IP par Adam Dunkels.
Cette implémentation a été par la suite implémentée dans Contiki, ce qui est pratique car cela est la base de mon travail.
Adam Dunkels propose deux version de son implémentation : uIP (microIP) et lwIP (lightweightIP).
Liste des features implémentées par uIP et lwIP :
Feature | uIP | lwIP |
---|---|---|
IP and TCP checksums | x | x |
IP fragment reassembly | x | x |
IP options | ||
Multiple interfaces | x | |
UDP | x | |
Multiple TCP connections | x | x |
TCP options | x | x |
Variable TCP MSS | x | x |
RTT estimation | x | x |
TCP flow control | x | x |
Sliding TCP window | x | |
TCP congestion control | x | |
Out-of-sequence TCP data | x | |
TCP urgent data | x | x |
Data buffered for rexmit | x |
Comparatif des tailles :
uIP
Fonction | Taille (octet) |
---|---|
checksum | 712 |
IP, ICMP, TCP | 4452 |
Total | 5164 |
lwIP
Fonction | Taille (octet) |
---|---|
Gestion de la mémoire | 3142 |
Interfaces Réseaux | 458 |
checksum | 1116 |
IP, ICMP, TCP | 14840 |
Total | 21756 |
Comme l'application que l'on souhaite réalisé ne nécessite pas beaucoup d'interfaces (une suffit), avec des paquet courts, on peut se passer de controle de congestion si besoin entre autre, l'implémentation uIP peut nous convenir.
Partir sur uIP et les sources déjà existantes de Contiki parait une bonne option. Malheureusement uIP et lwIP fonctionnenet sur le principe des protothreads aussi, ce qui risque d'être compliqué.
RPL
Avant de continuer à explorer la couche IP de Contiki et l'implémentation de uIP, j'ai voulu voir comment fonctionnait la couche RPL de Contiki.
Contiki propose 2 versions de RPL : rpl-classic
et rpl-lite
.
rpl-classic
propose une implémentation plus complète et robuste mais rpl-lite
propose une implémentation plus légère. Comme nous sommes contraint par la taille, je suis parti sur l'utilisation de RPL-lite.
Toute la bibliothèque RPL de Contiki se trouve dans le répertoire contiki-ng/os/net/routing/rpl-lite
Cette bibliothèque comprend les fichiers suivants :
rpl.c rpl-conf.h rpl-const.h rpl-dag.c rpl-dag.h rpl-dag-root.c rpl-dag-root.h rpl-ext-header.c rpl-ext-header.h rpl.h rpl-icmp6.c rpl-icmp6.h rpl-mrhof.c rpl-nbr-policy.c rpl-neighbor.c rpl-neighbor.h rpl-of0.c rpl-timers.c rpl-timers.h rpl-types.h
J'ai extrait la liste de toutes les fonctions extérieures à ces fichiers appelées par les fonctions de la bibliothèque RPL-lite et j'ai commencé à les explorer pour voir si elles étaient reliées aux protothreads.
Il s'avère que plusieurs fonctions appellent des fonctions définies dans sys/ctimer.h/c
qui lancent des protothreads.
Comme uIP et RPL utilisent les protothreads, je penses que le mieux est de garder au final les protothread et conserver un semblant d'architecture de Contiki.
Documentation
Documents Rendus
Rapport intermédiaire : Fichier:RapportIntermédiaire.pdf
Présentation intermédiaire : Fichier:SoutenanceIntermédiareDiapoP13.pdf