Forum: Compiler & IDEs ATmega2561 Problem mit WinAVR


von Maik S. (maikscholz)


Lesenswert?

Hallo,
ich möchte ethernut auf einen ATmega2561 laufen lassen.
Wenn ich ca. 100kByte code übersetzte und linke ist alles
ok.
Wenn ich aber den Code vergrößere (~200kB), dann bekomme
ich sehr viele Linker Warnungen wie:
  C:/subver/homenet/sw/ethernut/nut/crt/vfprintf.c:65: warning: internal
    error: out of range error
  C:/subver/homenet/sw/ethernut/nut/crt/vfprintf.c:65: warning: internal
    error: out of range error

Was kann ich dagegen unternehmen?

Der Linkeraufruf:
avr-gcc -x assembler-with-cpp -c -mmcu=atmega2561 
-Wa,-amhls=strstr_P.lst -DETHERNUT1 -DARTHERNET1 -D__HARVARD_ARCH__ 
-DARTHERCPLDSPI=0x1200 -DARTHERCPLDSTART=0x1100 -Os -gdwarf-2 strstr_P.S 
-o strstr_P.o
avr-gcc main.o http/httpserv.o can/canserv.o can/can.o can/mcp2515.o 
adc/adc.o pwr/powersupply.o db/sqlite3.o strstr_P.o  -mmcu=atmega2561 
-Wl,--defsym=main=0,-Map=homeserver.map,--cref 
-Lc:\subver/homenet/sw/app/station/nutbld 
-Wl,--section-start=.bootldrinfo=0x3eff8 -Wl,--start-group 
c:\subver/homenet/sw/app/station/nutbld/nutinit.o -lnutpro -lnutos 
-lnutarch -lnutdev -lnutarch -lnutnet -lnutfs -lnutcrt -lm 
-Wl,--end-group -o homeserver.elf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Maik Scholz wrote:

>   C:/subver/homenet/sw/ethernut/nut/crt/vfprintf.c:65: warning: internal
>     error: out of range error
>   C:/subver/homenet/sw/ethernut/nut/crt/vfprintf.c:65: warning: internal
>     error: out of range error
>
> Was kann ich dagegen unternehmen?

Vielleicht als allererstes mal gucken, was da auf Zeile 65 steht?

Ich fürchte, Ethernut macht hier irgendwas, was man eher nicht tun
sollte.

von Harald K. (Firma: egnite GmbH) (haraldkipp) Benutzerseite


Lesenswert?

Möglicherweise liegt es an der Übergabe eines Function pointers als 
Parameter. Dann hilft es evtl., wenn man im Makefile die LIBS Einträge 
anders anordnet.

von Gunter Weisbrod (Gast)


Lesenswert?

"Möglicherweise liegt es an der Übergabe eines Function pointers als
Parameter."

Jau!
Tatsächlich scheint der gcc-Compiler / Assembler ein Problem mit der 
Unterscheidung von pointern auf Funktionen (word) und flash-Daten 
(bytes) zu haben. Den 'internal error: out of range error' gibt es daher 
auch, wenn man eine ungerade(!) Anzahl Datenbytes im .text-Segment.
Abhilfe: Daten im .progmem -Segment plazieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gunter Weisbrod wrote:

> Den 'internal error: out of range error' gibt es daher
> auch, wenn man eine ungerade(!) Anzahl Datenbytes im .text-Segment.
> Abhilfe: Daten im .progmem -Segment plazieren.

Ja klar.  Eine ungerade Anzahl von Datenbytes in .text ist schlicht
nicht zulässig.  Warum kommt man auch auf so'ne Idee?  Der Compiler
selbst macht das ja nicht...  Genau dafür ist ja progmem da, dort
kümmert sich der Linkerscript nötigenfalls um das Padding.  Der
zweite Vorteil ist, dass progmem immer vor dem eigentlichen text
platziert wird, damit es (nach Möglichkeit) unterhalb der 64-KiB-
Grenze landet, innerhalb derer man mit den diversen _P-Funktionen
auf die Flash-Daten zugreifen kann.  Oberhalb 64 KiB muss man dann
umständlich manuell mit den pgm_..._far()-Funktionen arbeiten.

