Go Down

Topic: [résolu] __vector_default' / `__vector_7' (Read 3479 times) previous topic - next topic

manuo1

Apr 27, 2015, 04:16 pm Last Edit: May 01, 2015, 11:28 am by manuo1
Bonjour,

Je suis sur un sketch domotique avec une arduino mega 2560 + carte ethernet qui à certains moments envoi des Mail.

J'ai une fonction basique qui le fait très bien, je copie et je modifie juste le nom de la fonction, le corps et sujets du message.

J'ai donc actuellement 3 fonction pour l'envoi de 3 mail différents et je dois en rajouter une pour un quatrième mail.

Je reprend le même principe avec un copié collé, je change le nom de la fonction et indique un sujet et corps de message générique pour tester.  

Mais voila qu'arrive une Erreur lors de la compilation :

Quote
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o: In function `__vector_default':
(.vectors+0x1c): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_7' defined in .text section in c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o
Je ne peux pas mettre tout le code complet mais la partie qui pose problème est celle là :

Code: [Select]

void Envoi_email_Historique(){

if (client_MAIL.connect("smtp.sfr.fr", 25)){ // connexion au serveur "smtp.sfr.fr" sur le port 25
  
   delay(1800); // attend une réponse
   client_MAIL.println(F("EHLO localhost")); // dit bonjour
   delay(900);
   client_MAIL.println(F("mail from: <xx@sfr.fr>"));   // expéditeur
   delay(900);
   client_MAIL.println(F("rcpt to: <xx@sfr.fr>")); // destinataire
   delay(900);
wdt_reset();
   client_MAIL.println(F("DATA"));
   delay(900);
   client_MAIL.println(F("To: xx@sfr.fr")); // destinataire en-tête du message
   delay(900);
   client_MAIL.println(F("From: xx@sfr.fr")); // nom de l'expéditeur en-tête du message
   delay(900);
   client_MAIL.print(F("Subject: ")); // objet du message
   client_MAIL.println("Sujet"); // objet du message
   delay(900);
   client_MAIL.println(F("")); // ligne vide
   delay(900);
wdt_reset();  
   client_MAIL.println("corp"); // ecrit le corp du message
   delay(900);
   client_MAIL.println(F("")); // ligne vide
   delay(900);
   client_MAIL.println(F(".")); // termine le mail
   delay(900);
   client_MAIL.println(F("QUIT")); // stop la connexion
   client_MAIL.println();
   client_MAIL.stop();      // Stop la connexion
  }  
}



Si je supprime cette partie le code compile normalement.
Le message d'erreur n'est pas clair et rien trouvé sur Google ou sur le forum.

Quelqu'un à une idée

fdufnews

Est-ce spécifiquement ce morceau de code qui pose problème ou bien le retrait de n'importe quel autre supprime aussi l'erreur?
Ce pourrait être un code trop volumineux qui utiliserait trop de Flash avec les messages placés dans celle-ci.

manuo1

#2
Apr 27, 2015, 05:00 pm Last Edit: Apr 27, 2015, 05:00 pm by manuo1
Oui exact, quand je supprimes quelques lignes "client_MAIL.println(F" la compilation passe.

Je pensais que la mémoire Flash était suffisante sur ma méga et le compilateur  m'indique :

Quote
Le croquis utilise 83 516 octets (32%) de l'espace de stockage de programmes. Le maximum est de 258 048 octets.
Est-ce que je me trompe et que ce n'est pas la même mémoire ?
Ou alors est-ce que la macro F masque des octets utilisé ?

manuo1

#3
Apr 28, 2015, 12:40 am Last Edit: Apr 28, 2015, 12:41 am by manuo1
C'est effectivement plus compliqué que cela, j'ai refait le tour des mémoires etc... cela ne semble pas venir de là

J'utilise la version 1.5.6-r2 mais je préférè rester sur cette version, les nouvelles sont très lentes sous Windows.

En isolant un peux plus les lignes de la partie qui pose problème est dans la ligne :

Code: [Select]
client_MAIL.println(F("QUIT")); // stop la connexion

Et plus exactement la Macro F

si j'écris :

Code: [Select]
client_MAIL.println(("QUIT")); // stop la connexion

Le code compile.

J'ai donc une solution mais pas d'explication  ::)

cbrandt

Tu as beaucoup de chaînes en flash utilisées avec la macro F() ? Genre pile-poil plus de 64 ko ?

cbrandt

#5
Apr 28, 2015, 11:07 am Last Edit: Apr 28, 2015, 11:23 am by cbrandt
oui, quelque chose comme ça dans Print.cpp:

Code: [Select]


#define PRINTBUFFERSIZE 200

#define PSTR_FAR(s) (__extension__({static const char __c[] __attribute__((section(".fini7"))) = (s); pgm_get_far_address(__c);}))

void Print::printf_PF (uint_farptr_t format,...)
{
char buffer[PRINTBUFFERSIZE];
uint8_t format2[PRINTBUFFERSIZE];
va_list args;
uint8_t *ptr;
char c;


ptr = format2;
do
{
c = pgm_read_byte_far(format++);
*ptr++ = c;
}
while (c);

va_start (args, format);
vsnprintf (buffer, PRINTBUFFERSIZE, (char *) format2, args);
va_end (args);

write (buffer);
}


et qui s'utilise comme ça:

Code: [Select]

Serial.printf_PF (PSTR_FAR ("ma chaine\n"));


EDIT:

mon printf_pf n'est pas encore tout à fait au point, il utilise deux buffers de 200 octets dont on devrait pouvoir se passer…  


manuo1

J'ai copié mon code dans un tableau Excel pour extraire les parties avec la macro F().

Je n'ai que 2700 octets pour l'instant qui utilisent la macro F()

J'ai effectivement essayé d'ajouter au maximum mes print dans des fonctions mais pour les print de petites tailles (Style fermeture de balises HTML) je ne voulais pas rajouter des fonctions cela me bouffait plus de RAM encore donc j'utilise quand même la macro F.

Par contre je ne suis pas certain d'avoir saisir l'histoire des 64Ko.

En gros utiliser la macro F force le compilateur à placer les caractère des print en mémoire programme en non en RAM.
Mais si le programme devient gros il risque de placer mes caractères après une zone critique qui serait vers 64 000 octets.
Et hors des 64000 premiers octets la macro F ne peux plus y accéder a cause des valeurs que peut prendre le pointeur qui n'est qu'en 16 bits (soit 64ko)?

Si c'est bien cela, je ne préfère pas trop pour l'instant m'attaquer aux librairie, rien qu'en voyant l'exemple de cbrandt je me dis que j'ai encore du chemin à parcourir pour comprendre les méandres des librairies.

Pour les tailles de mes .print(F(  je ne pense jamais atteindre les 64ko donc comment je peux forcer le compilateur à placer mes caractères en début de programme ?

Simplement en les écrivant en premier dans le programme ?

cbrandt

#7
Apr 28, 2015, 02:36 pm Last Edit: Apr 28, 2015, 03:05 pm by cbrandt
EDIT: ça y est, c'est bon

Je n'ai que 2700 octets pour l'instant qui utilisent la macro F()

Pour les tailles de mes .print(F(  je ne pense jamais atteindre les 64ko donc comment je peux forcer le compilateur à placer mes caractères en début de programme ?

Simplement en les écrivant en premier dans le programme ?
c'est curieux, tu as peut-être beaucoup de variables initialisées genre
Code: [Select]
int x = 5;
 ? car le 5 doit aussi être placé en flash pour pouvoir être affecté à la variable lors du démarrage du programme. Mais ça ferait quand même beaucoup…

Et hors des 64000 premiers octets la macro F ne peux plus y accéder a cause des valeurs que peut prendre le pointeur qui n'est qu'en 16 bits (soit 64ko)?
exactement. (65536 octets pour être précis)
ceci dit, modifier la lib est quand même assez simple:

voici pour la version 1.0.5, dis-moi la version que tu utilises, j'indiquerai les modifications ou posterai directement les fichiers modifiés:

ouvre le fichier /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.cpp et remplace:

Code: [Select]

size_t Print::print(const __FlashStringHelper *ifsh)
{
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}


par:

Code: [Select]

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
size_t Print::print (const __FlashStringHelper *ifsh)
{
   uint_farptr_t p = (uint_farptr_t) ifsh;

  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte_far (p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}
#else
size_t Print::print(const __FlashStringHelper *ifsh)
{
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

#endif


puis ouvre le fichier /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:

insère vers le début du fichier, juste avant la ligne
Code: [Select]
class Print
ce qui suit:
Code: [Select]

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

#undef F
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>((__extension__({static const char __c[] __attribute__((section(".fini7"))) = (string_literal); pgm_get_far_address(__c);}))))

#define pgm_get_far_address(var)                          \
({                                                    \
 uint_farptr_t tmp;                                \
                                                      \
 __asm__ __volatile__(                             \
                                                      \
 "ldi %A0, lo8(%1)"           "\n\t"    \
 "ldi %B0, hi8(%1)"           "\n\t"    \
 "ldi %C0, hh8(%1)"           "\n\t"    \
 "clr %D0"                    "\n\t"    \
 :                                             \
 "=d" (tmp)                                \
 :                                             \
 "p"  (&(var))                             \
 );                                                \
 tmp;                                              \
})
#endif


et donc à l'utilisation, c'est comme avant:
Code: [Select]

Serial.print (F ("ma chaine\n"));


ps: toujours faire une copie des fichiers Print.h et .cpp avant de les modifier
ps2: j'ai pas trouvé ça tout seul, j'avais fais pas mal de recherches avec google quand j'ai été confronté au même problème, puis j'ai adapté à ma sauce, mais pour ma part j'avais énormément de message de debug sur le serial monitor, et j'avais atteint les limites… [/s]

cbrandt

j'ai corrigé mon message au dessus, en principe c'est ok maintenant  :smiley-lol:

manuo1

#9
Apr 28, 2015, 10:44 pm Last Edit: Apr 28, 2015, 11:52 pm by manuo1
c'est curieux, tu as peut-être beaucoup de variables initialisées genre
Je dirais à la louche 100 octets

J'utilise la version 1.5.6-r2 (sur Windows), j'ai regardé mais dans ma version dans les fichiers Print les lignes à remplacer ne sont pas les mêmes.


Non, et en fait ce serait même plutôt l'inverse. Il semblerait que tes chaînes de caractères ont plus de chance de se retrouver au début de la mémoire si elles apparaissent à la fin de ton fichier .ino .

L'analyse du code généré montre que les constantes sont stockées dans l'ordre inverse d'apparition, les constantes locales avant les constantes globales, et celles du programme principal avant celles des bibliothèques supplémentaires. (En tout cas c'est comme cela avec la version 1.6.0 ; je n'ai pas testé avec les versions plus anciennes).
J'ai donc testé en prenant toutes les fonctions qui intègres les macro F() et en les déplaçant en fin de code
=> Même résultat
Pour tester tout mis au début
=> Idem

j'ai repris aussi d'autres tests:
En gardant le code a problème complet mais en le mettant à la fin du programme, le message d'erreur n'est plus le même :

Quote
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o: In function `__vector_default':
(.vectors+0x0): relocation truncated to fit: R_AVR_13_PCREL against symbol `__init' defined in .init0 section in c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o
Si je remplace la fonction par une fonction réduite au lignes qui contiennes F():

Code: [Select]

void je_fais_des_tests(){

   client_MAIL.println(F("EHLO localhost"));
   client_MAIL.println(F("mail from: <xx@sfr.fr>"));
   client_MAIL.println(F("rcpt to: <xx@sfr.fr>"));
   client_MAIL.println(F("DATA"));
   client_MAIL.println(F("To: xx@sfr.fr"));
   client_MAIL.println(F("From: xx@sfr.fr"));
   client_MAIL.println(F("Subject: "));
   client_MAIL.println(F("."));
   client_MAIL.println(F("QUIT"));
 }


le code ne compile plus non plus mais j'ai encore un nouveau message d'erreur :

Quote
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o: In function `__vector_default':
(.vectors+0x58): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_22' defined in .text section in c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o
et dernière chose étonnante avec la fonction ci dessus, si j'ajoute une ligne :
client_MAIL.println(F("aa")); (2 caractères ou plus)

