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
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.
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.
"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.
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.
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.