Hallo
Ich benutze eclipse mit Winavr. Mittlerer Weile ist mein Programm so
groß geworden das ich die Warnung "warning: internal error: out of range
error" vom Linker bekomme. Im einzelnen handelt es sich um folgende
Meldungen:
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/avr6\libgcc.a(_addsub_sf.o)
: In function `_fpadd_parts':
(.text+0x6): warning: internal error: out of range error
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/avr6\libgcc.a(_addsub_sf.o)
: In function `__subsf3':
(.text+0x29c): warning: internal error: out of range error
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/avr6\libgcc.a(_addsub_sf.o)
: In function `__subsf3':
(.text+0x29e): warning: internal error: out of range error
Finished building: TRENDvent_Bedien.lss
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/avr6\libgcc.a(_addsub_sf.o)
: In function `__addsf3':
(.text+0x2fe): warning: internal error: out of range error
und noch einige mehr.
Als letzes habe ich weitere FLASH-Konstanten zum Code hinzugefügt, sodas
jetzt gut 32k mit Flashkonstanten (Bilder, Texte, Configurationen, ect.)
voll sind. Alle wurden mit dem PROGMEM-Atrribut angelegt und landetetn
in der .text-Section.
Der eigentliche Programmcode beginnt bei 0000815a <vBoot>: (aus
.lss-File)
Ich habe schon im Forum gesucht, aber noch nichts zu spezillen Problem
gefunden, da die Fehler ja beim vom Compiler generiertem Code entstehen.
Was kann ich machen um das Problem zu lösen?
Gruß Steffen
Steffen Graap schrieb:
> Hab das -lm dem Linker hinnzugefügt, hat aber leider nichts genutzt.
Was soll das heißen? Dass der Output immer noch genau so aussieht?
Wie sieht der Linker-Aufruf denn konkret aus?
Der Output sieht zwar nicht genau so aus, aber die warnings sind immer
noch da. Da die Ausgaben hier den Rahmen sprengen würden habe, ich sie
als Anhang beigefügt. Jeweils einemal mit, und ein mal ohne den
Linkerzusatz -lm.
Auch ist dort jeweils der Linkeraufruf enthalten. Das Linkerscript
"TRENDvent.x" ist das Standartscript für den Mega2560 (avr6.x) erweitert
um die Zusätze für die .xram-Section. Auch das habe ich im Anhang
beigefügt.
Gruß Steffen
Oh, Danke das wusste ich bis eben nicht, man lernt ständig dazu. Da ich
über eclipse arbeite, habe ich einfach den Zusatz mit ins Argumentenfeld
eingetragen, um die ganzen Objektdateien kümmert sich eclipse selbst.
Nun hab ichs einfach als zu benutzende bibliothek übergeben.
Das Resultat siehst du unten. Die Warnings sind schon weniger geworden,
aber immer noch vorhanden.
Gruß Steffen
Invoking: AVR C Linker
avr-gcc -Wl,-Map,TRENDvent_Bedien.map -T
c:/programme/winavr/avr/lib/ldscripts/TRENDvent.x -mmcu=atmega2560
-o"TRENDvent_Bedien.elf" ./Code/boot.o ./Code/dateisystem.o
./Code/doxygen.o ./Code/key.o ./Code/lcd_graph.o ./Code/lcd_text.o
./Code/main.o ./Code/memory.o ./Code/menue.o ./Code/spi.o
./Code/sprache.o ./Code/steuerung.o ./Code/task.o ./Code/tim.o
./Code/usart.o ./Code/usart_1.o ./Code/usart_2.o ./Code/usart_3.o -lm
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(dtoa_prf.o): In function `dtoa_prf':
(.text+0x4): warning: internal error: out of range error
Finished building target: TRENDvent_Bedien.elf
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(dtoa_prf.o): In function `dtoa_prf':
(.text+0x6): warning: internal error: out of range error
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(strtod.o): In function `strtod':
(.text+0x4): warning: internal error: out of range error
Invoking: AVR Create Extended Listing
avr-objdump -h -S TRENDvent_Bedien.elf >"TRENDvent_Bedien.lss"
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(strtod.o): In function `strtod':
(.text+0x6): warning: internal error: out of range error
Finished building: TRENDvent_Bedien.lss
Create Flash image (ihex format)
avr-objcopy -R .eeprom -O ihex TRENDvent_Bedien.elf
"TRENDvent_Bedien.hex"
Finished building: TRENDvent_Bedien.hex
Invoking: Print Size
avr-size --format=avr --mcu=atmega2560 TRENDvent_Bedien.elf
AVR Memory Usage
----------------
Device: atmega2560
Program: 137006 bytes (52.3% Full)
(.text + .data + .bootloader)
Data: 3634 bytes (44.4% Full)
(.data + .bss + .noinit)
Finished building: sizedummy
Wenn du mal -g einschaltest (Debug-Information), dann kann der
Linker dir statt nur einer Adresse die Quellcodezeile mit sagen,
auf die sich das bezieht. Vielleicht hast du ja dann eher eine
Idee, was die Ursache sein könnte.
Leider hat das hinzufügen von -g zum Linkeraufruf nicht mehr
Informationen gebracht. sieh unten
Was sind trampolines ? Im Listfile gibt es zwei Sprünge in diesem Teil.
Die beiden Sprünge sind genau die beiden Dateien, die der Linker
bemängelt
000080e8 <__trampolines_start>:
80e8: 0d 94 2b 06 jmp 0x20c56 ; 0x20c56 <strtod+0x250>
80ec: 0d 94 c9 04 jmp 0x20992 ; 0x20992 <dtoa_prf+0x250>
Gruß Steffen
make all
Building target: TRENDvent_Bedien.elf
Invoking: AVR C Linker
avr-gcc -Wl,-Map,TRENDvent_Bedien.map -g -T
c:/programme/winavr/avr/lib/ldscripts/TRENDvent.x -mmcu=atmega2560
-o"TRENDvent_Bedien.elf" ./Code/boot.o ./Code/dateisystem.o
./Code/doxygen.o ./Code/key.o ./Code/lcd_graph.o ./Code/lcd_text.o
./Code/main.o ./Code/memory.o ./Code/menue.o ./Code/spi.o
./Code/sprache.o ./Code/steuerung.o ./Code/task.o ./Code/tim.o
./Code/usart.o ./Code/usart_1.o ./Code/usart_2.o ./Code/usart_3.o -lm
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(dtoa_prf.o): In function `dtoa_prf':
(.text+0x4): warning: internal error: out of range error
Finished building target: TRENDvent_Bedien.elf
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(dtoa_prf.o): In function `dtoa_prf':
(.text+0x6): warning: internal error: out of range error
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(strtod.o): In function `strtod':
(.text+0x4): warning: internal error: out of range error
Invoking: AVR Create Extended Listing
avr-objdump -h -S TRENDvent_Bedien.elf >"TRENDvent_Bedien.lss"
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(strtod.o): In function `strtod':
(.text+0x6): warning: internal error: out of range error
Finished building: TRENDvent_Bedien.lss
Steffen Graap schrieb:
> Was sind trampolines ? Im Listfile gibt es zwei Sprünge in diesem Teil.> Die beiden Sprünge sind genau die beiden Dateien, die der Linker> bemängelt
Pointer sind beim GCC für AVR nur 16 Bits breit, auch wenn sie auf
Funktionen zeigen und der AVR mehr als 64KW/128KB Flash hat. Folglich
müssen alle Funktionen, oder mindestens alle die irgendwo indirekt
genutzt werden, eine Adresse innerhalb des davon adressierbaren Bereichs
haben.
Diese beiden Funktionen liegen ausserhalb und daher gibt es
Hilfsadressen innerhalb. Weshalb der Linker damit ein Problem hat ist
aber für mich unklar. Es fällt zwar auf, dass die Tramplines knapp
jenseits von 32KB liegen, ich kann aber nicht erkennen weshalb das ein
Problem sein sollte.
Versuch mal, die ROM-Daten soweit zu reduzieren, dass die Trampolines
unter 0x8000 rutschen. Nur testhalber, ob da ein Zusammenhang besteht.
A. K. schrieb:
> Versuch mal, die ROM-Daten soweit zu reduzieren, dass die Trampolines> unter 0x8000 rutschen. Nur testhalber, ob da ein Zusammenhang besteht.
das hab ich mal gemacht, die Trampolines rutschen jetzt unter 0x8000
00007988 <__trampolines_start>:
7988: 0d 94 70 02 jmp 0x204e0 ; 0x204e0 <strtod+0x250>
798c: 0d 94 0e 01 jmp 0x2021c ; 0x2021c <dtoa_prf+0x250>
Ein Fehler ist dadurch beseitigt worden, der andere bleibt aber.
Steffen
make all
Building file: ../Code/lcd_graph.c
Invoking: AVR Compiler
avr-gcc -Wall -g3 -gstabs -Os -fpack-struct -fshort-enums
-fno-strict-aliasing -funsigned-char -funsigned-bitfields -c -save-temps
-mmcu=atmega2560 -DF_CPU=14745600UL -MMD -MP -MF"Code/lcd_graph.d"
-MT"Code/lcd_graph.d" -c -o"Code/lcd_graph.o" "../Code/lcd_graph.c"
Finished building: ../Code/lcd_graph.c
Building target: TRENDvent_Bedien.elf
Invoking: AVR C Linker
avr-gcc -Wl,-Map,TRENDvent_Bedien.map -g -T
c:/programme/winavr/avr/lib/ldscripts/TRENDvent.x -mmcu=atmega2560
-o"TRENDvent_Bedien.elf" ./Code/boot.o ./Code/dateisystem.o
./Code/doxygen.o ./Code/key.o ./Code/lcd_graph.o ./Code/lcd_text.o
./Code/main.o ./Code/memory.o ./Code/menue.o ./Code/spi.o
./Code/sprache.o ./Code/steuerung.o ./Code/task.o ./Code/tim.o
./Code/usart.o ./Code/usart_1.o ./Code/usart_2.o ./Code/usart_3.o -lm
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(strtod.o): In function `strtod':
(.text+0x4): warning: internal error: out of range error
Finished building target: TRENDvent_Bedien.elf
c:/programme/winavr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6\li
bc.a(strtod.o): In function `strtod':
(.text+0x6): warning: internal error: out of range error
Invoking: AVR Create Extended Listing
avr-objdump -h -S TRENDvent_Bedien.elf >"TRENDvent_Bedien.lss"
Finished building: TRENDvent_Bedien.lss
Es ist noch nicht die aktuelle Version, sonder 20090313. Da werd ich
wohl erst mal die aktuelle Version installieren.
Was mir noch eingfallen ist, ich benutze Funktionspointer
wie z.B. in dieser Funktion
Eher nicht, denn dass du strtod indirekt nutzt scheint unwahrscheinlich.
Aber warte mal bis Jörg Wunsch aufgewacht ist, er scheint auch schon
über sowas gestoplert zu sein.
Für mich hat sich das erst mal erledigt. Nach der Installation des
neusten WinAVR sind die Fehler erst mal weg. Ob alles läuft kann ich
erst am Montag auf Arbeit testen, da ich hier keine Testhardware habe.
Für mich als Erkenntnis nehme ich erst mal mit, das wenn unerklärliche
Probleme auftauchen, ich erst mal nach der neusten Version schaue.
Nochmals Danke euch allen für die Hilfe.
Gruß Steffen
PS: nach entfernen des Linkerzusatzes -lm traten die Fehler wieder auf.
Steffen Graap schrieb:
> Für mich hat sich das erst mal erledigt. Nach der Installation des> neusten WinAVR sind die Fehler erst mal weg.
Weil das Problem weg ist oder weil nun alles unter 128KB liegt?
@ A. K.
Du hattest recht. Ich hatte etwas voreilig gehandelt. Das Problem war
erst mal so wie oben beschrieben nicht mehr vorhande. Da du aber die
Frage nach den 128kb gestellt hast, hab ich einen Versuche gemacht, und
alle Debugausgaben (Stringausgaben für erfolgreiche Programmabschnitte
über eine COM) eingeschaltet. Dabei trat dann der Out off Range error
wieder auf. Diesmal aber nicht in ein vom Compiler erstellten/benutzten
Funktion, sondern in der schon weiter oben erwähnten Funktion mit
Funktionspointerübergabe.
Invoking: AVR C Linker
avr-gcc -Wl,-Map,TRENDvent_Bedien.map -g -T
c:/programme/winavr/avr/lib/ldscripts/TRENDvent.x -mmcu=atmega2560
-o"TRENDvent_Bedien.elf" ./Code/boot.o ./Code/dateisystem.o
./Code/doxygen.o ./Code/key.o ./Code/lcd_graph.o ./Code/lcd_text.o
./Code/main.o ./Code/memory.o ./Code/menue.o ./Code/spi.o
./Code/sprache.o ./Code/steuerung.o ./Code/task.o ./Code/tim.o
./Code/usart.o ./Code/usart_1.o ./Code/usart_2.o ./Code/usart_3.o -lm
./Code/usart_2.o: In function `vSend_Debug_Data':
../Code/usart_2.c:684: warning: internal error: out of range error
../Code/usart_2.c:684: warning: internal error: out of range error
Finished building target: TRENDvent_Bedien.elf
hier die entsprechende Zeile
Steffen Graap schrieb:
> das Listfile zeigt auch den Grund für den out of range error
Welchen Grund siehst du denn da?
Die beiden "call" sind es jedenfalls nicht, falls du die meintest.
Hast du es schon mit "-Wl,--relax" für den Linker versucht?
Steffen Graap schrieb:
> Die Funktion vSend_Debug_Data liegt im Speicher auf Adresse 0x20440 => 132160. Das ist oberhalb der 16bit-Adressierung. Der Funktionspointer> aus
> kann aber nur 16bit.
Deshalb sollte es für die Funktion ein Trampoline geben, und dessen
Adresse an die Funktion übergeben werden. Ich habe ein solches Szenario
(und ein paar Variationen) nachgestellt, und hatte keinerlei Probleme
damit (mit WinAVR-20090313).
Stefan Ernst schrieb:
> Deshalb sollte es für die Funktion ein Trampoline geben, und dessen> Adresse an die Funktion übergeben werden. Ich habe ein solches Szenario> (und ein paar Variationen) nachgestellt, und hatte keinerlei Probleme> damit (mit WinAVR-20090313).
die gibt es aber nicht, sondern nur eine für die vCheckCom_2
Ich kenne derzeit leider keine einfache Methode, Funktionszeiger für
Code > 128 KiB zu benutzen. Man müsste die Dinger intern als uint32_t
führen, aber wie dereferenziert man sie dann?
Die Linkerzusätze bringen leider nichts.
Ich hab mir mal die Funktion, in der der Fehler auftritt, mal näher
angeschaut. Zu erst der C-Code, auf das wesentliche reduziert (der Rest
sind nur COM-Ausgaben)
204c8: 0e 94 6e ec call 0x1d8dc ; 0x1d8dc <u8Add_Time_Task>
15
}
die Konstante TIME_DEBUG_DATA ist mit 250 angegeben.
Wie man schön sehen kann wird hier nicht die Adresse von
vSend_Debug_Data (20440) übergeben und auch keine trampoline-Adresse,
sondern 0,
Die Frage bleibt weiter im Raum stehen wie kann ich den Linker überreden
hier ein trampoline zu benutzen?
Steffen
Ich weiß, das heut Sonntag ist, aber hat niemand eine Idee, warum der
Linker keine Trampolines benutzt, und wie man ihn dazu überreden kann?
Als Plan B könnte ich die ganzen FLASH-Konstanten (~30kb) ja in den
hinteren Teil des FLASH legen, dann hätte ich erst mal Ruhe bis der Code
entsprechend groß ist.
Gibt es dafür ne Standartlösung?
Ansonsten würde ich eine neue Section anlegen, diese in den hinteren
Berecih des Flash ansiedeln und die Daten mit prm_read_byte_far
inclusive dem far()-konvertierungsmacro laden.
Gruß Steffen
Steffen Graap schrieb:
> Gibt es dafür ne Standartlösung?
Sowas ist ein bischen jenseits dessen, was ich einem AVR zumuten würde.
Oder jedenfalls dem avr-gcc, vielleicht tun sich kommerzielle Compiler
damit leicher.
Steffen Graap schrieb:
> Ich weiß, das heut Sonntag ist, aber hat niemand eine Idee, warum der> Linker keine Trampolines benutzt, und wie man ihn dazu überreden kann?
Die AVR-GCC-Hacker findest du immer noch am ehesten auf der
avr-gcc-list (at nongnu.org), nicht hier im Forum. Allerdings
habe ich von Björn Haase lange nichts mehr gelesen. Er hat
seinerzeit die Trampoline für den AVR-Port implementiert.
Ich habe mir die Problematik nochmals genauer angeschaut. Der Fehler
tritt nur dann auf, wenn ich Funktionen über einen Pointer aufrufe. Bei
allen anderen Aufrufen funktioniert es mit den Trampolines oder mit
direkten CALL-Aufrufen. Dabei ist mir eine Idee aufgeblitzt.
Den Aufruf einer Funktion über einen Pointer mache ich nur in einer
Funktion, die den Pointer aus einer Liste übernimmt. Wenn ich jetzt
anstelle eines Pointers ein UINT32 ablege, und diesen dann per Assembler
CALL aufrufe sollte das ganze doch funktionieren? Was meint ihr dazu?
Gruß Steffen
Steffen Graap schrieb:
> Wenn ich jetzt> anstelle eines Pointers ein UINT32 ablege, und diesen dann per Assembler> CALL aufrufe sollte das ganze doch funktionieren?
Ja, das meinte ich weiter oben schon. Es ist übrigens ein EICALL,
und du musst dich ggf. noch drum kümmern, dass RAMPZ danach wieder
zurück gedreht wird (bin ich mir gerade nicht im Klaren).
Die Frage ist allerdings dennoch, warum die Trampoline hier nicht
greifen.
@ Jörg
Ja klar, ein EICALL ist der richtige Befehl. Ich werde das mal
ausprobieren. Ich werde allerdings erst zum Ende der Woche dazu kommen,
da vorher noch was anderes erledigt werden muss, und mit reduzierten
Dabugausgaben läuftdas ganze noch.
Ich melde mich dann wieder wenn ich so weit bin um euch auf dem
Laufenden zu halten.
Muss ich den Bug noch melden oder hat das schon jemand erledigt?
Gruß Steffen
Steffen Graap schrieb:
> Muss ich den Bug noch melden oder hat das schon jemand erledigt?
Bin ich mir gerade nicht sicher... Hier:
http://www.nongnu.org/avr-libc/bugs.html
sammelt Eric Weddington alle bekannten Toolchain-Bugs. Ich finde
auf Anhieb nichts dergleichen, kannst ja auch nochmal drüber schauen
und ggf. einen Bug bei GCC einkippen.
Ich bin mir auch nicht ganz sicher. Es gibt einen Bug-Report, der sich
aber mit dem EICALL-Befehl befasst.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38549
Ich denke ich werd da mal einen Bug einfügen.
Gruß Steffen
Bei diesem Bug bin ich mir nicht sicher, da auch der WinAVR-Bug, auf
den er sich bezieht, nicht mehr zugänglich ist.
Du kannst ja einen Verweis darauf anbringen. Da die Erwartungshaltung
aber ist, dass das Problem eigentlich durch die Trampoline gelöst
werden sollte, muss man den Bugreport wohl nicht bei GCC, sondern bei
den binutils einkippen. Bitte setz Eric.Weddington (at atmel.com)
mit auf Cc.
Hab's schon gesehen. Naja, nicht ganz die richtige Stelle, die
avr-libc kann da nicht viel dafür tun. Ich werde aber mal sehen,
ob ich damit dort erst einmal eine Diskussion lostreten kann, ob
das nun ein Bug in den linker trampolines ist oder nicht (also
ob die trampolines das eigentlich abfangen sollten oder ob das
gar nicht gehen kann).
Ja, sorry. Ich hab mich schon schwer getan den Bug in englisch da
reinzuhacken. Die ganze Compiler/Linker ect. Geschichte sind für mich
böhmische Wälder. Da ich ein Quereinsteiger in die C-Programmierung bin,
beschäftige ich mich mit den entsprechenden Thematiken erst wenn ich ein
Problem habe, so wie jetzt.
Der Compiler ist für mich ein Werkzeug, solange er funktioniert, ist es
mir egal wie er das macht. Erst wenn er seinen Dinst verweigert, muss
ich in die Innerein. Leider fehlt mir die Zeit, mich damit umfassender
zu befassen.
Ich denk mal der richtigere Weg wären nicht die Trampolines, sondern
Funktionspointer entsprechend des benutzten Device 16 oder 22(24)bit
breit zu machen, analog dem verwendeten Programmcounter.
Welche Variante nun weniger Arbeit bedeutet kann ich nicht sagen.
Betreffs des Workaround mit dem EICALL, werd ich mich wohl ab morgen
beschäftigen, da mein Programm jetzt nur noch läuft wenn ich alle
Debugausgaben abschalte. (Codegröße >140k)
Gruß Steffen
Jörg Wunsch schrieb:
> Ich werde aber mal sehen,> ob ich damit dort erst einmal eine Diskussion lostreten kann, ob> das nun ein Bug in den linker trampolines ist oder nicht (also> ob die trampolines das eigentlich abfangen sollten oder ob das> gar nicht gehen kann).
Wie ich schon schrieb, ich hatte versucht das nachzustellen(*), und
hatte keinerlei Probleme mit Funktionszeigern auf Funktionen jenseits
von 128k. Es wurde brav ein Trampoline angelegt, und der Zeiger verwies
dann auf dieses. "oder ob das gar nicht gehen kann" fällt also schon mal
raus. ;-)
(*): Ich habe alles ausprobiert, was mir an Kombinationen einfiel (z.B.
auch die Zuweisung des Funktionspointer jenseits von 128k gelegt),
keinerlei Fehler. Ohne kompletten compilierbaren Beispiel-Code wird aus
dem Bug-Report wohl nichts werden.
Moin
Den kompletten Code kann ich leider nicht zur Verfügung stellen
(Firmengeheimnis). Ich kann aber ein Versuchsprojekt anlegen, welches
ich Online stellen kann. Das dauert aber noch.
Vorab erst mal das Modul des Taskmanagers in der die Funktionspointer
erstellt und benutzt werden.
Gruß Steffen
So, ich habe das Testprojekt feritg, ging schneller als ich gedacht
habe. Ich habe mal das ganze eclips-Projektverzeichnis gezipt. Dazu noch
die Compiler/linkerausgabe als Bild.
Gruß Steffen
Du hast hier einfach per PROGMEM so viele Daten in das Flash gepumpt,
dass der Trampoline selber auch jenseits der 128k liegt. Das ist ein
anderes Szenario, als das im ursprünglichen Code, wo die Trampolines
deutlich unterhalb liegen:
Beitrag "Re: warning: internal error: out of range error"
Stefan Ernst schrieb:
> Du hast hier einfach per PROGMEM so viele Daten in das Flash gepumpt,> dass der Trampoline selber auch jenseits der 128k liegt.
Jup, das hab ich nicht beachtet, ich werd das morgen mal nachbessern.
Kleiner Tipp: um viel Code zu erzeugen, nimmst du dir am besten
eine als "volatile" deklarierte (oder zwei :) Variablen eines
32-Bit-Datentyps, und die summierst du dann (mittels automatisch
generiertem C-Code) kräftig auf.
Ich hab das Versuchsprojekt mal angepasst, und siehe da, alles läuft
ohne Probleme wie bei Stefan.
In meinem richtigen Projekt hab ich mal 32k FLASH-Müll eingefügt, und
nun hab ich 49 out of range error. Warum es im Testprojekt funktioniert,
und im richtigen Projekt nicht, ist mir ein Rätsel.
Was mir aufgefallen ist, es werden zwar Trampolines für eine Funktion
angelegt (warscheinlich für einen Aufruf ohne Pointer)
hierbei wird aber nicht die absolute Funktionsadresse angesprungen wird.
Hat bestimmt was mit Optimierung zu tun. Die selbe Funktion
(vSetAlarm_LED) wird aber auch über die Taskfunktionen (u8Add_Time_Task,
u8Check_Time_Task und u8Remove_Time_Task) benutzt, und hierfür wird kein
Trampoline (hier würde die absolute Adreesse benötigt) angelegt.
Steffen Graap schrieb:
> In meinem richtigen Projekt hab ich mal 32k FLASH-Müll eingefügt, und> nun hab ich 49 out of range error. Warum es im Testprojekt funktioniert,> und im richtigen Projekt nicht, ist mir ein Rätsel.
Nun, ein wichtiger Unterschied ist das eigene Linkerscript. Lass das
doch mal auf das Testprojekt los.
Stefan Ernst schrieb:
> Nun, ein wichtiger Unterschied ist das eigene Linkerscript. Lass das> doch mal auf das Testprojekt los.
Da hast du zwar recht, aber da der Unterschied in den Linkerscripten nur
magrinal ist (nämlich nur das einfügen des externen Speichers) hab ich
es gar nicht erst benutzt. Zum Beweis hab ich im Testprojekt auch das
Linkerscript benutzt, aber es gibt kein Unterschied.
An Unterschieden zwischen den Projekten fallen mir folgendes ein.
- Anzahl der benutzten Funktionen ~5 gegenüber ~100
- Anzahl der Aufrufe mit Funktionspointerübergaben 6 gegnüber 286
- Anzahl der übergebenen Funktionen 1 gegenüber ~30
Ich hab des Testprojekt mal erweitert. Und der error tritt jetzt auf.
Ich hoffe ich habe nicht wieder irgendetwas nicht beachtet, denn so
langsam Platzt mir der Kopf.
Anbei wieder das gezipte eclipse Projekt und die Ausgaben als Bild.
Ich denke das jetzt genügend Informationen zur Verfügung stehen um den
Bug oder meine Unzulänglichkeit ;-) zu finden.
Gruß Steffen
Tja, dann muss ich mal auf einen meiner ersten Tipps zurückkommen. Mit
einem "-Wl,--relax" verschwinden die Probleme in deinem Testprojekt. Und
wenn ich mir den Output weiter oben nochmal genau ansehe, dann hast du
dort das --relax auch gar nicht an den Linker übergeben ("-Wl," fehlt).
das -Wl fügt eclipse wohl automatisch mit dazu. Das --relax hatte ich
drin da es nichts gebracht hat hab ich es wieder entfernt.
Hier das ganze mit b eiden Zusätzem zum Linker.
Muss der Compiler die Zusätze auch bekommen?
Building target: Pointertest.elf
Invoking: AVR C Linker
avr-gcc -Wl,-Map,Pointertest.map -g --relax -mmcu=atmega2560
-o"Pointertest.elf" ./Code/funktionen.o ./Code/main.o ./Code/task.o
./Code/tim.o -lm
./Code/funktionen.o: In function `vTestFunktion6':
../Code/funktionen.c:63: warning: internal error: out of range error
../Code/funktionen.c:63: warning: internal error: out of range error
./Code/funktionen.o: In function `vTestFunktion7':
../Code/funktionen.c:72: warning: internal error: out of range error
../Code/funktionen.c:72: warning: internal error: out of range error
./Code/funktionen.o: In function `vTestFunktion8':
../Code/funktionen.c:81: warning: internal error: out of range error
../Code/funktionen.c:81: warning: internal error: out of range error
./Code/funktionen.o: In function `vTestFunktion9':
../Code/funktionen.c:90: warning: internal error: out of range error
../Code/funktionen.c:90: warning: internal error: out of range error
Finished building target: Pointertest.elf
Steffen Graap schrieb:
> das -Wl fügt eclipse wohl automatisch mit dazu.
Na, offensichtlich wohl nicht, ...
> Invoking: AVR C Linker> avr-gcc -Wl,-Map,Pointertest.map -g --relax -mmcu=atmega2560
... oder siehst du hier etwa ein "-Wl," vor dem "--relax"?
-mrelax sollte auf der Compiler-Kommandozeile auch gehen, der Compiler
übersetzt das dann beim Linken in ein --relax an den Linker.
Allerdings sollte man mittels --relax zwar ggf. kürzeren Code erhalten,
aber eigentlich ist die Option nicht dafür gedacht, Fehler beseitigen
zu helfen.
Jörg Wunsch schrieb:
> Allerdings sollte man mittels --relax zwar ggf. kürzeren Code erhalten,> aber eigentlich ist die Option nicht dafür gedacht, Fehler beseitigen> zu helfen.
Gibt es eine Doku zur "Linker Relaxation" bei AVRs?
Wenn ich mir den in der ld-Doku enthaltenen diesbezüglichen Part zu
68HC11/68HC12 anschaue, gibt es z.B. dort einen Einfluss von --relax auf
den Themenbereich Adressen/Sprünge/Aufrufe.
Und dass die Tampolines auf der gleichen Seite genannt werden, ist doch
auch irgendwie "verdächtig". ;-)
http://sourceware.org/binutils/docs/ld/M68HC11_002f68HC12.html#M68HC11_002f68HC12
Stefan Ernst schrieb:
> Gibt es eine Doku zur "Linker Relaxation" bei AVRs?
Nö.
Du kannst allerdings Recht haben. Soweit ich mich erinnere, hat
Björn Haase die linker relaxations in der Tat vor den trampolines
implementiert.
Sorry, das ich mich nich früher gemeldet habe. Der Admin hat den Proxy
runtergefahren und ich war vom Netz getrennt. Musste also erst mal nach
Hause, und nach dem Schneeschippen bin ich nu soweit.
Stefan Ernst schrieb:
> Na, offensichtlich wohl nicht, ...>>> Invoking: AVR C Linker>> avr-gcc -Wl,-Map,Pointertest.map -g --relax -mmcu=atmega2560>> ... oder siehst du hier etwa ein "-Wl," vor dem "--relax"?
Das löst das Problem, und nicht nur im Testprojekt. Ich dachte das sind
zwei Zusätze, die nicht zusammen gehören und das Komma sei das
Trennzeichen.
War also doch meine Unzulänglichkeit.
Ich muss mich wohl doch mehr mit den Innerein des "Werkzeuges" Compiler
beschäftigen.
Trotzdem nochmals einen herzlichen Dank an alle Beteiligten.
Gruß Steffen
Was passiert jetzt mit dem Bugeintrag?
Steffen Graap schrieb:
> Was passiert jetzt mit dem Bugeintrag?
Den kann ich ja mit Verweis auf -mrelax bzw. -Wl,--relax beruhigt
schließen. Möglicherweise mach' ich noch einen FAQ-Eintrag draus.
Moin
Ich bin gerade dabei einen Bootloader zu schreiben. Wenn ich hier den
Taskmanager nutzen wollte, der ja die Funktionspointer benutzt, hätte
ich wohl ein Problem. Die "Trampoline-Krügge" funktioniert ja Aufgrund
der Verschiebung der text.-Section nicht.
Gibt es, oder wird es für diesen Fall eine Lösung geben?
Gruß Steffen
Verstehe ich nicht ganz, welcher "task manager"?
Ein Bootloader braucht doch normalerweise nur RJMP/RCALL, und einen
einzigen langen EIJMP, mit dem er die Applikation anspringt. Den
kann man allemal mit der Hand codieren, wenn's sein muss.
Jörg Wunsch schrieb:
> Verstehe ich nicht ganz, welcher "task manager"?
Da muss ich ein wenig weiter ausholen.
Das System besteht aus mehreren Controllern (4 Stück). Einer diese
Controller hate einen FLASH, der auch vom PC als Massenspeicher benutzt
werden kann. Auf diesen FLASH wird vom PC eine Datei abgelegt, in der
die Updatedaten aller Controller enthalten sind. Der Controller hat
jetzt die Aufgabe den Inhalt der Datei an die anderen Bootloader zu
verteilen, damit diese das Update durchführten können.
Da hierbei etwas mehr zu tun ist als nur Daten von einem
Kommunikationsport in den FLASH zu schreiben. Ich wollte mein weiter
oben erwähnten Taskmanager / Sceduler benutzen um Aufgabe (Task) wie
z.B. Kommunikationstimeouts, Pollingintervalle ect. zu setzen.
Dieser Taskmanager benutzt Funktionspointer um sich die auszuführende
Aufgabe zu merken.
Gruß Steffen
Hmm, kann ich mir gerade zu wenig vorstellen, welche Implikationen
das nun auf die Zeiger hat. Schlimmstenfalls musst du das halt
wirklich mit inline asm machen.
Die Funktionspointer werden im Bootloader ganz sicher nicht
funktionieren, da ja auch die Trampolines dann über 128k liegen. Sattle
doch im Bootloader auf eine Lösung um, die keine Funktionspointer
benötigt (*). Du könntest z.B. statt dem Pointer eine ID speichern. Und
statt den Pointer zu dereferenzieren (um die Funktion aufzurufen), rufst
du eine Dispatcher-Funktion mit dieser ID auf, die dann die eigentliche
Funktion aufruft.
(*) Ich denke das wird einfacher sein, als zu versuchen, mit Inline-ASM
im Bootloader die Funktionspointer zum funktionieren zu bringen.
@ Stefan
so in etwa habe ich mir das auch schon überlegt.
Es Besteht bei mir nicht wirklich ein Problem. Ich habe das Thema hier
nur nochmals angesprochen, weil die "Trampoline-Krügge" (nicht böse
gemeint) hier versagt. Wie weiter oben schon angesprochen wäre eine
Erweiterung der Funktionspionter auf >=22Bit die sichere Lösung die auch
im Bootloader funktioniert.
Vieleicht kann man ja mal über eine Änderung in entsprechenden Kreisen
nachdenken.
Gruß Steffen
Steffen Graap schrieb:
> Vieleicht kann man ja mal über eine Änderung in entsprechenden Kreisen> nachdenken.
"nachdenken" hilft da nicht. ;-) Wenn sich keiner findet, der die
Zeit (geschätzt Mannmonate bis Mannjahre) investiert, GCC eine
Harvard-Architektur näher zu bringen, die dann innerhalb einer
Architektur verschieden große Zeiger verkraftet, dann kannst du
darüber nachdenken, bis der Arzt kommt. Ist ein typischer Fall von
Opensource: diejenigen, die das Feature so sehr benötigen, dass sie
ohne dieses nicht mehr weiterarbeiten möchten, müssen letztlich auch
daher kommen und es implementieren. Die Mainstream-GCC-Entwickler,
die einen i386 oder amd64 ihr eigen nennen, haben doch keinerlei
Motivation, in ein derartiges Feature Aufwand zu stecken.
(Alternative: solche Aktionen wie Google summer of code.)