le programme compile  :o



ps2: j'ai pas trouvé ça tout seul, j'avais fais pas mal de recherches avec google quand j'ai été confronté au même problème, puis j'ai adapté à ma sauce, mais pour ma part j'avais énormément de message de debug sur le serial monitor, et j'avais atteint les limites…
J'imagine qu'en bossant beaucoup la question j'arriverai certainement un jour à manipuler les librairies j'ai d'ailleurs déjà modifier la taille des buffers des port série.
Mais quand vous mettez les mains dedans, en plus de comprendre le langage, vous avez une visions globale et une "facilité" à suivre les conséquences sur tout le reste.
Alors à moins que l'on me mâche tout le boulot  :D  je touche le moins possible au librairies "officielles".




manuo1

Le fait de rajouter quelques caractères doit déplacer ces informations au-delà de la limite des 64Ko, et empêcher la détection de l'erreur (données et vecteurs aux mêmes adresses), ou dans le meilleur des cas régler un problème de compilation lié au chevauchement de la limite.
Oui finalement ce n'est pas anormale de compiler en ajoutant ou supprimant certain caractères, je déplace la zone utilisée pour le stockage et si le problème viens de là...
D'ailleur j'espère que le problème est bien dans les F() je testerais bien quand même la solution de cbrandt si elle est adapté à ma version.
Et sinon j'essairai avec une version plus récente de l'IDE





