Hallo Zusammen,
Hallo GCC-Compiler-Experten,
Ich habe wohl einen Bug am avr-gcc entdeckt:
Ich arbeite an einem grösseren System (Atmega 2560 / WinAVR 20071221).
Die Codegrösse (binär) liegt bei ca 135kB. Bisher lief über ein Jahr
alles normal. Aber plötzlich crasht das System, sobald ich eine weitere
Komponente hinzufüge. Egal was, ob eine weitere Funktion oder z.B. die
scanf_float library.
Der Crash wird nicht durch die hinzugefügte Funktion verursacht.
Die Ursache ist wohl die sprintf und sprintf_P-Funktion, die oft
verwendet wird. Ich habe mir mal das Map-File angesehen.
Anscheindend läuft die Funktion oder nicht, je nachdem, wohin sie
gelinkt wird. Wird sie unterhalb 128kB gelinkt, läuft sie, wird sie
oberhalb 128kB gelinkt, führt sie zum Absturz.
Wie kann das sein? Ich sitze seit einem Monat an diesem Fehler, und das
behindert das ganze Projekt, das seit gut einem Jahr entwickelt wird.
Ich bin am Verzeweifeln. Wenn ich keine Lösung finde, muss ich wohl den
Compiler wechseln mitsamt der ganzen Toolchain.
Ich wäre seeehr froh, wenn jemand einen Rat wüsste. Danke.
Chris
Teste, ob das Problem nur bei deinem alten WinAVR auftritt oder auch in
neueren WinAVR Versionen.
Wenn neuere Versionen ebenfalls betroffen sind, dann stelle einen
Sourcecode bereit, mit dem das Problem für Dritte reproduzierbar ist.
Es wäre optimal, wenn es möglich ist, das Problem zu identifizieren,
ohne einen Atmega 2560 zu haben und geht/geht nicht anhand eines
Runtime-Crashs zu entscheiden. Kannst du hierzu was sagen?
Das bisherige Programm konnte ich so nicht im Simulator laufen lassen,
da doch an zu vielen Stellen auf weitere Peripherie zugegriffen wird.
Andere mögliche Ursachen wie Stack Overflow oder Interruptroutinen habe
ich auch geprüft, das ist es wohl nicht.
Ok, ich werde bis morgen mal einen entsprechenden Code zusammenstellen.
Bis denn...
Ich bin ueberrascht, dass du so lange keine Probleme hattest - ich habe
noch irgendwo im Hinterkopf, dass der AVR-gcc Probleme mit mehr als 64k
Codegroesse hat? Ich kann aber keine Aussage dazu machen, wie
zuverlaessig diese Information ist und meine eigene Arbeit ist noch ein
gutes Stueck davon entfernt.
Peter Stegemann wrote:
> Ich bin ueberrascht, dass du so lange keine Probleme hattest - ich habe> noch irgendwo im Hinterkopf, dass der AVR-gcc Probleme mit mehr als 64k> Codegroesse hat? Ich kann aber keine Aussage dazu machen, wie> zuverlaessig diese Information ist und meine eigene Arbeit ist noch ein> gutes Stueck davon entfernt.
Die 64k beziehen sich auf mehrere Sachen mit unterschiedlicher
Bedeutung. Beim Code sind es 64k-words (128kbyte) ab welcher segmentiert
werden muss und es aufwending wird. Bei RAM bestehen die normalen 64K
Grenzen. Wenn Daten im Flash abgelegt werden die per Programm ausgelesen
werden gibt es wieder 64Kbyte Probleme und es muss Segmentiert werden.
Also die üblichen Probleme :-).
CA Dirk
Der Unterschied liegt in der Return-Adresse. Die ist bei AVRs mit mehr
als 64KW Flash nicht mehr 2 Byte sondern 3 Byte gross. Das muss der
Compiler berücksichtigen und wenn Assembler-Code beteiligt ist evtl.
auch dieser. Es kann folglich nicht der gleiche Binärcode der Library
für AVRs bis 64KW und für solche darüber verwendet werden.
Soweit ich weiss wird aber jenseits 64KW nichts segmentiert, sondern es
wird mit eingefügten Sprungbefehlen dafür gesorgt, dass alle Funktionen
mit einer Einsprungadresse in den ersten 64KW erreicht werden können.
Dadurch wird vermieden, sämtliche Adressen auf 24 Bit erweitern zu
müssen.
Sieht danach aus. Da das springen mit diesen Jumptables nicht ganz
trivial ist gibt es immer wieder Probleme damit. Ich habe auch
Festgestellt das es auch von Version zu Version des AVR-GCC anders ist
:-), ja nach dem wie gepatcht wurde. Bosonders ärgerlich ist dieses
Problem wenn man viele "Daten" im Flash hat die mehr als 64Kbyte
belegen, da bekommt der AVR-GCC dann Probleme.
CA Dirk
Guten Morgen!
Wie ich sehe, scheint das Thema ja einige zu interessieren. Schön. So,
anbei habe ich nun ein kleines Beispielprojekt für WinAVR bzw. AVRStudio
4.14. Die Vermutung bestätigt sich: Wenn sprintf oberhalb 128kB gelinkt
wird, stürzt das Programm auch im Simulator ab. Hier meine
main-Funktion:
int main(void)
{
char str[20];
int i=0;
dummy_funktion_1();
dummy_funktion_2();
dummy_funktion_3();
dummy_funktion_4();
dummy_funktion_5();
dummy_funktion_6();
dummy_funktion_7();
sprintf(str,"Test %d",i); //Hier Haltepunkt 1
i=1; //Haltepunkt 2
return i;
}
Wenn dummy 6 und 7 auskommentiert werden (und auch die
Funktionsdefinitionen) läuft das Programm bis Haltepunkt 2. Mit dummy 6
und 7 ist bei HP 1 finito.
Anbei habe ich das Paket fürs AVR-Studio (4.14). Schaut es Euch an.
Was kann man da machen???
Anbei das Projekt mitsamt lss Datei.
Zur Info: Das Makefile basiert auf der Standard-Vorlage, falls jemand
was ändern möcht. Die Optimierung ist ausgeschaltet, da sonst meine
dummy_funktionen geschrumpft werden.
Ich habe den Test gerade auch mal mit der neusten WinAVR 20080610 / GCC
4.3.0 Version durchgeführt. --> Leider der gleiche Fehler wie bei der
alten.
???
Das Problem scheint an der printf-library zu liegen, nicht am Compiler.
Denn eine Funktion die aktuell compiliert und >128kB gelinkt wurde läuft
korrekt (z.B. dummy_funktion_7 bei 0x000208f6).
Nur Funktionen, die aus der Library angespungen werden und >128kB liegen
führen zum Absturz. Vielleicht wäre die Lösung, dass man die printf- und
andere libs nochmal mitkompiliert, anstatt sie als lib einzubinden ?
Das duerfte das Problem loesen - alternativ den Compiler anpassen, dass
er vorkompilierte Bibliotheken immer im unteren Bereich ablegt. Kannst
dir ueberlegen, welche Loesung einfacher ist ;-)
Ja, nur wie?
Idee 1) librarys neu kompilieren:
Wo finde ich die printf und die anderen Libs als source? Die sind im
WinAVR-Paket nur als fertige libs dabei.
Idee 2) libs in den Bereich <128kB linken.
Wie geht das? Wie muss ich das Makefile modifizieren oder ein geht das
über ein Linkerskript? Es gibt ja eine sektion .lowtext. Man könnte
versuchen die libs in diese sektion reinzulinken. Oder man macht eine
neue Sektion zwischen .lowtext und .text, in die man die libs packt, das
geht ja über ein Linkerskript.
Nur wie sagt man dem Linker, dass er die libs da reinlinken soll?
Danke für den Tip.
Ich habe mir die Librarys heruntergeladen und angeschaut. Das
Neukompilieren kommt mir doch etwas komplizierter vor, als ich dachte,
wenn ich mir die Makefiles anschaue. Da gibt es ja eine Unmenge von
Optionen und Variablen. Vielleicht versuce ich erst die 2. Lösung -
Linken in den unteren Bereich. Nur wie geht das?
Das Neucompilieren wird dir nicht viel helfen, es wird lediglich zum
gleichen Ergebnis führen (hoffentlich -- sonst hätten wir was falsch
gemacht).
Du solltest das Problem erstmal analysieren.
Sorry, ich habe diese Woche selbst keinerlei Zeit, mir das anzusehen.
Ich komme nicht dazu, das Problem noch weiter zu analysieren, habe
einfach zu wenig Zeit und Ahnung, mich mit den Details des Compilers zu
beschäftigen. Ich habe den Bug bei Sourceforge gemeldet und auch schon
die Antwort erhalten, dass der in der kommenden WinAVR Version behoben
sein wird.
Siehe:
https://sourceforge.net/tracker/?func=detail&atid=520074&aid=2064430&group_id=68108
Nun noch die Frage an die Entwickler: Wann kommt die nächste WinAVR
Version raus?
Denn ich stehe wegen diesem Bug auch finanziell ganz schön auf dem
Schlauch. Ich werde nach Projektfortschritt bezahlt. Und es ist ja auch
ein Problem das ALLE Atmega 2560/2561 - Programme betrifft - in welchem
Programm kommt keine printf-Funktion vor?
Chris wrote:
> Ich komme nicht dazu, das Problem noch weiter zu analysieren,...
OK, das hat ja offenbar auch schon jemand getan.
Entsprechend Anatoliys Antwort würdest du übrigens offenbar zuerst
einen neu gebauten Compiler benötigen und mit diesem dann die
avr-libc neu compilieren müssen.
> Nun noch die Frage an die Entwickler: Wann kommt die nächste WinAVR> Version raus?
Keine Ahnung im Moment, wie Erics Pläne dafür aussehen. Ich bin
gerade aus dem Urlaub zurück.
> Denn ich stehe wegen diesem Bug auch finanziell ganz schön auf dem> Schlauch.
Ist es denn eine Option, dass du auf die 20071224-Version von WinAVR
zurück gehst? Die sollte davon nicht betroffen sein.
Hallo Jörg, danke für die schnelle Antwort.
Du meinst wahrscheinlich die 20071221er Version. Leider hat diese auch
das Problem. In diesem Jahr habe ich bisher nur diese Version
eingesetzt. Mit den 2008er Versionen hatte ich ein anderes Problem mit
Assemblercode (aber nicht ganz so gravierend, lässt sich wohl
work-arounden)
Gruß
Christian
Wie viele Funktionen aus der Library brauchst du denn? printf() ist zwar
maechtig, aber auch kein Hexenwerk, liese sich zur Not auch selbst
schreiben (oder eben "leihen" und in den eigenen Code einpassen).
Wenn der Compiler selber der Übeltäter ist, dann ist der Ersatz von
printf nur begrenzt hilfreich, denn das Problem kann dann auch anderswo
auftreten. Das es grad printf erwischt hat, ist dann eher darauf
zurückzuführen, dass der Linker die Funktionen der Lib hinten dran
hängt.
Hi,
der Fehler ist zu umgehen. Nur auf -mcall-prologues verzichten und die
paar libc-Funktionen, die scheinbar mit dieser Option kompiliert sind
via Linkerscript in die unteren 128k lokatieren. Dazu gehören folgende
Funktionen, dei ich in meinem Projekt identifiziert habe (ist
wahrscheinlich nicht vollständig, lässt sich aber im .map-File durch
Suche nach _prologue_saves__ und __epilogue_restores_ verifizieren)
Alle Funktionen, die diese Beiden benutzen müssen unterhalb der 128k
Grenze liegen. Auszug aus Linkerscript:
/* for code that needs to reside in the lower 128k progmem */
_unord_sf.o (.text) /* used by vprintf */
_prologue.o (.text.libgcc) /* prolog routine */
_epilogue.o (.text.libgcc) /* epilog routine */
*(.lowtext)
*(.lowtext*)
Alle weiteren projektspezifischen Funktionen, die prolog und epilog
benutzen, gehören dann auch noch in diese Sektion.
Gruss und hoffe es hilft
Tmo
Hallo Tmo,
danke für den Tip. Ich denke auch das ist die Lösung.
Bei mir kommt nur eine Fehlermeldung, wenn ich das das Projekt mit dem
modifizierten Linkerskript kompiliere:
...ld.exe: cannot find _prologue.o
Warum findet er nach der Modifikation des Linkeskripts diesen Objektcode
auf einmal nicht? Ich habe versucht, im WinAVR-Makefile die
entsprechende Bibliothek (libgcc.a) nochmal manuell nachzulinken:
LDFLAGS = -Wl,-lgcc
LDFLAGS = -Wl,-L"C:\Program Files\WinAVR\lib\gcc\avr\4.2.2\avr6"
, das hilft aber nicht.
Gruß
Christian
Hi,
sorry, habe Dir wohl einen Auszug aus einem Testscript geschickt :-(
Anbei das Richtige. Die Fehlermeldung kommt wohl von internen
Namenserweiterungen, wenn eine Lib erstellt wurde, deswegen:
/* for code that needs to reside in the lower 128k progmem */
_unord_sf.o (.text)
_prologue.o (.text.libgcc)
_epilogue.o (.text.libgcc)
*(.lowtext)
*(.lowtext*)
Gruss
Ich grab mal den Thread aus, weil das Problem ja immer noch besteht
(WinAVR 20100110).
1
0002239c<fputc>:
2
2239c:0f93pushr16
3
2239e:1f93pushr17
4
223a0:cf93pushr28
5
223a2:df93pushr29
6
223a4:8c01movwr16,r24
7
223a6:eb01movwr28,r22
8
223a8:8b81lddr24,Y+3;0x03
9
223aa:81ffsbrsr24,1
10
223ac:1bc0rjmp.+54;0x223e4<fputc+0x48>
11
223ae:82ffsbrsr24,2
12
223b0:0dc0rjmp.+26;0x223cc<fputc+0x30>
13
223b2:2e81lddr18,Y+6;0x06
14
223b4:3f81lddr19,Y+7;0x07
15
223b6:8c81lddr24,Y+4;0x04
16
223b8:9d81lddr25,Y+5;0x05
17
223ba:2817cpr18,r24
18
223bc:3907cpcr19,r25
19
223be:64f4brge.+24;0x223d8<fputc+0x3c>
20
223c0:e881ldr30,Y
21
223c2:f981lddr31,Y+1;0x01
22
223c4:0193stZ+,r16
23
223c6:f983stdY+1,r31;0x01
24
223c8:e883stY,r30
25
223ca:06c0rjmp.+12;0x223d8<fputc+0x3c>
26
223cc:e885lddr30,Y+8;0x08
27
223ce:f985lddr31,Y+9;0x09
28
223d0:802fmovr24,r16
29
223d2:1995eicall;====>KrachBoomBang
Es wird einfach vergessen, das EIND Register zu setzen.
Es wird nur einmalig zu Programmbeginn gesetzt:
1
00000234<__ctors_end>:
2
234:1124eorr1,r1
3
236:1fbeout0x3f,r1;63
4
238:cfefldir28,0xFF;255
5
23a:d1e2ldir29,0x21;33
6
23c:debfout0x3e,r29;62
7
23e:cdbfout0x3d,r28;61
8
240:00e0ldir16,0x00;0
9
242:0cbfout0x3c,r16;60=EIND
Gibt es da wirklich keine Lösung?
Warum überhaupt ein EICALL an dieser Stelle?
Ich arbeite doch bisher nirgends mit Funktionspointern.
Ich würde das natürlich auch gerne noch machen für meinen Scheduler.
Kann man Funktionspointer als far (32Bit Pointer) deklarieren?
Peter
Peter Dannegger schrieb:
> Kann man Funktionspointer als far (32Bit Pointer) deklarieren?
Nein. Du kannst aber auch mit den normalen 16Bit Pointern eine Funktion
oberhalb 128k aufrufen. Dann wird im unteren Bereich ein Trampoline
angelegt. Diesbezüglich könnte dieser Thread für dich interessant sein:
Beitrag "warning: internal error: out of range error"
Stefan Ernst schrieb:
> Peter Dannegger schrieb:>> Kann man Funktionspointer als far (32Bit Pointer) deklarieren?>> Nein. Du kannst aber auch mit den normalen 16Bit Pointern eine Funktion> oberhalb 128k aufrufen. Dann wird im unteren Bereich ein Trampoline> angelegt.
Wie schaltet man denn dieses Trampoline ein?
Ist das dann nur für meine Funktionen oder auch für die Lib?
Peter
Peter Dannegger schrieb:
> Wie schaltet man denn dieses Trampoline ein?
Die produziert der Linker automatisch, wenn dem Funktionszeiger eine
Funktion zugewiesen wird, die jenseits der 128k liegt.
> Ist das dann nur für meine Funktionen oder auch für die Lib?
Sollte auch für Lib-Funktionen funktionieren.
PS: Wichtig ist, dass du beim Linken die Option -Wl,--relax benutzt.
Stefan Ernst schrieb:
> Sollte auch für Lib-Funktionen funktionieren.
Leider nicht wirklich.
In dem Trampolin stehen brav alle Funktionen meines Schedulers drin.
Auch ein "__muldi3+0xc" steht drin, welches "__prologue_saves__"
aufruft.
Soweit also alles o.k.
Aber das verflixte "fputc" macht weiter seinen EICALL in den Wald.
Da scheint also ein schwerer Bug in der fputc/fgetc-Lib zu sein.
Peter
Peter Dannegger schrieb:
> Da scheint also ein schwerer Bug in der fputc/fgetc-Lib zu sein.
Nein. Die Bibliothek enthält ja nur C-Code. Wenn, müsste es ein
Bug im Compiler sein.
Der Bug liegt aber im Prinzip. Das Trampolin nützt hier nichts.
Das fdevopen() (oder der vergleichbare Makro) trägt brav die Adresse
der put-Funktion in die interne Struktur ein, die hinter FILE steht.
An dieser Stelle weiß es einfach nicht, aus welchem der 128-KiB-
Segmente es später benutzt wird, es kann also nur die direkte Adresse
eintragen. Da der GCC nie für eine Harvard-Architektur geschrieben
worden ist, kann er für eine Zielplattform auch nur eine Größe von
Zeiger implementieren. Da nun niemand alle SRAM-Zeiger plötzlich auf
32 bit haben will, bleibt die Zeigergröße natürlich nach wie vor
16 bit.
Wenn der Compiler nun in fputc() die "put"-Funktion aufrufen will,
dann hat er also nur 16 bit an Information vorliegen. Er tut sein
bestes und implementiert einen EICALL, aber das EIND fasst er in der
Tat nicht an -- die Information, die er in EIND hinein schreiben
müsste, besitzt er schlicht und ergreifend gar nicht, denn die steht
im genannten Funktionszeiger gar nicht drin!
Möglicherweise könnte man einen würgaround in der Bibliothek
implementieren, der auf CPUs mit > 128 KiB Flash-ROM statt eines
Funktionszeigers eine uint32_t-Zahl nimmt und dann die Indirektion
später zu Fuß in inline asm schreiben. Allerdings kann einen
natürlich diese böse Falle immer wieder einholen...
Patches welcome. ;)
Jörg Wunsch schrieb:
> Das fdevopen() (oder der vergleichbare Makro) trägt brav die Adresse> der put-Funktion in die interne Struktur ein, die hinter FILE steht.
Danke für die Erklärung.
Also muß ich alle Funktionspointer, die an fdevopen()übergeben werden,
nach unten linken lassen.
Und alles andere funktioniert dann über das Trampolin.
Peter
Wenn ich das so lese werde ich wohl nie einen AVR mit mehr als 128k
nutzen sondern gleich auf nen ARM gehen, dort sollte dieser Hickhack
nicht auftauchen.
MFG
Falk
Falk Brunner schrieb:
> dort sollte dieser Hickhack> nicht auftauchen.
Nein, tut er nicht. Dafür ist der ARM dann an anderen Stellen deutlich
komplizierter als ein AVR.
Also mal eben mit einer Minimalbeschaltung ganz schnell etwas
ausprobieren geht nicht immer. Trotzdem arbeite ich auch gerne mit den
ARM (Cortex-M3).
Das 64KiB (Datenspeicher) und 64KiWord (Programmspeicher) Problem hat
sich ja durch die XMega auch noch etwas verschärft. Ich denke, dass hier
auf jeden Fall eine Lösung gefunden werden muss und zwar auch für
Datenspeicherzugriffe im 24 Bit Adressraum. Es wäre schade, wenn die
Möglichkeiten des XMegas und der großen AVRs am Ende an
Compilerlimitierungen scheitern.
@Joerg:
Ich dachte für diesen Fall gibt es extra die Trampolines. Wenn ich die
Ausgabefunktion in die Filestruktur eintragen lasse, dann wird doch auf
die Funktionsadresse indirekt zugeriffen und der Linker erzeugt
automatisch dann einen Trampolineeintrag, nur wenn die referenzierte
Funktion auch in den oberen 128kb liegt. Das erlaubt dann das
Funktionieren des EICALL mit EIND=0. Funktioniert bei meinem OS schon
seit WinAVR2007schiessmichtot probelmlos. Das wirkliche Problem war
meines Wissens nur das Erstellen der Libs mit
save_call_prologues/epilogues in Verbindung mit dem erweiterten
Stackpointer, wofür ich oben eine Lösung gepostet hatte.
Trampolines tauchen bei mir nur unter zwei Bedingungen auf:
- es wird eine Funktionsadresse im Code verwendet (z.B.
Funktionpointerarray, Taskfunktionen, fputc mit Stream-IO ...)
- die indirekt verwendete Funktion liegt in den oberen 128kb Flash
Oder habe ich da was falsch verstanden ?!
Gruss
tmo
Trampolines müssen auch benutzt werden, um von einem 128-KiB-Block
eine Funktion in einem anderen 128-KiB-Block zu rufen.
Was soll das Trampoline bei einem Funktionszeiger helfen? Entweder,
er liegt im ersten 128er Segment und ist per EIND = 0 (was der
default sein sollte) erreichbar, oder das Trampoline hilft auch
nicht.
Oder habe ich das was falsch verstanden? ;-)
das Trampoline hilft schon dabei, da der EICALL nicht auf dei Funktion
in den oberen 128kb geht, sondern auf den Trampolineeinsprung und somit
immer in den unteren 128kb landet ...
Gruss
... der RCALL beim 2560 kann auch den ganzen 256kb Flash dirket ohne
Trampoline ansprechen. Lediglich bei indirektem Funktionsaufruf via
EICALL wird ein Trampoline fällig (wegen der EIND-Problematik). EICALL's
werden aber vom Compiler nur erzeut, wenn ein Funktionszeiger verwendet
wird ...
oder bin ich da falsch ...
Gruss
tmo
Ohje Ohje, Würg around ^3.
Kennen wir diesen Unsinn nicht aus 286er Zeiten, mit Segmenten.
Weg mit dem Müll!!
Wie wäre eine Compileroption, welche zwischen 16 und 24(32) Bit Pointern
umschaltet? Machbar? Sinnvoll?
MFG
Falk
ja Falk, das wäre sicher wünschenswert. Führt aber natürlich zu einem
kompletten Umbau des Compilers für das AVR-Target und sicher zur
Vergrösserung des Codes und RAM-Bedarfs, da ja dann alle Pointer 24 oder
32 Bit sein müssten. Die Lösung mit den Trampolines funktioniert recht
zuverlässig, verbraucht nicht zuviel Speicher und Rechenzeit und wird
nur bei indirekten Funktionsaufrufen benötigt (falls ich mich nicht
komplett irre), da ja sonst ein rcall problemlos seinen Dienst tut (das
hier beim 2560 zusätzliche Byte beim rcall auf dem Stack hat auch die
Probleme mit den prologues/epilogues gemacht). Die Lösung von IAR mit
den getaggten/smarten Pointern wäre auch eine Lösung ist aber so im GCC
sicher nicht vorgesehen und erfordert ähnlichen Umbauaufwand. Zusätzlih
gibt es ja leider unter C auch keinen nativen 24Bit Datentypen ...
Gruss
tmo
Tmo schrieb:
> ... der RCALL beim 2560 kann auch den ganzen 256kb Flash dirket ohne> Trampoline ansprechen.
Ein RCALL? Eher nicht. ;-) Der kann +-4 Kib adressieren.
Du hast aber Recht, ein CALL kann den kompletten Adressbereich
ansprechen.
Ich bin da mittlerweile auch ein wenig verwirrt mit den Trampolines,
muss ich zugeben.
Falk Brunner schrieb:
> Wie wäre eine Compileroption, welche zwischen 16 und 24(32) Bit Pointern> umschaltet? Machbar?
Das wäre eine komplett neue Portierung für den AVR, im Prinzip ein
zweiter Prozessor, selbst wenn man es noch im derzeitigen Port
unterbekommt. Soll nicht heißen, dass es gar nicht machbar wäre,
aber es wäre zumindest ein immenser Aufwand, einschließlich neuer
Bugs...
@Joerg:
mea culpa, Du hast recht ich meinte den CALL. Ich habe jetzt mal mit dem
aktuellen Compiler getestet. Es ist so wie beschrieben:
- Trampoline wird vom Linker nur bei indirekt referenzierten Funktionen
die in den oberen 128kb liegen erzeugt.
- der EICALL geht dann auf das Trampoline und wird dort via JMP in die
oberen 128kb gelenkt.
- alle normalen/anderen Aufrufe via RCALL oder CALL ohne Trampoline.
Um die Performance zu verbessern, empfiehlt es sich aber trotzdem alle
Funktionen, die indirekt referenziert werden (meist Taskfunktionen,
Stream-IO ...) in die unteren 128kb zu lokatieren. Das spart den
Trampolineeintrag und den zusätzlichen JMP. Als Alternative kann man ja
alle Interruptfunktionen in die oberen 128kb lokatieren, da die ja
sowieso mit einem JMP aus dem Int-Table gestartet werden.
Gruss
tmo
tmo schrieb:
> - Trampoline wird vom Linker nur bei indirekt referenzierten Funktionen> die in den oberen 128kb liegen erzeugt.>> - der EICALL geht dann auf das Trampoline und wird dort via JMP in die> oberen 128kb gelenkt.>> - alle normalen/anderen Aufrufe via RCALL oder CALL ohne Trampoline.
Gibt es zu diesem Thema irgendwo eine Doku? Hab schon mal kurz gegraben,
aber außer hier im Forum verstreute Infos hab ich nichts gefunden.
Also ich meine, wie der Machnismus im WinAVR implementiert ist.
@Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
>Das wäre eine komplett neue Portierung für den AVR, im Prinzip ein>zweiter Prozessor, selbst wenn man es noch im derzeitigen Port>unterbekommt.
Und wo bleibt da die vielzitierte Portabilität und Wartbarkeit, wenn
eine Umstellung der Pointer von 16 auf 32 Bit soooooo aufwändig ist?
Das es nicht mit einem einfachen define getan ist ist schon klar, aber
eine "komplett neue Portierung" halte ich für deutlich daneben.
>aber es wäre zumindest ein immenser Aufwand,
Wieso? Es muss doch nicht jede Funktion manuell komplett neu gemacht
werden, oder?
MfG
Falk
Falk Brunner schrieb:
> Und wo bleibt da die vielzitierte Portabilität und Wartbarkeit, wenn> eine Umstellung der Pointer von 16 auf 32 Bit soooooo aufwändig ist?
"Portabel" heißt doch nicht, dass du eine neue CPU gewissermaßen
"kostenlos" bekommst.
> Das es nicht mit einem einfachen define getan ist ist schon klar, aber> eine "komplett neue Portierung" halte ich für deutlich daneben.
Eine neue CPU-Portierung ist es schon. Die 95 % maschinenunabhängige
Dinge kannst du ja trotzdem weiter benutzen, dort liegt die eigentliche
Portabilität (einschließlich der vielen Optimierungen, die bereits auf
diesem Niveau laufen).
> Wieso? Es muss doch nicht jede Funktion manuell komplett neu gemacht> werden, oder?
Guck dir doch einfach mal an, wie viel es ist. ;-)