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.
Nun, dann habe ich ja noch etwas Platz, bis ich an die Grenze stosse - bei Chris scheint es mir aber auf das Problem zu passen?
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
Hi, habe jetzt gesehen, das die Erweiterungen hier im Web verschluckt werden: Also nochmal:
1 | /* for code that needs to reside in the lower 128k progmem */
|
2 | *_unord_sf*.o (.text) |
3 | *_prologue*.o (.text.libgcc) |
4 | *_epilogue*.o (.text.libgcc) |
5 | *(.lowtext) |
6 | *(.lowtext*) |
Gruss
Hallo Tmo, VIELEN VIELEN DANK !!! Es funktioniert jetzt. Dank Deinem Tip kann es jetzt wieder weitergehen. Schönen Gruß aus Berlin Christian
Ich grab mal den Thread aus, weil das Problem ja immer noch besteht (WinAVR 20100110).
1 | 0002239c <fputc>: |
2 | 2239c: 0f 93 push r16 |
3 | 2239e: 1f 93 push r17 |
4 | 223a0: cf 93 push r28 |
5 | 223a2: df 93 push r29 |
6 | 223a4: 8c 01 movw r16, r24 |
7 | 223a6: eb 01 movw r28, r22 |
8 | 223a8: 8b 81 ldd r24, Y+3 ; 0x03 |
9 | 223aa: 81 ff sbrs r24, 1 |
10 | 223ac: 1b c0 rjmp .+54 ; 0x223e4 <fputc+0x48> |
11 | 223ae: 82 ff sbrs r24, 2 |
12 | 223b0: 0d c0 rjmp .+26 ; 0x223cc <fputc+0x30> |
13 | 223b2: 2e 81 ldd r18, Y+6 ; 0x06 |
14 | 223b4: 3f 81 ldd r19, Y+7 ; 0x07 |
15 | 223b6: 8c 81 ldd r24, Y+4 ; 0x04 |
16 | 223b8: 9d 81 ldd r25, Y+5 ; 0x05 |
17 | 223ba: 28 17 cp r18, r24 |
18 | 223bc: 39 07 cpc r19, r25 |
19 | 223be: 64 f4 brge .+24 ; 0x223d8 <fputc+0x3c> |
20 | 223c0: e8 81 ld r30, Y |
21 | 223c2: f9 81 ldd r31, Y+1 ; 0x01 |
22 | 223c4: 01 93 st Z+, r16 |
23 | 223c6: f9 83 std Y+1, r31 ; 0x01 |
24 | 223c8: e8 83 st Y, r30 |
25 | 223ca: 06 c0 rjmp .+12 ; 0x223d8 <fputc+0x3c> |
26 | 223cc: e8 85 ldd r30, Y+8 ; 0x08 |
27 | 223ce: f9 85 ldd r31, Y+9 ; 0x09 |
28 | 223d0: 80 2f mov r24, r16 |
29 | 223d2: 19 95 eicall ; ====> Krach Boom Bang |
Es wird einfach vergessen, das EIND Register zu setzen. Es wird nur einmalig zu Programmbeginn gesetzt:
1 | 00000234 <__ctors_end>: |
2 | 234: 11 24 eor r1, r1 |
3 | 236: 1f be out 0x3f, r1 ; 63 |
4 | 238: cf ef ldi r28, 0xFF ; 255 |
5 | 23a: d1 e2 ldi r29, 0x21 ; 33 |
6 | 23c: de bf out 0x3e, r29 ; 62 |
7 | 23e: cd bf out 0x3d, r28 ; 61 |
8 | 240: 00 e0 ldi r16, 0x00 ; 0 |
9 | 242: 0c bf out 0x3c, 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.
nein, wüsste ich nicht :-( Habe alles aus diversion Foren, Quellcodes und rumprobieren für mich und meine Projekte ermittelt. Gruss tmo
@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. ;-)
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.