Le contenu du fichier print.cpp de ma version arduino :

Code: [Select]
/*
 Print.cpp - Base class that provides print() and println()
 Copyright (c) 2008 David A. Mellis.  All right reserved.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 Modified 23 November 2006 by David A. Mellis
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Arduino.h"

#include "Print.h"

// Public Methods //////////////////////////////////////////////////////////////

/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    n += write(*buffer++);
  }
  return n;
}

size_t Print::print(const __FlashStringHelper *ifsh)
{
  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

size_t Print::print(const String &s)
{
  return write(s.c_str(), s.length());
}

size_t Print::print(const char str[])
{
  return write(str);
}

size_t Print::print(char c)
{
  return write(c);
}

size_t Print::print(unsigned char b, int base)
{
  return print((unsigned long) b, base);
}

size_t Print::print(int n, int base)
{
  return print((long) n, base);
}

size_t Print::print(unsigned int n, int base)
{
  return print((unsigned long) n, base);
}

size_t Print::print(long n, int base)
{
  if (base == 0) {
    return write(n);
  } else if (base == 10) {
    if (n < 0) {
      int t = print('-');
      n = -n;
      return printNumber(n, 10) + t;
    }
    return printNumber(n, 10);
  } else {
    return printNumber(n, base);
  }
}

size_t Print::print(unsigned long n, int base)
{
  if (base == 0) return write(n);
  else return printNumber(n, base);
}

size_t Print::print(double n, int digits)
{
  return printFloat(n, digits);
}

size_t Print::println(const __FlashStringHelper *ifsh)
{
  size_t n = print(ifsh);
  n += println();
  return n;
}

size_t Print::print(const Printable& x)
{
  return x.printTo(*this);
}

size_t Print::println(void)
{
  size_t n = print('\r');
  n += print('\n');
  return n;
}

size_t Print::println(const String &s)
{
  size_t n = print(s);
  n += println();
  return n;
}

size_t Print::println(const char c[])
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(char c)
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(unsigned char b, int base)
{
  size_t n = print(b, base);
  n += println();
  return n;
}

size_t Print::println(int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(double num, int digits)
{
  size_t n = print(num, digits);
  n += println();
  return n;
}

size_t Print::println(const Printable& x)
{
  size_t n = print(x);
  n += println();
  return n;
}

// Private Methods /////////////////////////////////////////////////////////////

size_t Print::printNumber(unsigned long n, uint8_t base) {
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return write(str);
}

size_t Print::printFloat(double number, uint8_t digits)
{
  size_t n = 0;
  
  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  if (number <-4294967040.0) return print ("ovf");  // constant determined empirically
  
  // Handle negative numbers
  if (number < 0.0)
  {
     n += print('-');
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
  
  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  n += print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0) {
    n += print(".");
  }

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    n += print(toPrint);
    remainder -= toPrint;
  }
  
  return n;
}




manuo1

Et print.h :

Code: [Select]
/*
  Print.h - Base class that provides print() and println()
  Copyright (c) 2008 David A. Mellis.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef Print_h
#define Print_h

#include <inttypes.h>
#include <stdio.h> // for size_t

#include "WString.h"
#include "Printable.h"

#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2

class Print
{
  private:
    int write_error;
    size_t printNumber(unsigned long, uint8_t);
    size_t printFloat(double, uint8_t);
  protected:
    void setWriteError(int err = 1) { write_error = err; }
  public:
    Print() : write_error(0) {}
 
    int getWriteError() { return write_error; }
    void clearWriteError() { setWriteError(0); }
 
    virtual size_t write(uint8_t) = 0;
    size_t write(const char *str) {
      if (str == NULL) return 0;
      return write((const uint8_t *)str, strlen(str));
    }
    virtual size_t write(const uint8_t *buffer, size_t size);
    size_t write(const char *buffer, size_t size) {
      return write((const uint8_t *)buffer, size);
    }
   
    size_t print(const __FlashStringHelper *);
    size_t print(const String &);
    size_t print(const char[]);
    size_t print(char);
    size_t print(unsigned char, int = DEC);
    size_t print(int, int = DEC);
    size_t print(unsigned int, int = DEC);
    size_t print(long, int = DEC);
    size_t print(unsigned long, int = DEC);
    size_t print(double, int = 2);
    size_t print(const Printable&);

    size_t println(const __FlashStringHelper *);
    size_t println(const String &s);
    size_t println(const char[]);
    size_t println(char);
    size_t println(unsigned char, int = DEC);
    size_t println(int, int = DEC);
    size_t println(unsigned int, int = DEC);
    size_t println(long, int = DEC);
    size_t println(unsigned long, int = DEC);
    size_t println(double, int = 2);
    size_t println(const Printable&);
    size_t println(void);
};

#endif

cbrandt

alors, pour la version que tu as:

Print.h:
Code: [Select]



/*
  Print.h - Base class that provides print() and println()
  Copyright (c) 2008 David A. Mellis.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef Print_h
#define Print_h

#include <inttypes.h>
#include <stdio.h> // for size_t

#include "WString.h"
#include "Printable.h"

#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2


#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

#undef F
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>((__extension__({static const char __c[] __attribute__((section(".fini7"))) = (string_literal); pgm_get_far_address(__c);}))))

#define pgm_get_far_address(var)                          \
({                                                    \
 uint_farptr_t tmp;                                \
                                                      \
 __asm__ __volatile__(                             \
                                                      \
 "ldi %A0, lo8(%1)"           "\n\t"    \
 "ldi %B0, hi8(%1)"           "\n\t"    \
 "ldi %C0, hh8(%1)"           "\n\t"    \
 "clr %D0"                    "\n\t"    \
 :                                             \
 "=d" (tmp)                                \
 :                                             \
 "p"  (&(var))                             \
 );                                                \
 tmp;                                              \
})
#endif

class Print
{
  private:
    int write_error;
    size_t printNumber(unsigned long, uint8_t);
    size_t printFloat(double, uint8_t);
  protected:
    void setWriteError(int err = 1) { write_error = err; }
  public:
    Print() : write_error(0) {}
 
    int getWriteError() { return write_error; }
    void clearWriteError() { setWriteError(0); }
 
    virtual size_t write(uint8_t) = 0;
    size_t write(const char *str) {
      if (str == NULL) return 0;
      return write((const uint8_t *)str, strlen(str));
    }
    virtual size_t write(const uint8_t *buffer, size_t size);
    size_t write(const char *buffer, size_t size) {
      return write((const uint8_t *)buffer, size);
    }
   
    size_t print(const __FlashStringHelper *);
    size_t print(const String &);
    size_t print(const char[]);
    size_t print(char);
    size_t print(unsigned char, int = DEC);
    size_t print(int, int = DEC);
    size_t print(unsigned int, int = DEC);
    size_t print(long, int = DEC);
    size_t print(unsigned long, int = DEC);
    size_t print(double, int = 2);
    size_t print(const Printable&);

    size_t println(const __FlashStringHelper *);
    size_t println(const String &s);
    size_t println(const char[]);
    size_t println(char);
    size_t println(unsigned char, int = DEC);
    size_t println(int, int = DEC);
    size_t println(unsigned int, int = DEC);
    size_t println(long, int = DEC);
    size_t println(unsigned long, int = DEC);
    size_t println(double, int = 2);
    size_t println(const Printable&);
    size_t println(void);
};

#endif

cbrandt


et Print.cpp:

Code: [Select]

/*
 Print.cpp - Base class that provides print() and println()
 Copyright (c) 2008 David A. Mellis.  All right reserved.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 Modified 23 November 2006 by David A. Mellis
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Arduino.h"

#include "Print.h"

// Public Methods //////////////////////////////////////////////////////////////

/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    n += write(*buffer++);
  }
  return n;
}


#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

size_t Print::print (const __FlashStringHelper *ifsh)
{
   uint_farptr_t p = (uint_farptr_t) ifsh;

  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte_far (p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

#else

size_t Print::print(const __FlashStringHelper *ifsh)
{
  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

#endif

size_t Print::print(const String &s)
{
  return write(s.c_str(), s.length());
}

size_t Print::print(const char str[])
{
  return write(str);
}

size_t Print::print(char c)
{
  return write(c);
}

size_t Print::print(unsigned char b, int base)
{
  return print((unsigned long) b, base);
}

size_t Print::print(int n, int base)
{
  return print((long) n, base);
}

size_t Print::print(unsigned int n, int base)
{
  return print((unsigned long) n, base);
}

size_t Print::print(long n, int base)
{
  if (base == 0) {
    return write(n);
  } else if (base == 10) {
    if (n < 0) {
      int t = print('-');
      n = -n;
      return printNumber(n, 10) + t;
    }
    return printNumber(n, 10);
  } else {
    return printNumber(n, base);
  }
}

size_t Print::print(unsigned long n, int base)
{
  if (base == 0) return write(n);
  else return printNumber(n, base);
}

size_t Print::print(double n, int digits)
{
  return printFloat(n, digits);
}

size_t Print::println(const __FlashStringHelper *ifsh)
{
  size_t n = print(ifsh);
  n += println();
  return n;
}

size_t Print::print(const Printable& x)
{
  return x.printTo(*this);
}

size_t Print::println(void)
{
  size_t n = print('\r');
  n += print('\n');
  return n;
}

size_t Print::println(const String &s)
{
  size_t n = print(s);
  n += println();
  return n;
}

size_t Print::println(const char c[])
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(char c)
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(unsigned char b, int base)
{
  size_t n = print(b, base);
  n += println();
  return n;
}

size_t Print::println(int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(double num, int digits)
{
  size_t n = print(num, digits);
  n += println();
  return n;
}

size_t Print::println(const Printable& x)
{
  size_t n = print(x);
  n += println();
  return n;
}

// Private Methods /////////////////////////////////////////////////////////////

size_t Print::printNumber(unsigned long n, uint8_t base) {
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return write(str);
}

size_t Print::printFloat(double number, uint8_t digits)
{
  size_t n = 0;
  
  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  if (number <-4294967040.0) return print ("ovf");  // constant determined empirically
  
  // Handle negative numbers
  if (number < 0.0)
  {
     n += print('-');
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
  
  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  n += print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0) {
    n += print(".");
  }

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    n += print(toPrint);
    remainder -= toPrint;
  }
  
  return n;
}

manuo1

Merci cbrandt, du tout mâché tout prêt a utilisé  :smiley-grin:

Si je ne me trompe pas il s'agit des fichiers complet je remplace tout le contenu original de print.cpp et print.h par tes lignes ?

Donc j'ai fait la modif, le code compile bien dans les situations évoquées précédemment, par contre le résultat sur le projet donne des affichages html conceptuellement intéressante mais apparemment pas compris par les navigateurs  :smiley-wink:

HTTP/1.1 200 OK   dans la ligne client.println(F("HTTP/1.1 200 OK"));

est affiché dans Mozilla comme ça :

Quote
OÈiêuà"Ý"Œèà¸"Œ È""•Ž^OÈaåsà"Ý"Žëà¸"Œ È""•áè.ñ,ìýÇnärà"Ý"Ž ]OÈ`àrà"Ý"Ǹ"º
J'ai rien contre les langues étrangère mais ma page web à une tête Bizarre  :smiley-lol:

Go Up