Hallo. Ich möchte aus Geschwindigkeitsgründen eine globale Variable einem festen Register zuweisen. d.h. dass die variable uint8_t x nicht im RAM gespeichert wird, sondern im z. B. nur im Register R16. Dadurch will ich vermeiden, dass am Anfang einer Interruptroutine erst die ganzen Register mit push und pop gesichert und dann die Variablen aus dem RAM gelesen werden müssen. Wie kann ich das dem avrgcc mitteilen? oder geht das gar nicht? Danke Bernhard
aus gcc.pdf You can define a global register variable in GNU C like this: register int *foo asm ("a5");
Für eine globale Variable wird das nicht gehen. Selbst wenn avr-gcc die Möglichkeit hätte, würde das bedeuten, dass Du die ganze C-Library neu übersetzen musst, denn die kann ja nichts davon wissen.
Lass es besser bleiben. Im Normalfall ist es keine so gute Idee, dem Compiler da ins Handwerk zu pfuschen. Wie Hazeh schon geschrieben hat, kann das mächtig ins Auge gehen, wenn du Funktionen aus der C-Runtime Library benutzt. Und dadurch, dass du an dieser Stelle dem Compiler ein Register nimmst, kriegt der Compiler an anderen Stellen unter Umständen kräftige Probleme, weil ihm dann genau dieses Register fehlt. Aus diesem Grund ignorieren praktisch alle Compiler seit langem das in C vorgesehene 'register' Schlüsselwort und verlassen sich lieber auf ihre eigene Datenflussanalyse als darauf, dass der Programmierer den Überblick hat, wieviele und welche Register vorhanden und frei sind, um dort oft benutzte Werte abzulegen.
Leider muss ich es aber machen, da meine ISR innerhalb von etwa 50 Taktzyklen reagieren muss und ein bisschen was berechnen muss und da komme ich mit den ganzen push und pop nicht hin.
Bernhard Mayer schrieb: > Leider muss ich es aber machen, da meine ISR innerhalb von etwa 50 > Taktzyklen reagieren muss und ein bisschen was berechnen muss und da > komme ich mit den ganzen push und pop nicht hin. Wie wäre es den dann mit einer "naked" ISR und inline ASM?
Läubi .. schrieb: > Wie wäre es den dann mit einer "naked" ISR und inline ASM? Sofern man nicht schon mit Inline-ASM vertraut ist, ist eine separate Asm-Datei die bessere Wahl, da einfacher. @ Bernhard Mayer: > komme ich mit den ganzen push und pop nicht hin. Du rufst doch nicht etwa in der ISR eine andere Funktion auf, oder?
1 | // direktzuweisung von variablen zu registern
|
2 | register volatile uint8_t mask0_r10 asm ("r10"); |
man kann da ruhig dem kompiler ins handwerk pfuschen ... ich hab 8 Register auf diese weise belegt und keinerlei probleme damit.
Nochmal, das das geht bezweifelt keiner. Aber: Du musst dann auch die C-Runtime Library mit dieser neuen Einschränkung neu kompilieren. Ansonsten kann beim ersten Aufruf einer Standard-Funktion alles mögliche passieren ... ... WEIL DIESE LIBRARY FUNKTIONEN NICHTS DAVON WISSEN, DASS EIN REGISTER ABGEZWACKT WURDE Welcher Teil dieses Satzes ist unverständlich?
habe ich schon mehrfach ohne Probleme gemacht...z.B. hier Beitrag "Klingel mit 100 Melodien - last minute Weihnachtsgeschenk"
Ok, dann bitte mal konkret - AVRGCC - wo gibt es denn da die Kollisionen mit http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_regbind Welche Funktionen aus der C-Runtime benutzen denn diese Register?
egberto schrieb:
> habe ich schon mehrfach ohne Probleme gemacht...z.B. hier
Du benutzt dort ja auch keinerlei "echte" Funktion aus der Lib.
Von
1 | ich habe keine Probleme damit |
zu
1 | kann man so machen |
ist und bleibt eine unzulässiger Schlussfolgerung.
egberto schrieb:
> Welche Funktionen aus der C-Runtime benutzen denn diese Register?
Disassembliere die Lib, und schaue nach. Vielleicht keine. Aber selbst
dann kann es mit der nächsten Version der Lib schon ganz anders
aussehen.
egberto schrieb:
> Welche Funktionen aus der C-Runtime benutzen denn diese Register?
Ich denke nicht, dass man als Programmierer sich darüber Gedanken machen
müsste / sollte. Denn:
* Wird im Compiler der Optimizer verändert, kann sich alles umdrehen.
* Macht man im Applikationsprogramm zu Debug-Zwecken nur einen
simplen itoa rein, kann es zu dubiosen Fehlern kommen.
(Selbiges mit allen anderen Library Funktionen)
Die Frage lautet: Soll man sich als Programmierer wirklich solche schwer
zu überschauenden Abhängigkeiten schaffen?
Wenn die Not groß ist, kann ich das vielleicht noch akzeptieren. Aber
selbst dann würde ich alles daran setzen, keine speziell angepasste
Runtime-Library zu benötigen. Das sind Zeitbomben.
Muss ja auch gar nicht die Runtime Library sein. Der nächste, der deine Klingel einsetzen will und sich als Zusatz ein LCD (zb mit den bewährten Fleury Funktionen) zusätzlich drann bauen will, wird sich schön bei dir bedanken, wenn er nach Stunden draufkommt, dass du ein paar Variablen fix in Register gelegt hast und er jetzt Register-Clashes mit zb den LCD-Funktionen hat. Da kommt er nicht gleich drauf, nein, das dauert lange, bis er merkt, dass Variablen 'seltsamerweise' magisch ihre Werte auf unverhersehbare Weise ändern.
Ok, ich spreche auch nur für den Hobbybereich! Ich habe obiges Manual quasi als "offiziell" angesehen - soll heißen, für die aktuelle Compilerversion gilt das geschriebene oder? Diese Register wurden auch nur wegen platzknappheit verwendet - schön, wenn man noch solche Reserven hat. Und wer zusätzlich noch Code der gleichen "Machart" verwendet, muß eben sehr genau hinschauen... Grüße, egberto
egberto schrieb: > Ich habe obiges Manual quasi als "offiziell" angesehen - soll heißen, > für die aktuelle Compilerversion gilt das geschriebene oder? Ja. Da steht aber auch nicht, dass man das gefahrlos machen kann.
1 | Typically, it should be safe to use r2 through r7 that way. |
Man beachte das "typically" und das "should". Und vor allem beachte man diesen Satz dort:
1 | Extreme care should be taken that the entire application is compiled |
2 | with a consistent set of register-allocated variables, including possibly |
3 | used library functions. |
Die GPIORs sind übrigens eine gute Alternative zu Registern. Leider gibts viel zu wenige davon :-)
egberto schrieb: > Ok, ich spreche auch nur für den Hobbybereich! Gerade dort würde ich das nicht machen. Professionals dokumentieren so was nämlich ausführlichst und weisen darauf hin. Hobbyprogrammierer tun das nicht. > Ich habe obiges Manual quasi als "offiziell" angesehen - soll heißen, > für die aktuelle Compilerversion gilt das geschriebene oder? Das Manual ist auch ok. Aber auch dort steht ja explizit (wenn auch nicht sehr deutlich) drinnen, dass besondere Vorsicht geboten ist. > Diese Register wurden auch nur wegen platzknappheit verwendet - schön, > wenn man noch solche Reserven hat. Schon klar. Bei dir macht dieser Unterschied gerade die paar Bytes aus, damit noch alles in den Tiny reinpasst. Mit einer grossen Warnung, die auch ein Blinder aus 3 Meter Entfernung noch ertasten kann, ist das ok. > Und wer zusätzlich noch Code der gleichen "Machart" verwendet, Muss noch nicht einmal 'die gleiche Machart sein'. Stinknormaler, üblicher C-Code aus einer anderen Quelle, der sich an die üblichen Regeln hält, reicht bereits. > muß eben > sehr genau hinschauen... Genau darum gehts. Die Praxis zeigt, dass 'dann muss man eben genau schauen', eine regelmässige Zeitbombe ist. In einem halben Jahr weiß das nämlich kein Mensch mehr.
Ich habe allerdings noch nie Probleme mit r2 bis r6 gehabt. Bei keiner Compiler/Stdlib Version. Einfach machen und die Bedenkenträger ignorieren. Zur Doku schreibst du eine kleine Warnung zur Erinnerung und dann die aktuell verwendete Compiler/stdlibversion in den Quältext - und gut is.
man kann auch register unbenutzter µC funktionen für solche sachen benutzen. Bei denen kommt der Kompiler nicht auf die Idee, sie verwenden zu wollen und die haben außerdem noch den Vorteil, dass sie bit-adressierbar sind. Dh, man kann zB, 8 seperate Flags unterbringen, was nützlich ist um aus der Intteruptroutine an die Hauptschleife Flags zu übermitteln, ohne das jedes mal erst der Ram gelsesn werden muss (oder zusätzlich noch die Bits ausmaskiert werden müssen). Dazu bieten sich zB folgende Register an: EPPROm Daten+Adress-Register, so lange man den eeprom nicht braucht. timer-compare register von unbenutzten Timern. timer-counter register von unbenutzten Timern. Daten- und Datenratenregister der seriellen schnittstellen (USI,UART, SPI, TWI), solange man die nicht braucht.
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.