von Harald K. (Firma: egnite GmbH) (haraldkipp) Benutzerseite


Lesenswert?

Wenn der Compiler das nicht macht, wäre die Frage: Wie bekommt man das 
dann hin?

Wie viele Bytes im Text Segment sind, ist aber doch eigentlich 
belanglos. Wichtig ist lediglich, dass alle Elemente auf Wortgrenzen 
beginnen, oder?

Noch als Info: Nut/OS verwendet, wenn es für AVR gebaut wird, die Linker 
Skripts von avrlibc. Explizite .text Segmente werden nur für den 
ImageCraft Compiler definiert, beim avr-gcc beschränken wir uns auf 
pgmspace.h. Also kein Voodoo oder andere Tricks, bis auf die für's 
Multithreading nötigen Stack-Manipulationen. Die o.g. Routine ist 
übrigens klein:

 int vfprintf(FILE * stream, CONST char *fmt, va_list ap)
 {
   return _putf(_write, stream->iob_fd, fmt, ap);
 }

Als Problem vermutete ich, dass der erste Parameter, ein 
Funktionspointer auf die _write() Routine (ganz normale stdio _write 
Funktion, aber nicht aus avrlibc) das Problem verursacht.

Die Geschichte mit ungeraden Bytes im .text Segment hat mich jetzt 
irgendwie verunsichert. @Gunter: Woraus schließt Du das? Map File? Wenn 
ja, wleches Modul?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Harald Kipp wrote:

> Wenn der Compiler das nicht macht, wäre die Frage: Wie bekommt man das
> dann hin?

Der Compiler packt normalerweise nach .text nur generierten Code,
keine Konstanten.  Da beim AVR alle Befehle Vielfache von 16 Bits
lang sind, kann dabei immer nur eine gerade Zahl von Bytes
entstehen.

Wo ggf. die ungerade Zahl herkommt, musst du dir schon selbst
ansehen.  Die Vermutung liegt nahe, dass es irgendwie mit NutOS
zu tun haben könnte, denn ich habe ansonsten noch nie eine
derartige Fehlermeldung berichtet gehört.

> Die o.g. Routine ist
> übrigens klein:
>
>  int vfprintf(FILE * stream, CONST char *fmt, va_list ap)
>  {
>    return _putf(_write, stream->iob_fd, fmt, ap);
>  }

Das kann gut und gern schief gehen.  NutOS hat formal kein Recht,
Teile der normalen C-Bibliothek (mit den dort standardisierten
Namen) neu zu implementieren.  Der C-Standard verbietet dies
ausdrücklich und gibt gleichzeitig dem Compiler damit die Möglich-
keit, sein internes Wissen darüber, was die Funktionen der
Standardbibliothek machen, für Optimierungen zu nutzen.

von Jens B. (kaeptnahab)


Lesenswert?

Hallo Zusammen,

auch ich habe Probleme von ATmega128 auf 2561 zu gehen.
Mit Optimierungen (-Os/-O2) ist alles ok.

mit Optimierung (-O1) nicht mehr Warnings, aaaber Funktionspointereien 
scheinen schief zu gehen,

ohne Optimierung (-O0) plötzlich knapp 400 Warnings, z.B.:

(.text+0x4): warning: internal error: out of range error
c:/user/tools/winavr20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/li 
b/avr6\libc.a(sprintf.o):  In function `sprintf':

oder

menucfg.o:(.progmem.data+0x3d48): warning: internal error: out of range 
error

Eigentlich hatte ich ja gehofft, mit dem CPU-Wechsel mehr als 128k 
nutzen zu können, aber so einfach scheints ja nicht zu gehen.
Was gibts denn da als Lösung oder workaround?

CU
KäptnAhab

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.