Go Down

Topic: [résolu] 2 libraries utilisées: Conflit PSTR ? (Read 2 times) previous topic - next topic

atlas2003

Nov 14, 2012, 04:55 am Last Edit: Nov 18, 2012, 02:27 am by atlas2003 Reason: 1
Bonjour / Bonsoir

Je suis en train de travailler sur mon premier vrai projet Arduino depuis maintenant quelques mois.
J'ai vraiment TRÈS bien progressé mais là, depuis 2 jours, je suis bloqué. Habituellement, je cherche jusqu'a ce que je trouve la solution par moi même (généralement en me documentant) car c'est comme ca que j'apprend le mieux. Mais ce soir, j'avoue, je suis à court d'idée. Je me permet donc de vous soumettre mon problème.

J'utilise dans mon projet principalement 2 libraries: ethercard (module ENC28j60) et RF24 ( nRF24L01)
J'ai deja fais pas mal de tests avec ces deux libraries ensemble et je n'ai jamais eu de problème auparavant. Elles fonctionnent très bien toutes les deux.

Voici ce que je fais mon projet en mode simplifié:
J'ai un serveur web qui tourne sur l'arduino, il recoit une requete, il recupère une valeur passé dans la querystring et il envoit cette valeur par onde radio via le RF24 à un autre arduino.
Jusque la cela fonctionnait bien.

Je voudrais maintenant que ma value recu soit aussi en même temps envoyé a PACHUBE (ou devrais je dire COSM maintenant)

Avec la librarie Ethercard, il y a un exemple pour envoyer des data sur PACHUBE. Je l'ai testé, ca fonctionne super. J'ai donc repris ce bout de code et l'ai ajouté a mon code principal. Mais depuis que j'ai fais ca, je suis impossible de compiler mon code, j'ai toujours 4 erreurs:
Code: [Select]
error: __c causes a section type conflict

qui apparait vis à vis de ce morceau de code:
Code: [Select]
   Stash::prepare(PSTR("PUT http://$F/v2/feeds/$F.csv HTTP/1.0" "\r\n"
                       "Host: $F" "\r\n"
                       "X-PachubeApiKey: $F" "\r\n"
                       "Content-Length: $D" "\r\n"
                       "\r\n"
                       "$H"),
           website, PSTR(FEED), website, PSTR(APIKEY), stash.size(), sd);


C'est le PSTR qui pose problème.

J'ai essayé d'enlever le plus d'info dans mon code pour essayer de trouver l'endroit qui cause problème et je me suis rendu compte que les deux libraries déclarent PSTR

RF24Config.h pour la lib RF24

Code: [Select]
// Avoid spurious warnings
#if 1
#if ! defined( NATIVE ) && defined( ARDUINO )
#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))
#undef PSTR
#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))
#endif
#endif

// Progmem is Arduino-specific
#ifdef ARDUINO
#include <avr/pgmspace.h>
#define PRIPSTR "%S"
#else
typedef char const char;
typedef uint16_t prog_uint16_t;
#define PSTR(x) (x)
#define printf_P printf
#define strlen_P strlen
#define PROGMEM
#define pgm_read_word(p) (*(p))
#define PRIPSTR "%s"
#endif


Et dans tcpip.cpp pour la lib Ethercard

Code: [Select]
// Avoid spurious pgmspace warnings - http://forum.jeelabs.net/node/327
// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))
#undef PSTR
#define PSTR(s) (__extension__({static prog_char c[] PROGMEM = (s); &c[0];}))



J'ai essayé de me documenter sur cela mais cela depasse mes compétences malheuresement.
Je comprend l'utilité de PROGMEM (après mettre documenté)... J'imagine que PSTR c'est pour dire "print string" et que par conséquent, j'imagine que ca sert à "printer" une valeur qui etait setté avec progmem...
Mais à part cela...

J'ai fais pas mal de test:
-Supprimer ces defines
-Laisser seulement ceux de RF24
-Laisser seulement ceux de Ethercard
-Supprimer les deux et inserer juste ceux de ethercard à meme mon fichier ino
-Remplacer celui de RF24 par exactement le même que celui de ethercard.

Je suis à court d'idée. Si jamais quelqu'un a une piste, je suis preneur!

Je met le code source de mon programme qui ne compile pas en l'état des lieux:

https://dl.dropbox.com/u/138037/web/code.ino


Et voici les liens vers les deux libs en question:
https://github.com/maniacbug/RF24
https://github.com/jcw/ethercard

Merci beaucoup

barbudor

Bonjour

PSTR ne sert pas à faire un print mais c'est une macro qui simplifie la déclaration d'une chaine de caractère qui devra rester en mémoire Flash.

En effet, par défaut, les mémoires programmes (flash) et données (ram) d'un ATmega sont différents et ne peuvent pas être accédés de la même façon (cherche la différence entre model VonNeuman et modèle Harvard pour en savoir plus. l'atmega suit le modèle Harvard).
Ce qui veut dire qu'au début du programme (avant le setup) il existe un code qui recopie les chaines de caractères de la flash dans la RAM.
C'est evidemment idiot car cela consomme de la RAM pour des informations qui sont constantes.

Pour cela, tu peux forcer le compilateur a laisser des chaines de caractères en Flash mais il faut que derrière les fonctions sachent aller chercher la chaine de caractère en flash plutot qu'en RAM. Ainsi par exemple la fonction sprintf( destination, format, ....) se sait pas aller chercher la chaine de format ailleurs qu'en RAM. Si tu utilises sprintf( result, PSTR("%u"), 5 ) ca ne marcheras pas. Il existe pour cela une fonction spéciale sprintf_P qui sait aller chercher la chaine de format en Flash (mais pas en RAM...)
Serial.print() au contraire sait faire la différence et aller chercher la chaine de caractère aussi bien en RAM qu'en flash.

Voila pour le principe.

Maintenant pour en revenir à ton problème...
Ces lib redéfinissent la macro PSTR() d'une façon légèrement différent de la façon standard (qui est dans avr/pgmspace.h) afin d'éviter des warning que la version standard laisse passer à la compilation.

Mais je pense que le problème ne vient pas de là mais de ta façon de coder :
Code: [Select]
Stash::prepare(PSTR("PUT http://$F/v2/feeds/$F.csv HTTP/1.0" "\r\n"
                        "Host: $F" "\r\n"
                        "X-PachubeApiKey: $F" "\r\n"
                        "Content-Length: $D" "\r\n"
                        "\r\n"
                        "$H"),
            website, PSTR(FEED), website, PSTR(APIKEY), stash.size(), sd);


Le problème devrait apparaitre aussi bien avec 1 ou 2 lib car la syntaxe utilisée est incomplète/erronée.
En effet d'un point de vue C, PSTR étant une macro doit tenir sur une seule ligne !
Hors ta façon de coder la chaine de caractères sur plusieurs lignes est compatible d'un appel de fonction mais pas de l'utilisation d'une macro.
Il existe en C un moyen d'indiquer qu'une même ligne de code se poursuit sur plusieurs lignes de l'éditeur de texte. Pour cela il faut ajouter un "backslash" \ sans autre caractères après à la fin de la ligne :

Code: [Select]
Stash::prepare(PSTR("PUT http://$F/v2/feeds/$F.csv HTTP/1.0" "\r\n" \
                        "Host: $F" "\r\n"  \
                        "X-PachubeApiKey: $F" "\r\n"  \
                        "Content-Length: $D" "\r\n"  \
                        "\r\n"  \
                        "$H"),
            website, PSTR(FEED), website, PSTR(APIKEY), stash.size(), sd);


devrait marcher
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

atlas2003

Bonjour

Merci pour tes explications. Ca m'aide beaucoup.
Cependant le script fonctionne si j'enleve tout ce qui est relatif aux RF24.
J'ai quand même essayé ce que tu m'a donné, mais malheuresement cela fait la même erreur.

atlas2003

Bonsoir

Personne n'aurait une 2eme idée? J'ai encore fais plein de nouvelle recherche, sur les macro, mais rien de concret pour le moment :(

Merci

barbudor

Je suis en déplacement professionnel cette semaine donc pas trop le temps mais j'essayerais ce week-end si personne d'autre ne trouve la solution d'ici là.

Pourrais tu poster le INO minimum qui permet de reproduire le problème ainsi que le lien vers les site où tu as téléchargé les lib utilisée ?
Ceci pour être sur de tester dans les mêmes conditions que toi.
Ton IDE Arduino est bien la dernière v1.0.1 ?
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

Go Up