Hallo,
gibt es irgendeine Möglichkeit, eine Variable fest an ein Register zu
binden, so dass der avr-gcc sich da strikt dran hält?
Mit der Zuweisung
1
register uint8_t test asm("r5")
schaffe ich es zwar, dass der compiler die Variable da rein lädt, aber
er lagert sie trotzdem wohl mal ins Sram aus. Das Problem an der Sache
ist, dass ich einen modifizierten Atmel habe, bei dem Register breiter
sind, als das SRAM, was bedeutet, dass Daten verlorengehen, wenn sie
ausm Register geschoben werden.
Printf besipielsweise schluckt ja sehr viele Register...
Falls es noch keine Möglichkeit gibt, meint ihr es ist möglich, dem
COmpiler ein neues Attribut beizubringen, welches dann eben wirklich
bindend ist?
Danke schonmal =)
Gruß Peter
Es reicht nicht aus, die Hardware zu modifizieren. Schreibe bitte den
GCC entsprechend um, daß er Deine Hardware unterstützt. Dann gibt es
nicht nur eine Portierung für den AVR, sondern auch eine Portierung für
Deine HW.
Bernhard
Ja, das wäre natürlich ideal.
Gibt es da Dokumentationen zu?
Also es wurden schon Modifikationen an Opcodes vorgenommen, also neue
integriert in den assembler, die die HW unterstützt. Das einzige was
eben noch fehlt ist das mit den Registern.
Ich durchsuche die ganze Zeit schon alle Sources des Gcc nach den
entsprechenden Stellen, aber bis jetz noch erfolglos.
Also ich finde weder die Definition der Registerbreite in den Quellen,
noch die Definition von Attributen, wie eben die vom Typ "Register".
Wie schon erwähnt wäre es perfekt, ein neues Attribut zu definieren, das
eine Variable einem Register zuweist und zwar bindend!
Irgendein Tipp, oder ein Verweis auf entsprechende Dokus wäre super und
würde mir unglaublich helfen, da ich schon sehr lange an dem Problem
hänge.
Viele Grüße, und danke für die bisherige Antwort!
Peter schrieb:
> er lagert sie trotzdem wohl mal ins Sram aus. Das Problem an der Sache> ist, dass ich einen modifizierten Atmel habe, bei dem Register breiter> sind, als das SRAM, was bedeutet, dass Daten verlorengehen, wenn sie> ausm Register geschoben werden.
Was muss man sich darunter vorstellen?
Eventuell gibt es ja eine Lösung, bei der man nicht den Compiler
modifizieren muss. Aber ich kann mir mit deiner Beschreibung der
Modifikation nichts darunter vorstellen.
Die Regs sind breiter gemacht worden, um für bestimmte anwendungen
schneller zu sein.
Also beispielsweise haben die jetz 32 bit Breite.
Dann wird in der SW eine Variable reingeladen, meinetwegen noch ne
zweite und die addiere ich jetz zb.
Dann schieb ich die in ein Array aus 8bit Elementen, um das ganze dann
schöne ausgeben zu können.
Wenn ich jetz allerdings andere Befehle zwischen Berechnung und Asugabe
schreibe, speziell printf, passiert folgendes:
Weil printf wohl viele Regs braucht, wird das 32 Bit ergebnis aus dem
Reg ins SRAM gerettet. Und sobald printf durch is, wieder in mein Reg
geschoben.
Aaaaber, das SRAM is ja nur 8 bit breit, das heisst es konnte auch nur
die unteren 8bit retten.
Wenn ich dann mein ergebnis ausgebe, das sich im Reg befindet, hab ich
die unteren 8bit korrekt. Aber die üblichen sind nun 0, weil sich die
niemand gemerkt hat...
Eigentlich soll das Register attribut ja dafür sorgen, dass des gewählte
Register dem Compiler gar nich mehr zugänglich gemacht wird, aber leider
macht er in der Realität ja doch was er will.
wenn er nur 8bit von dem Register gerettet und wieder zurück geschrieben
werden müsste doch alles stimmen? Die restelichen 24Bit bleiben doch wo
sie sind oder etwas nicht?
Peter schrieb:
> Dann wird in der SW eine Variable reingeladen, meinetwegen noch ne> zweite und die addiere ich jetz zb.
Woher kommen denn die Werte beim reinladen? Diese müssen doch auch
irgendwie aus dem SRAM kommen, oder? Die Lade-Operation muss dann doch
auch 32 Bit sein?
Die Operationen, die printf oder ein anderes Unterprogramm aufrufen um
Register zu retten, heißen push und pop.
Wenn die Lade-Operationen 32 Bit breit sind, dann kannst Du doch auch
push und pop verändern, sodass push und pop mit 32 Bit werten arbeiten.
Wäre es nicht besser gewesen, einen ARM-Core zu benutzen, wenn du
breitere Register haben willst (oder irgendeinen anderen 32-bit-Core)?
Der AVR-Port des GCC ist nun ohnehin nicht wirklich optimal, wenn
du ihn jetzt noch mit sowas vermurksen willst, kommst du doch vom
hundertsten ins tausendste...
Warum nicht gleich ein 32 Bit Prozessor... ???
Nur den GCC zu ändern reicht sowieso nicht, die ganzen Libs müssen
wahrscheinlich auch noch geändert werden.
Das führt zu nix...außer einem riesen Batzen Entwicklungsarbeit.
Und wenn printf das einzige Problem ist... warum verzichtet man nicht
einfach darauf ?
Aber wenn es nur um 32-Bit additionen oder ähnlichen Kleinkram geht, und
das ganze auf einem FPGA stattfindet, gibt es da auch ganz andere
Lösungswege.
Kernfrage:
Neues Attribut definieren? Doku? Welche Stelle genau? Beispieldef vom
typ "Register"?
Wollte doch gar keine riesen Diskussion auslösen =)
Danke für alle hinweise, aber mir geht es um die punkte oben.
Dokumentation zum GCC: läßt sich finden.
In einem Teil des GCC wird die verwendete Hardware auf der Ebene RTL
beschrieben. Das ist Dein Ansatzpunkt. Ich gehe davon aus, daß dieser
Teil gut dokumentiert ist: Jeder, der neue HW in den GCC einfügt, hat
sich dort auszukennen.
Bernhard
Peter schrieb:
> Die Regs sind breiter gemacht worden, um für bestimmte anwendungen> schneller zu sein.
Ich hab dich immer noch nicht.
Wie kann man Register breiter machen?
> Na toll. Von Hamburg VHDL nen AVR geladen, dran rumgebastelt> und nun steckt er in der Sch...
Stimmt diese Vermutung?
Wenn ja, dann hast du im Grunde ja keinen AVR mehr vor dir liegen,
sondern einen anderen Prozessor. Da drafst du dich nicht wundern, wenn
der gcc damit nicht klar kommt.
> Eigentlich soll das Register attribut ja dafür sorgen, dass des gewählte> Register dem Compiler gar nich mehr zugänglich gemacht wird, aber leider> macht er in der Realität ja doch was er will.
Und das ist in der überwiegenden Mehrzahl der Fälle auch gut so.
Mit 'register' ist in der Vergangenheit ziemlich viel Humbug betrieben
worden. Compiler sind dazu übergegangen ihrer eigenen Datenflussanalyse
mehr zu vertrauen als dem was der Programmierer sich ausdenkt.
Karl heinz Buchegger schrieb:
> Wie kann man Register breiter machen?
Indem man die Wortbreite (und die Busbreite) vergrößert. Am besten
funktioniert dies durch Multiplikation mit einer Potenz von zwei :-)
Ja, die Modi ist in vhdl realisiert.
Ich weiss, es ist prinzipiell ein anderer Prozessor, aber wiederum auch
nicht, weil bis auf die Breite nix verändert wurde.
Und prinzipiell macht der Compiler ja auch brav das was er soll.
Wäre es dann prinzipiell eine Möglichkeit einen alten avr-gcc zu
verwenden?
Hat denn schonmal jemand von euch am Compiler selbst rumgeschraubt? Also
sowas in der Richtung von eigenen Attributen hinzufügen?
Wäre natürlich am schönsten, wenn das so irgendwie ginge, damit die
Entwicklungszeit in einem vertretbaren Rahmen bliebe...
Peter schrieb:
> Ja, die Modi ist in vhdl realisiert.
Na endlich!
Das man da aber immer erst alles 5 mal nachfragen und aus der Nase
ziehen muss.
> Ich weiss, es ist prinzipiell ein anderer Prozessor, aber wiederum auch> nicht, weil bis auf die Breite nix verändert wurde.
Doch ist es.
WinAvr geht von gewissen Eigenschaften des Prozessors aus, wenn du ihm
einen AVR unterjubelst. Da dein Proz diese Eigenschaften nicht hat, ist
es ein anderer Proz.
> Wäre natürlich am schönsten, wenn das so irgendwie ginge, damit die> Entwicklungszeit in einem vertretbaren Rahmen bliebe...
Der war gut!
Den 'vertretbaren Rahmen' hast du in dem Moment verlassen, indem du
beschlossen hast, deine eigene CPU zu kreieren.
Klaus Falser schrieb:
> Die Operationen, die printf oder ein anderes Unterprogramm aufrufen um> Register zu retten, heißen push und pop.> Wenn die Lade-Operationen 32 Bit breit sind, dann kannst Du doch auch> push und pop verändern, sodass push und pop mit 32 Bit werten arbeiten.
Und beten, dass der gcc nicht auf die Idee kommt, Arithmetik mit dem
Stackpointer zu betreiben. Das geht dann mit Sicherheit das eine oder
andere mal ins Auge.
Die ganze indirekte Adressierung von lokalen Variablen, die am Stack
angelegt wurden, wird dann nicht mehr stimmen, etc.
Sorry, da ich nicht zuviele details preisgeben darf(!) wollte ich mich
nunmal auf den Knackpunkt beschränken.
Ich hab das alles ja gar nich beschlossen! Ich darf nur Entscheidungen
anderer ausbaden (wie wir alle eigentlich immer) ;-) Ich hab eben die
genannte Problemstellung und muss nun eine Lösung dafür finden! Bin also
nur der Depp vom Dienst auf den ihr nich nur draufhauen sollt ;-)
Bin immer noch für jeden Vorschlag offen, da immer noch genauso rat- und
hilflos...
Viele Grüße
Karl heinz Buchegger schrieb:
> Klaus Falser schrieb:>>> Die Operationen, die printf oder ein anderes Unterprogramm aufrufen um>> Register zu retten, heißen push und pop.>> Wenn die Lade-Operationen 32 Bit breit sind, dann kannst Du doch auch>> push und pop verändern, sodass push und pop mit 32 Bit werten arbeiten.>> Und beten, dass der gcc nicht auf die Idee kommt, Arithmetik mit dem> Stackpointer zu betreiben. Das geht dann mit Sicherheit das eine oder> andere mal ins Auge.> Die ganze indirekte Adressierung von lokalen Variablen, die am Stack> angelegt wurden, wird dann nicht mehr stimmen, etc.
Naja, so ganz ernst war meine Antwort nicht gemeint, und in der
Zwischenzeit haben Ihm ja alle freudlichst klar gemacht, worauf er sich
einläßt :-)
Peter schrieb:
> Ja, die Modi ist in vhdl realisiert.
Na endlich!
>Bin immer noch für jeden Vorschlag offen, da immer noch genauso rat- und
hilflos...
Also, da fällt mir ein Märchen ein. Gestern gesehen.
Ein armes Bauernmädchen wird aufgefordert einem Stein die Haut
abzuziehen.
Sie willigt ein, wenn der Prinz erstmal dem Stein das Blut rauslässt,
weil sie eben kein Blut sehen kann.
Ebenso hier: Derjenige der die Entscheidung getroffen hat, den AVR so zu
verändern das die Register breiter werden, soll noch die Entscheidung
treffen, den GCC so umzuarbeiten, das er mit dem neuen Prozessor
arbeitet.
An sich müssten die Entscheidungen sowieso im selben Zuge getroffen
werden, wenn sowas gemacht wird.
Rechne ein paar Mann-Monate, wenn Du gcc gut kennst.
Vielleicht ein paar Wochen um mal irgendwas übersetzen zu können.
Ich gehe mal davon aus, das der Prozessor auch mal eben so larifari
"erweitert" worden ist und die ganze Arithmetik uswusf. wohl noch mal
angeguckt werden muss.
Handelt es sich eigentlich nur um 1 derartiges Register, oder sind alle
betroffen?
Wenn es nur 1 ist, dann würde ich mal dahingehend überlegen, dieses
Register vor dem gcc zu verstecken. Zb indem man es als r33 einführt und
dann alle Spezialoperationen (von denen der gcc ja auch nichts weiß)
mittels inline-Assembler zu realisieren. Bei Funktionsaufrufen muss man
halt aufpassen, das nicht innerhalb der Funktion wieder dieses
Spezialregister benutzt wird und im Notfall selbst um Push/Pop kümmern.
Also: keine Modifikation des AVR-Kerns sondern eine Erweiterung. Der AVR
Kern, so wie er dem gcc bekannt ist, belibt unangetastet und die
HW-Erweiterung wird über inline-Assembler angesprochen.
Peter schrieb:
> Ich hab eben die> genannte Problemstellung und muss nun eine Lösung dafür finden!
Bist du wenigstens Informatiker? Ich glaube, ansonsten hast du
ein ziemlich schweres Los, einen Compiler wie den GCC passend zu
modifizieren. (Btw., ich bin keiner, und ich gucke in weiten Teilen
des GCC-Codes wie das berühmte Tier ins Uhrwerk. ;-)
Ich würde an deiner Stelle anfangen, den AVR-Code im GCC komplett
zu clonen, vielleicht in ein Target namens "myavr" (oder
"my_schools_avr" :), und den dann modifizieren. Wenn du dir da
wirklich nur ein paar Register frei halten willst, die du dann
ausschließlich via Assemblercode beackerst, mag das vielleicht
gehen, wenn du dem register allocator im GCC einfach beibiegst,
dass er diese Register gar nicht erst kennen möge. Allzu viele
Register wirst du sicher nicht ohne größere architekturelle
Umbauten frei bekommen auf diese Weise, aber vielleicht genügen
dir ja ein paar.
Allerdings sehe ich schwarz, dass es irgendwie möglich ist, dass
man ihm ,,mal schnell'' beibringt, dass verschiedene Register in
unterschiedlicher Breite existieren.
Wie schon geschrieben, das ganze Projekt hätte man wohl lieber gleich
mit einem 32-bit-Core beginnen sollen, das wäre deutlich effektiver
gewesen, als hier die Zeit in schrägen Compilerhacks zu verplempern,
die nachher rettungslos verloren sind, weil sowas natürlich keiner
`upstream' im GCC einpflegen wird, sodass sie lediglich mit der
Compilerversion benutzbar sind, die du manuell gepatcht hast. Drei
GCC-Versionen weiter passt das niemand mehr mal einfach so an, damit
werden die entsprechenden Bits ganz schnell verrotten.
Jörg Wunsch schrieb:
> Bist du wenigstens Informatiker? Ich glaube, ansonsten hast du> ein ziemlich schweres Los, einen Compiler wie den GCC passend zu> modifizieren. (Btw., ich bin keiner, und ich gucke in weiten Teilen> des GCC-Codes wie das berühmte Tier ins Uhrwerk. ;-)
Ich bin einer.
Und ich hab mal vor Jahren versucht (zugegeben: nicht sehr intensiv) zu
verstehen, wie das funktioniert.
Ich habe nur 'Schienengebundenes öffentliches Verkehrsmittel
Haltestelle' verstanden und bin dagestanden wie das 'männliche
zeugungsunfähige Rindvieh vor der Öffnung, die der Maurer in der Wand
gelassen hat'
Ich hab dann für mich entschieden: Das ist sinnlos und auch nicht
zielführend.
Da schreibe ich lieber meinen eigenen Compiler. Das geht schneller, auch
wenn ich am Anfang nicht soviele Optimierungen drauf haben werde wie der
gcc.
Wenn man keinen 32Bit-Core implementieren will, würde ich eine art
CO-Prozessor schreiben, der dir deine 32Bit-Berechnungen macht. Den
sprichst du über deinen Speicher-Bus an.
Das ist (meistens, kommt auf deine Aufwendige Berechnung an) schneller
als die emulation von 32bit auf 8Bit-Cores.
ciao Volker
Nee, kein Info, sondern E-techniker ;-)
Sie sind nich 32 Bit breit, sondern noch mehr. Und es sind alle 32 Stück
verbreitert worden.
Wie schon erwähnt, im Prinzip funltioniert alles wunderbar! Ich habe
auch Routinen drin, die mir die Reg-Werte retten in die 8-Bit arrays.
Was jedoch wieder einige Rechenschritte kostet und der ganze clou an dem
system ist ja die Geschwindigkeit. Ich soll das ganze in C
programmierbar hinterlassen. Mit Assembler kriegt man das alles ganz gut
in den Griff, aber der Knackpunkt is halt der C-compiler.
Wäre es eine Möglichkeit, statt printf eine eigene Routine zu verwenden,
die dann die Rettung durchführt bevor printf gestartet wird? Prinzipiell
schon oder?
Fallen euch spontan noch andere Funktionen ein, die haufenweise Register
zuballern?
Danke für all die Infos und Mühen =)
Volker Zabe schrieb:
> die emulation von 32bit auf 8Bit-Cores
Darum geht es hier nicht.
Peter schrieb:
> Wie schon erwähnt, im Prinzip funltioniert alles wunderbar!
Wieviel Arbeit steckt da jetzt schon drin?
Peter schrieb:
> Wäre es eine Möglichkeit, statt printf eine eigene Routine zu verwenden,> die dann die Rettung durchführt bevor printf gestartet wird? Prinzipiell> schon oder?
Nicht im Kontext mit
> Ich soll das ganze in C programmierbar hinterlassen.
Das ist alles bloss Gefrickel.
D.h. irgendwie würgt man das schon hin. Aber es hat keinen Zeck. Der
Entscheider wird halt in den sauren Apfel beissen müssen.
Peter schrieb:
> Nee, kein Info, sondern E-techniker ;-)
Na super.
Wer kommt eigentlich auf solche Ideen?
> Wie schon erwähnt, im Prinzip funltioniert alles wunderbar!
Kann ich mir nicht wirklich vorstellen.
Das Attribut "wunderbar" würde ich dem nicht zugestehen.
> Ich habe> auch Routinen drin, die mir die Reg-Werte retten in die 8-Bit arrays.> Was jedoch wieder einige Rechenschritte kostet und der ganze clou an dem> system ist ja die Geschwindigkeit. Ich soll das ganze in C> programmierbar hinterlassen.
Das wirst du so nie hinkriegen.
> Wäre es eine Möglichkeit, statt printf eine eigene Routine zu verwenden,> die dann die Rettung durchführt bevor printf gestartet wird? Prinzipiell> schon oder?
Prinzipiell ja.
printf ist auch nicht sonderlich schwer zu schreiben.
Aber printf ist nur die halbe Miete.
Im Grunde musst du durch die komplette Runtime Library durch und alle
Funktionen neu schreiben (bzw. anpassen).
Wenn du dem gcc 1 oder 2 Register mittels 'register' klaust, reicht es
im Prinzip aus, die Runtime Library mit genau dieser Einstellung neu zu
compilieren um die Benutzung dieses Register exclusiv deinem Programm
(und nur deinem Programm) zu erlauben.
Wie sinnvoll das ist, ist eine andere Frage.
Den Zeitgewinn an einer Stelle erkaufst du dir damit, dass dem gcc an
anderer Stelle dafür die Register ganz schnell ausgehen und er wie wild
Register jonglieren muss.
Mal ganz davon abgesehen, dass das dann eine Runtime Library ist, die
ganz speziell für ein Programm (oder einen Programmtyp) angepasst wurde.
> Fallen euch spontan noch andere Funktionen ein, die haufenweise Register> zuballern?
Es ghet nicht nur darum, ob sie 'haufenweise' Register zuballern. Es
geht darum welche sie zuballern. Eines reicht schon, wenn es das
richtige ist.
Karl heinz Buchegger schrieb:
> Na super.> Wer kommt eigentlich auf solche Ideen?
Ganz klar. Einer der auf keinen Fall gefeuert wird, es sei denn es ist
der TO selbst.
Peter schrieb:
> Sie sind nich 32 Bit breit, sondern noch mehr. Und es sind alle 32 Stück> verbreitert worden.
Schönen Schrank auch. Und dafür nimmt man sich ausgerechnet einen
AVR als Original? Der GCC ist ursprünglich vor allem für 32-bit-
CPUs vorgesehen gewesen, das ganze Gefummel, was der AVR-GCC als
Hacks für die kleine 8-bit-CPU macht, hätte man sich hier komplett
klemmen können. Von mir aus auch 64 bits. (Weiß nicht, wie schwer
es wäre, ihn auch auf noch breitere Architekturen zu portieren.)
Karl heinz Buchegger schrieb:
> Das Attribut "wunderbar" würde ich dem nicht zugestehen.
Geht mir auch so.
Peter, tut mir echt leid für dich. Hat man dich mit Geld bedroht,
dass du dir so einen <censored>-Job hast andrehen lassen? ;-)
Lieber würde ich meine Energie in eine Portierung auf einen ATtiny10
stecken, als mir eine derartige Krücke freiwillig aufzuladen. Sorry,
wenn das jetzt hart klingt.
Volker Zabe schrieb:
> Wenn man keinen 32Bit-Core implementieren will, würde ich eine art> CO-Prozessor schreiben, der dir deine 32Bit-Berechnungen macht. Den> sprichst du über deinen Speicher-Bus an.
Das sehe ich auch als die einzige Möglichkeit an.
Wenn man einen vorhandenen Compiler benutzen will, muß man sich
sklavisch exakt, bis auf I-Tüpfelchen, 100%-ig an den original
Befehlssatz halten, da führt kein Weg dran vorbei.
Ändert man das Verhalten auch nur eines Bits, produziert der Compiler
nur noch Schrott.
Für memory mapped Zusatzfunktionen brauchst Du dann nur alle nötigen
Zugriffsfunktionen schreiben und kannst sie dann in C aufrufen.
Compiler Internas werden damit nicht gestört. Er kann weiterhin richtig
rechnen, den Speicher verwalten und Bedingungen testen.
Peter
Peter schrieb:
> Wie schon erwähnt, im Prinzip funltioniert alles wunderbar!
Das kannst Du vielleicht jemandem erzählen, der sich die Hose mit der
Kneifzange anzieht.
Schon eine simple Adreßberechnung läuft gegen die Wand, wenn die
Register nicht 8-bittig sind:
Der Compiler addiert den low-Index zu ZL und erwartet bei >255 einen
Übertrag, den er dann mit dem high-Index zu ZH addiert. Und dann springt
er an die richtige Stelle, aber bei Dir springt er in den Wald.
Peter
Auch wenn Ihr euch das nich vorstellen könnt, es klappt wirklich alles
sehr gut. Also alle Berechnungen werden brav durchgeführt mit den neuen
Regs.
Die Angepasste Breite und die neue Rechnerarchitektur ist nicht das
Problem.
Das einzige Problem ist ungewünschte Auslagerung der Regs. Wenn die
nicht wäre, wären alle Beteiligten zufrieden.
Aber lassen wir das drumherum mal kurz beiseite =)
Ich habe versucht mehr Infos über den Ablauf der printf routine zu
bekommen, aber leider finde ich da keine... im dissassembler wird ja
auch nur die subroutine gecallt und ich erhalte keinen Einblick, was da
jetzt genau passiert und eben in meinem Fall schiefgeht...
Und im Netz finde ich das ganze auch nicht in den gcc sources auch
nicht.
Was ich eben auch nicht verstehe, ist, was hier auch schon angemerkt
wurde, wieso und wobei werden die oberen Bits 0 gesetzt. Der Compiler
denkt ja mein Reg is 8Bit breit, dh er rettet doch nur 8 Bit ins SRAM
und dürfte die oberen ja gar nicht anrühren?!?
Außerdem sehe ich nicht, ob er sie überhaupt ins SRAm rettet, da ich ja
nur rcall printf sehe im Assemb... Und im restlichen Code werden die ja
gar nicht angerührt.
Naja, wahrscheinlich ist das ganze zu speziell und vielleicht auch zu
ungeschickt durchgeführt um es von außen nachvollziehen zu können. Ich
kann leider nicht genauer auf die Implementation des Ganzen eingehen, da
ich sonst riskiere Ärger zu bekommen, wegen Vertraulichkeitsgedöhns :(
Vielen Dank für alle GEdanken die Ihr euch wegen mir schon gemacht habt
=)
Und wie gesagt, ich kann nix dafür sondern muss es nur ausbaden ;-)
Viele Grüße
Wenn sich C und eurer superdupererweiterterasemblercode nicht vertragen,
dann mischt sie auch nicht.
Definiere ein Interface zwischen C und erweitertem Asembler.
Und haltet euch sauber daran.
Das Konzept bleibt aber Mist.
Peter schrieb:
> Der Compiler> denkt ja mein Reg is 8Bit breit, dh er rettet doch nur 8 Bit ins SRAM> und dürfte die oberen ja gar nicht anrühren?!?
PUSH/POP sind ja nicht die einzigen Befehle, der Compiler braucht die
Register hauptsächlich zum Rechnen!
Was passiert denn bei den Befehlen, werden z.B. immer nur die unteren
8Bit addiert und das Carry beim 8Bit gesetzt?
Du wirst ja die Befehle auf 32Bit erweitert haben und genau deswegen
knirscht es.
Solange wird Deine Änderungen im Befehlssatz nicht kennen, stochern wir
alle nur im Nebel.
Falls Du kein Genie bist, daß eben mal schnell nen Compiler aus dem
Boden stampft, wirst Du Dich damit abfinden müssen, daß nur purer
Assembler auf Deiner Kiste läuft.
Peter
Apropos Compiler: Wer sich vom GCC Quellcode erschlagen fühlt, der kann
sich mal meinen alten Bekannten ansehen, den Portable C Compiler (Google
hilft). Der ist zwar mittlerweile ca. 35 Jahre alt, aber zu meiner
Überraschung wieder aus dem Grabe auferstanden. Ist sehr viel einfacher
als GCC, optimiert aber natürlich auch nicht ganz so gut.
@ Peter:
Dein Problem läßt sich recht einfach lösen, und ich wundere mich, daß Du
nicht selbst darauf gekommen bist. Schließlich zeigt eine Diplomarbeit,
daß ihr Ersteller wissenschaftlich arbeiten kann.
Die Sourcen der GCC-Library-Funktionen sind öffentlich. Du kannst
hingehen und sie an die Bedürfnisse Deines Environments anpassen - sei
es durch Modifikation des Source-Codes, sei es durch entsprechende
Compiler-Optionen.
Bernhard
Naja, er hat's ja noch nichtmal geschafft, die avr-libc zu finden.
Wenn er sie findet, wird seine Welt aber auch nicht besser sein:
der ganze Code von stdio ist ja in C geschrieben, das heißt, wenn
da irgendwas mit seinem gehackten Professor nicht richtig läuft,
ist es doch wieder der C-Compiler, an dem er sich vergreifen muss...
Eine Möglichkeit wäre noch, alle original Atmel Befehle 100% identisch
zu implementieren und Befehle für erweiterte Register nur über noch
freie Befehlskombinationen zu machen. Ich glaube bei den
Doppelwordbefehlen ist noch viel frei.
Dann läuft der Compiler wieder richtig.
Aber die erweiterten Befehle mußt Du dann als Opcode hinschreiben, also
weder C noch Assembler.
Peter
Also es gibt ja mehrere neue Befehle, die mit den langen Regs arbeiten.
Es gibt dann eben die ein oder andere Routine, speziell die zum retten
der Regs in ein Array, hierbei werden dann 8Bit stücke nacheinander
gespeichert.
Oder eben das Laden eines Regs aus dem 8-Bit Array.
Aber wie schon erwähnt, das ganze andere Handling klappt prima.
Problematisch wird es eben ab dem Moment, in dem der Compiler die Regs
anders nutzt.
ALU usw klappen einwandfrei...
Ja die Sourcen sind öffentlich und ja ich habe sie auf dem Rechner und
mache seit Tagen nichts anderes, als diese zu durchforsten. Aber die
grundlegende Definition von beispielsweise printf besipielsweise finde
ich dort nicht. Auch die Maschinenbeschreibung vom Atmel ist ja da zu
finden mit Registeranzahl usw.. Aber wirklich was anfangen kann ich
damit nicht, bin wohl doch kein Genie ;-) Das Thema Compilerbau ist halt
eben doch sehr komplex und ich habe im moment keinen richtigen
Anfangspunkt und bin wohl auch zu doof um in den GCC Dokus die richtigen
Stellen zu finden, um den COmpiler an neue HW anzupassen.
Werde mir mal den portable anschauen, vllt bekomme ich da eher nen
durchblick, danke für den tipp =)
Ansonsten wird die Marschrichtung wohl sein, die Funktionen und Routinen
zu bestimmen, bei denen der Fehler vorkommt und diese zu ersetzen durch
andere, die zuerst noch eine sicherung der gefährdeten Register
durchführen.
Oder ich finde raus, wann es passiert, dass die eigentlich unbekannten
oberen Bits 0 gesetzt werden, denn wenn diese erhalten blieben während
einer Routine, wäre das Problem ja auch schon gelöst, egal was Ihr alle
von der Implementation haltet ;-)
Danke nochmal für alles =)
Peter schrieb:
> Aber die> grundlegende Definition von beispielsweise printf besipielsweise finde> ich dort nicht.
1
int
2
printf(constchar*fmt,...)
3
{
4
va_listap;
5
inti;
6
7
va_start(ap,fmt);
8
i=vfprintf(stdout,fmt,ap);
9
va_end(ap);
10
11
returni;
12
}
vfprintf ist dann das eigentliche Arbeitspferd der gesamten Familie,
steht in libc/stdio/vfprintf.c.
Da das aber alles in C geschrieben ist bedeutet das, wenn diese
Funktionen in deinem Prozessor Mist machen, dass dann auch jede
x-beliebige andere Funktion genauso Mist machen kann. Bis auf
einen kleinen inline-assembler-Makro, der dynamisch entscheidet,
ob ein bestimmter Zeiger als Zeiger auf den RAM oder Flash-ROM
zu interpretieren ist, ist das alles stinknormaler C-Code, wie
er auch in jeder Nutzer-Applikation auftreten könnte.
@Peter:
Das wurde auch genauso gemacht, neue Opcodes, neue Befehle usw...
Und die klappen durch die Mnemonics ja auch wunderbar in assembler, und
durch inline asms auch wunderbar in C.
Das alles ist ja nich das Problem!
@Jörg: Naja, ich hab die Libs schon gefunden und durchgesehn, aber ne
extern int printf(bla,blubb) deklaration bringt mich eben auch nich
weiter....
Naja, es wird schon irgendwie klappen...
Peter schrieb:
> @Jörg: Naja, ich hab die Libs schon gefunden und durchgesehn, ...
Offenbar nicht, denn so klein, dass dir die 714 Zeilen Implementierung
für vfprintf einfach so durch die Lappen rutschen könnten, ist sie ja
nun wirklich nicht. Aber wie schon gesagt, eben (fast) stinknormaler
C-Code, das heißt, wenn das nicht geht, bist du wieder bei "LOS!" und
darfst dir den Compiler vorknöpfen, denn es könnte dir für jede andere
Funktion genauso passieren.
Was u. U. hilft, das Problem zu triggern ist, dass printf() eine
"variadic function" ist, d. h. Argumente können (bis auf den
Formatstring) nur über den Stack übergeben werden. Du kannst das
Problem vermutlich auch mit einer variadic function innerhalb deiner
Applikation dann triggern.
Ja, tut mir leid, ich gebe zu damit begebe ich mich grad aufs
halbwissen-glatteis...
Also nochmal langsam, wenn ich von QUellen rede meine ich die Gcc 4.4.3
Quellen. Darin enthalten sind doch genau die sources, mit denen der gcc
gebaut wird?
Das ja, aber dort findest du keine Definition von printf, sondern
allenfalls die GCC-spezifische aber hier nutzlose Heurikstik, in der
Formatstring und Parametertypen gegengecheckt werden um ggf. zu warnen.
Sorry, aber mit deinen Kenntnissen bewaffnet solltest du dich auf die
Hardware konzentrieren und die Softwareseite auf dem Verhandlungsweg
lösen. Du willst die Arbeit doch bestimmt noch dieses Jahr abgeben.
Denn bevor man sich in einen C Compiler stürzt, egal welchen, sollte man
C wenigstens gut verstanden haben.
Peter schrieb:
> Oder eben das Laden eines Regs aus dem 8-Bit Array.> Aber wie schon erwähnt, das ganze andere Handling klappt prima.
Du meinst:
Du hast nur noch nicht die ganzen anderen C-Fälle gefunden, in denen es
nicht funktioniert und ein kleines Problem lauert, das nur darauf wartet
rausgelassen zu werden und zu einem großen Problem zu mutieren.
> grundlegende Definition von beispielsweise printf besipielsweise finde> ich dort nicht.
Ich würde mal erwarten, dass printf so implementiert ist
1
intprintf(constchar*fmt,...)
2
(
3
intres;
4
va_listargs;
5
6
va_start(args,fmt);
7
res=vfprintf(stdout,fmt,args);
8
va_end(args);
9
10
returnres;
11
}
Das könnte auch dein Ansatzpunkt sein, an dem du dein spezielles
Registerhandling vor und nach der eigentlichen Funktionalität einbringen
kannst.
(Die 3 Punkte sind hier übrigens nicht das Zeichen dafür, dass ich da
etwas ausgelassen habe. Die gehören da hin und müssen da sein)
Wenn du mit obiger printf-Funktion allerdings nicht klarkommst, rate ich
dir von der ganzen Sache ab. Du begibst dich da in eine Situation, in
der du nur verlieren kannst.
> Denn bevor man sich in einen C Compiler stürzt, egal welchen,> sollte man C wenigstens gut verstanden haben.
Full ACK!
Und zwar auch in den 'dunklen Ecken von C'!
Das war auf die bescheidenen Kentnisse bezogen.
Ja, printf war bisher nur ein Beispiel was schiefgehen kann. Wollte auch
nie bezweifeln, dass es bei vielen adneren genauso schiefgeht.
Deshalb war der ursprüngliche Gedanke ja, de gefährdeten Regs dem
Zugriff des Compuilers zu entziehen. ICh hatte ja hoffnung, dass das zu
machen wäre.
Aber ich sehe ja ein, dass die ganze Problematik extrem viel komplexer
ist als erhofft.
Peter schrieb:
> Deshalb war der ursprüngliche Gedanke ja, de gefährdeten Regs dem> Zugriff des Compuilers zu entziehen. ICh hatte ja hoffnung, dass das zu> machen wäre.
Wenn es sich nur um 1 oder 2 spezielle Register handeln würde, ja dann
würde das gehen. Ganz im Gegenteil: Anstatt an den vorhandenen Registern
rumzuwerken, hätte man die beiden Register als Erweiterung zu den
bestehenden gemacht, von denen der Compiler nichts weiß.
Dazu noch die Spezialbefehle, die zum Ansprechen dieser Erweiterung
notwendig sind, schön verpackt in inline-Assembler Funktionen, und im
Grunde wärs das gewesen.
Man kommt dem Compiler nicht ins Gehege (*) und muss ihn auch nicht
austricksen. Jeder tut das was er am besten kann: Der Compiler kümmert
sich um die AVR Architektur und die Assembler Funktionen bedienen die
Erweiterung.
Aber nein, statt dessen musste es ja gleich ein Rundumschlag sein (ich
weiß, du kannst nichts dafür), damit man sich nur ja richtig in die
Schei... reinreitet.
(*) Das kann man durchaus auch als Aufforderung verstehen:
"Man kommt dem Compiler nicht ins Gehege!"
Das tut man einfach nicht, denn man kann dabei nur verlieren. Compiler
sind nicht mehr die einfachen linearen Programme, die mit 2 mal schief
ansehen verstehbar sind. Jede noch so kleine Änderung kann unabsehbare
Konsequenzen nach sich ziehen.
Und es gilt immer noch das Dogma: Der Compiler hat immer recht! Immer?
Immer!
Ja, der Gedanke mit Extra-Registern drängt sich förmlich auf.
Sollte das so nich akzeptiert werden, werde ich versuchen, einfach durch
try&error kritische Funktionen zu ermitteln und diese dann an eine
Rettung der Regs knüpfen mit entsprechenden Vorschriften für potentielle
Programmierer.
Also in jedem Falle, ein herzliches Dankeschön fürs Augen öffnen und
Grenzen (auch persönliche ;-) ) aufzeigen =)
P.S.: wäre das schön, wenn es ein bindendes Registerattribut gäbe ;-)
Peter schrieb:
> P.S.: wäre das schön, wenn es ein bindendes Registerattribut gäbe ;-)
Überleg mal.
So etwas kann es im Allgemeinen nicht geben!
Dein Code ist nicht der einzige der auf der Maschine läuft. Du hast
immer noch einen gewissen Anteil an Funktionen aus der Runtime-Library
mit dabei. Die sind vorcompiliert und wissen nichts von deiner
Registerabzwackerei.
Wie KHB oben schon erwähnte gibt es im GCC über das globale asm("r2")
die Möglichkeit, ihn komplett von der Verwendung bestimmter Register
abzubringen. Allzu viele dürfen es natürlich nicht sein und es kommen
auch nicht alle in Frage.
Damit das aber funktioniert, muss der gesamte Code mit dieser
Definition des Registers frisch übersetzt werden und damit sind auch die
Bibliotheksfunktionen gemeint. Es kann dann auch nötig werden, einzelne
in Assembler implementierte Bibliotheksfunktionen daraufhin zu
überprüfen, ob sie diese Register verwenden.
Wenn man sich mit solchen Registern sehr zurückhält und nur am selten
genutzen Rand knabbert, dann werden nur wenige Bibliotheksfunktionen ein
Problem bereiten. Es kann dann helfen, das printf komplett selbst zu
implementieren und mit etwas Lust am Risiko die vorhandene Bibliothek
trotzdem für den Rest zu verwenden. Andere Problemkandidaten wären
Funktionen, die 64-Bit Integer verwenden bzw. deren Arithmetik
implementieren.
Peter schrieb:
> @Peter:> Das wurde auch genauso gemacht, neue Opcodes, neue Befehle usw...> Und die klappen durch die Mnemonics ja auch wunderbar in assembler, und> durch inline asms auch wunderbar in C.> Das alles ist ja nich das Problem!
Dann kann das Problem nur sein, daß bei der Implementierung der original
Befehle ein Fehler gemacht wurde und die Register sich nicht 8bittig
verhalten.
Dafür kann man aber nicht dem Compiler die Schuld in die Schuhe
schieben.
Da mußt Du Dir erstmal ein Testprogramm schreiben, was sämtliche
original Register-Befehle testet.
Also auch die Flagsetzung, bedingte Sprünge, indirekte Adressierung usw.
Und nicht die 16Bit Befehle vergessen (MOVW, ADIW, ..).
Das kann schon in richtig Arbeit ausarten.
Peter
Karl heinz Buchegger schrieb:
> Die sind vorcompiliert und wissen nichts von deiner> Registerabzwackerei.
Wenn man an irgendwas wie dem ABI rumschraubt ist es eigentlich
Pflicht, dass man als mindestes erstmal die run-time lib komplett
mit dem gleichen Compiler und den gleichen Compilerschrauben selbst
compiliert.
Ok, das klingt natürlich auch vernünftig..
Bitte nicht hauen, aber ..ähhm... wie würde ich das anfangen? diese
nochmal selber zu compilieren in deckung geh
Und wenn Du dann die Runtime-Lbrary neu compilierst, dann hast Du die
Möglichkeit, jede einzelne Funktion anhand des jeweiligen
Assembler-Listings auf unerwartete Registerbenutzung u.ä.
Inkompatibilitäten mit Deinem Prozessor zu prüfen. Du besitzt dann die
Freiheit, diese Funktionen mit angepaßten Compiler-Optionen (z.B. -O0)
zu compilieren bzw. nicht erforderliche Teile (z.B. Float-Unterstützung
bei der ..printf-Familie) zu eliminieren. Das liegt alles in Deiner
Hand.
Bernhard
Bernhard R. schrieb:
> Und wenn Du dann die Runtime-Lbrary neu compilierst, dann hast Du die> Möglichkeit, jede einzelne Funktion anhand des jeweiligen> Assembler-Listings auf unerwartete Registerbenutzung u.ä.> Inkompatibilitäten mit Deinem Prozessor zu prüfen. Du besitzt dann die> Freiheit, diese Funktionen mit angepaßten Compiler-Optionen (z.B. -O0)> zu compilieren bzw. nicht erforderliche Teile (z.B. Float-Unterstützung> bei der ..printf-Familie) zu eliminieren. Das liegt alles in Deiner> Hand.
Und wehe, deine Kapazunder kommen auf die Idee, in einem halben Jahr auf
die neueste Version upzugraden (sowohl Compiler als auch Runtime
Library).
Dann geht das ganze Spielchen von vorne los :-)
Also am besten jede Modifikation dokumentieren, warum sie notwendig war
und was die Modifikation bewirkt.
Auf die Assembler Anteile in der Runtime Library nicht vergessen (wurde
weiter oben schon einmal erwähnt)
Letzter Hinweis:
Hier ( http://www.nongnu.org/avr-libc/ ) ist die Runtime-Library für die
AVR-Portierung des GCC. Es ist alles vorhanden: C-Files, H-Files,
Makefiles, Dokumentation.
Bernhard
Ich vermisse in den letzten Postings die Ironie-Tags.
Wenn das wirklich so einfach ist, könnt ich mir ja mal schnell über
Mittag nen WINAVR ohne das R0,R1-Geraffel basteln.
Peter
Ok, super =)
Dann hab ich ja jetz erstmal ordentlich was zu tun =)
Sorry, wegen der Build-Frage war mir nich ganz sicher, ob ich dafür auch
die ganzen schritte über Unix-Umgebungen gehen muss, aber es gibt ja zum
glück das avr-libc manual =)
Also ich kann nur noch einmal betonen:
Vielen, vielen Dank für den ganzen Input und eure ganze Nachsicht mit
Laien =)
Viele Grüße
vllt melde ich mich ja nochmal wenn alles geklappt hat, oder ihr als
Zeugen auftreten müsst, wenn ich ne schlechte Note kriegen soll =)
> Wenn das wirklich so einfach ist, könnt ich mir ja mal schnell über> Mittag nen WINAVR ohne das R0,R1-Geraffel basteln.
A.K. hat schon geschrieben, dass R0,R1 nicht geht. Und bei den
Registern, die zum Argumentpassing abegstellt sind, wirds wohl auch
Schwierigkeiten geben (aus dem Bauch heraus geschätzt).
Aber im Grunde kann man das bei anderen Registern schon machen.
Die Frage ist halt immer: wie sinnvoll ist es, dem Registerallokator
seine Arbeitsgrundlage zu entziehen. Das ist ungefähr so sinnvoll, wie
einem Klavierbauer zu sagen, er möge alle Tasten ausser C,D,E,F,G,A,H,C
weglassen, weil was anderes braucht man nicht für 'Hänschen klein'. Will
man nur 'Hänschen klein' spielen und andere Stücke, die mit diesen Noten
auskommen, dann ist das perfekt. Aber wehe, wenn nicht.
Irgendwann bezahlt man dafür. Und dann hat man die paradoxe Situation,
dass diese vermeintliche Beschleunigung eine Verschlechterung darstellt,
weil der Geschwindigkeitsvorteil an einer Stelle durch massive
Verschlechterung an anderen Stellen (durch die dort fehlenden Register)
mehr als aufgefressen wird.
Ausserdem muss man sich immer überlegen, ob es schlau es ist, eine
speziell privat angepasste Runtime Library im Projekt zu haben. Wenns
nicht anders geht, ist es ja ok. Nur sollte man auch die Konsequenzen
für die Zukunft berücksichtigen.
Karl heinz Buchegger schrieb:
>> Wenn das wirklich so einfach ist, könnt ich mir ja mal schnell über>> Mittag nen WINAVR ohne das R0,R1-Geraffel basteln.>> A.K. hat schon geschrieben, dass R0,R1 nicht geht.
Wobei ich das noch nicht so absolut sehen würde. Für eine rein
private Version geht das sicher, sie ist eben nur komplett ABI-
inkompatibel zu allem anderen, und man muss jedes Stück Assembler-
code (einschließlich inline asm) einzeln begutachten.
Ob man komplett ohne _zero_reg_ auskommt, weiß ich nicht, aber
auf ein anderes Register umlegen müsste man das wirklich können.
Eine Mittagspause wird nicht reichen, ein Wochenende schon, wenn
man ungefähr weiß, wo man was suchen will, und wenn man wenigstens
die Buildumgebung schon hat.
Eine Frage hab ich dann aber doch noch:
Wenn ich alles neubaue, an welcher Stelle werden "reserviere" ich die
globalen Reg-variablen? Soll ich dann einfach die eigene .h mit meinen
inline assembler routinen usw, zu den runtime-libs inzufügen und dann
das ganze builden?
Jörg Wunsch schrieb:
>> A.K. hat schon geschrieben, dass R0,R1 nicht geht.>> Wobei ich das noch nicht so absolut sehen würde.
Ich bezog mich dabei auf die vorher beschriebene Variante asm("r0") zur
Reservierung eines Registers.
R0,R1 komplett frei zu bekommen ist sicherlich möglich, erfordert aber
signifikante Änderungen am maschinenabhängigen Teil des Compilers und in
Assembler-Routinen der Lib. Zudem müssen denn Multiplikationen entweder
mit abgeschalteten Interrupts oder ohne die entsprechenden Befehle
ausgeführt werden.
Peter schrieb:
> Eine Frage hab ich dann aber doch noch:> Wenn ich alles neubaue, an welcher Stelle werden "reserviere" ich die> globalen Reg-variablen? Soll ich dann einfach die eigene .h mit meinen> inline assembler routinen usw, zu den runtime-libs inzufügen und dann> das ganze builden?
Mach dir ein Header File, in welches die extern-'Reservierung' (und nur
diese) hineinkommt.
Diesen Header includierst du dann quer durch die Bank in allen *.c
Files, damit auch alle wissen, das diese Register tabu sind.
Ich kenne jetzt den Aufbau der Runtime Lib nicht. Eventuell gibt es dort
ja schon ein Header File, welches wirklich überall includiert wird. Das
wäre dann ein guter Platz.
Peter schrieb:
> Wenn ich alles neubaue, an welcher Stelle werden "reserviere" ich die> globalen Reg-variablen? Soll ich dann einfach die eigene .h mit meinen> inline assembler routinen usw, zu den runtime-libs inzufügen und dann> das ganze builden?
Du benötigst eine zentrale .h mit deinen register asm("rX") Statements
drin, die in allen C-Quellcodes der Lib included wird.
Sehr viele Register sollten das aber nicht sein, sonst besteht die
Gefahr, dass der Compiler öfter mal nicht weiter weiss und verzweifelt
die Segel streicht, insbesondere wenn registerfressende 64-Bit Integers
verwendet werden.
A. K. schrieb:
> R0,R1 komplett frei zu bekommen ist sicherlich möglich, erfordert aber> signifikante Änderungen am maschinenabhängigen Teil des Compilers
Das ist in 1...2 Stunden erledigt. Wie gesagt, in der Annahme, dass
man stur r0/r1 durch r2/r3 ersetzt. Das sind einige wenige Stellen,
das meiste dabei ist relativ zentral definiert.
> und in> Assembler-Routinen der Lib.
Das ist der größere Aufwand, das würde den restlichen ersten Tag
des genannten Wochenendes in Beschlag nehmen. ;-)
> Zudem müssen denn Multiplikationen entweder> mit abgeschalteten Interrupts oder ohne die entsprechenden Befehle> ausgeführt werden.
Nein, man muss eigentlich dem Compiler nur beibringen, dass die
Multiplikationsbefehle diese beiden Register benötigen, sodass eine
ISR sie als geändert betrachten muss, wenn solche Befehle benutzt
werden. Entsprechend müssen sie dann nur noch bei Bedarf gesichert
werden, wie alle anderen Register, die nicht immer gesichert werden
müssen. Dem Compiler das beizubringen wäre der zweite Tag des
Wochenendes. :-)
Mein Posting sollte auch nur ironisch gemeint sein:
Beitrag "Re: Registerattribut"
Die R0,R1 Sache hat nix mit dem "Peter (Gast)" zu tun.
Vergeßt es einfach.
Peter
P.S.:
Immerhin interessant, daß es für den Kundigen in 2 Tagen zu schaffen
wäre.
Jörg Wunsch schrieb:
> Nein, man muss eigentlich dem Compiler nur beibringen, dass die> Multiplikationsbefehle diese beiden Register benötigen, sodass eine> ISR sie als geändert betrachten muss, wenn solche Befehle benutzt> werden.
Vorausgesetzt, man verwendet in ISRs keine Funktionen, die auf die
betroffenen Registervariablen angewiesen sind. Denn deren Werte sind
dann unauffindbar irgendwo im Stack versteckt.
Peter Dannegger schrieb:
> Immerhin interessant, daß es für den Kundigen in 2 Tagen zu schaffen> wäre.
Für die erste Alpha-Version könnte das passen. Aber du bist wohl lange
genug in der Branche um zu wissen, was man mit ersten optimistischen
Aufwandseinschätzungen tun muss ;-).
A. K. schrieb:
> Vorausgesetzt, man verwendet in ISRs keine Funktionen, die auf die> betroffenen Registervariablen angewiesen sind.
Häh? Hier verstehe ich dich nicht mehr...
Nimm an, dein Hauptprogramm benutzt einen MUL-Befehl, das Ergebnis
steht in r0/r1. Jetzt kommt ein Interrupt rein. Die ISR benutzt
selbst auch MUL und rettet daher r0/r1 (was sie sonst nun nicht
mehr müsste). Danach hat sie das normale Ergebnis vorliegen, aber
was soll sie jetzt mit den "betroffenen Registervariablen" wollen
(welchen überhaupt)?
Wenn die ISR zurückkehrt restauriert sie r0/r1, und das Hauptprogramm
sammelt aus diesen dann das Ergebnis der vorangegangenen Multi-
plikation auf.
Die ISR muss natürlich immer noch r2 retten (scratch register),
allerdings darf sie nun davon ausgehen, dass niemand mehr jemals
die 0 aus r3 entfernt, daher muss sie das weder retten noch neu
ausnullen. Sollte eine Assemblerfunktion jemals r3 benutzen
wollen, ist sie natürlich dafür verantwortlich, für diese Zeit
die Interrupts zu sperren.
Jörg Wunsch schrieb:
> Häh? Hier verstehe ich dich nicht mehr...
Es ging um globale Variablen der Form:
register uint8_t status asm("r0");
Eine Multiplikation muss R0 verwenden, wird es also vorher sichern. Wenn
nun eine ISR auf "status" zugreifen will, aber grad eine Multiplikation
unterbrochen hat, dann war's das. Nix geht mehr. Der Wert liegt irgendwo
im Stack oder einem beliebigen anderen Register.
A. K. schrieb:
>> Häh? Hier verstehe ich dich nicht mehr...>> Es ging um globale Variablen der Form:> register uint8_t status asm("r0");
Ja, es ist ja wohl klar, dass dann r0 bis r3 komplett tabu sind für
eine explizite Registerzuweisung. r0 und r1 wegen der Multiplikation,
r2 und r3 wegen ihrer Sonderbedeutung.
Hm, also habe die ganze Build-Umgebung..
Hat alles soweit gut funktioniert.
Wenn ich jetz allerdings avr-libc builden will mit der angegebenen
congigure anweisung, bekome ich einen:
1
tee: invalid option -- c
2
Try `tee --help' for more information.
fehler in msys... google hilft leider nicht...
configure:
Peter schrieb:
> tee: invalid option -- c> 2>&1 | tee $package-configure.log
Wo auch immer du das her genommen hast... Die Variable "package"
ist bei dir einfach leer, sodass das da oben zu
2>&1 | tee -configure.log
erweitert. Damit würdest du dem tee-Kommando die Optionen -c,
-o, -n, -f, -i, -g, -u, -r, -e, -., -l, -o und -g übergeben
wollen, wovon er sich bereits bei der ersten beschwert. ;-)
Schreib einfach: »... | tee logfile.txt« (Dein Windows würde mit dem
Suffix .log ohnehin nichts anfangen können, denn Windows hat sich
ja mit sowas ziemlich eigen.)
> achso, mein OS is leider vista premium
Nein, dein OS ist Windows, die Version ist Vista Premium. Ich
sage dir doch auch nicht, dass mein OS 8.0-stable ist und impliziere
dass du weißt, dass damit ein FreeBSD gemeint ist. ;-)
Ach tut mir leid, aber ich bin zu unfähig! Weder Google, noch Su-Fu
haben geholfen, deswegen nerv ich euch schon wieder :-(
Also habe mich genau an die Anleitung von
http://www.nongnu.org/avr-libc/user-manual/install_tools.html
gehalten.
Die Tools haben ja dann sich auch installen lassen.
Configuren von avr-libc hat dann auch funktioniert, dank Jörg ;-)
Aber wenn ich dann den make install Befehl durchführe passiert
folgendes:
Ach Mann, ich könnte heulen...
Also wenn ich make install mache von avr-libc, dann passiert folgendes:
Er legt brav los und maked. Dann irgendwann beim 1500 make schritt,
kommt ne windows fehlermeldung, dass der arbeitsspeciher belegt wäre,
dann macht make trotzdem im schneckentempo weiter und dann brichts
irgendwann ab, wegen ner Fehlermeldung, die irgednwas mit
sync_with_child zu tun hat und auch irgendwas mit Mem.
Wenn ich im Taskmanager Prozesse anschaue, sehe ich dass wohl jeder make
und hs.exe schritt nen eigenen Prozess hat, mit ca 1MB Speicher. So
werden dann wohl schnell die 4GB ram zugemüllt.
Wie gesagt, OS is Windows(!) Version Vista Premium 32-bit...
Peter schrieb:
> Wenn ich im Taskmanager Prozesse anschaue, sehe ich dass wohl jeder make> und hs.exe schritt nen eigenen Prozess hat, mit ca 1MB Speicher. So> werden dann wohl schnell die 4GB ram zugemüllt.
Da kannst du nur mal Eric Weddington fragen, wie er das dann schafft.
Dass Windows nicht sonderlich effizient im Anlegen neuer Prozesse
ist, ist bekannt (unter unixoiden Systemen ist das Anlegen eines
Threads praktisch genauso teuer wie das Anlegen eines Prozesses,
beide werden intern sehr ähnlich gehandhabt). Aber dass man deshalb
gar nicht mehr compilieren kann, wundert mich schon, auch wenn die
avr-libc zugegebenermaßen ein ziemliches Mammutprojekt ist, was das
Compilieren angeht.
Kann natürlich sein, dass Eric von Windows Vista einfach mal die
Finger gelassen hat und bei XP als Version geblieben ist.
Du könntest noch versuchen, verzeichnisweise zu installieren,
wobei du mindestens die Verzeichnisse "include", "libc" und "libm"
installieren musst (also jeweils mit cd da hinein wechseln und dann
dort »make install« ausführen).