ATmega2561 Problem mit WinAVR

#1113597
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
Moderator Persönliche Seite #1114566
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.
Gast #1129721
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.
Moderator Persönliche Seite #1129732
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.
(Firma: egnite GmbH) Persönliche Seite #1129762
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?
Moderator Persönliche Seite #1130835
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.
#1487214
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren